aboutsummaryrefslogtreecommitdiff
path: root/tests/zfs-tests/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests/zfs-tests/tests')
-rw-r--r--tests/zfs-tests/tests/Makefile.am1
-rw-r--r--tests/zfs-tests/tests/functional/Makefile.am90
-rw-r--r--tests/zfs-tests/tests/functional/acl/Makefile.am6
-rw-r--r--tests/zfs-tests/tests/functional/acl/acl.cfg64
-rw-r--r--tests/zfs-tests/tests/functional/acl/acl_common.kshlib630
-rw-r--r--tests/zfs-tests/tests/functional/acl/posix/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/cleanup.ksh33
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/posix_001_pos.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/posix_002_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/posix_003_pos.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/acl/posix/setup.ksh52
-rw-r--r--tests/zfs-tests/tests/functional/alloc_class/Makefile.am21
-rw-r--r--tests/zfs-tests/tests/functional/alloc_class/alloc_class.cfg31
-rw-r--r--tests/zfs-tests/tests/functional/alloc_class/alloc_class.kshlib67
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_001_pos.ksh43
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_004_pos.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_005_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_006_pos.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_007_pos.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_008_pos.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh50
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_012_pos.ksh122
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/alloc_class_013_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/cleanup.ksh27
-rwxr-xr-xtests/zfs-tests/tests/functional/alloc_class/setup.ksh26
-rw-r--r--tests/zfs-tests/tests/functional/arc/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/arcstats_runtime_tuning.ksh46
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/cleanup.ksh29
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/dbufstats_001_pos.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/dbufstats_002_pos.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/dbufstats_003_pos.ksh43
-rwxr-xr-xtests/zfs-tests/tests/functional/arc/setup.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/atime/Makefile.am14
-rw-r--r--tests/zfs-tests/tests/functional/atime/atime.cfg30
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/atime_001_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/atime_002_neg.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/atime_003_pos.ksh70
-rw-r--r--tests/zfs-tests/tests/functional/atime/atime_common.kshlib102
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/root_atime_off.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/root_atime_on.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/root_relatime_on.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/atime/setup.ksh31
-rw-r--r--tests/zfs-tests/tests/functional/bootfs/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_001_pos.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_002_neg.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_003_pos.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_004_neg.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_006_pos.ksh156
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_007_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/bootfs_008_pos.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/bootfs/setup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/btree/Makefile.am20
-rwxr-xr-xtests/zfs-tests/tests/functional/btree/btree_negative.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/btree/btree_positive.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/cache/Makefile.am20
-rw-r--r--tests/zfs-tests/tests/functional/cache/cache.cfg71
-rw-r--r--tests/zfs-tests/tests/functional/cache/cache.kshlib154
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_001_pos.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_002_pos.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_003_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_004_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_005_neg.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_006_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_007_neg.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_008_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_009_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_010_pos.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_011_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cache_012_pos.ksh110
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/cleanup.ksh46
-rwxr-xr-xtests/zfs-tests/tests/functional/cache/setup.ksh41
-rw-r--r--tests/zfs-tests/tests/functional/cachefile/Makefile.am12
-rw-r--r--tests/zfs-tests/tests/functional/cachefile/cachefile.cfg37
-rw-r--r--tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib46
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cachefile_001_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cachefile_002_pos.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cachefile_003_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cachefile/setup.ksh46
-rw-r--r--tests/zfs-tests/tests/functional/casenorm/Makefile.am25
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/case_all_values.ksh42
-rw-r--r--tests/zfs-tests/tests/functional/casenorm/casenorm.cfg35
-rw-r--r--tests/zfs-tests/tests/functional/casenorm/casenorm.kshlib131
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/cleanup.ksh20
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/insensitive_formd_delete.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/insensitive_formd_lookup.ksh51
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/insensitive_none_delete.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/insensitive_none_lookup.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/mixed_create_failure.ksh136
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/mixed_formd_delete.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/mixed_formd_lookup.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/mixed_formd_lookup_ci.ksh51
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/mixed_none_delete.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/mixed_none_lookup.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/mixed_none_lookup_ci.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/norm_all_values.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/sensitive_formd_delete.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/sensitive_formd_lookup.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/sensitive_none_delete.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/sensitive_none_lookup.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/casenorm/setup.ksh27
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/Makefile.am6
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib230
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/Makefile.am46
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/cleanup.ksh19
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/setup.ksh21
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.out1
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.zcp25
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.err4
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.zcp16
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.exists.ksh45
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.exists.zcp26
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_illegal.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_overflow.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_neg.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_pos.ksh42
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.out1
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.zcp280
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_base.lua469
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_coroutine.lua362
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_strings.lua241
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_table.lua252
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.libraries.ksh31
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.memory_limit.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.zcp770
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.ksh23
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.zcp71
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.nvlist_to_lua.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive.zcp31
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_neg.ksh24
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_pos.ksh23
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_large.ksh54
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_large.zcp24
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_neg.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_pos.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.ksh31
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.zcp21
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.err18
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.ksh33
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.zcp20
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.ksh55
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.zcp22
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am53
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/cleanup.ksh22
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/setup.ksh25
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh45
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp32
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.ksh43
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp26
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_fs.ksh45
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_snap.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_count_and_limit.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.ksh41
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.out4
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.zcp77
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_mountpoint.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_neg.ksh43
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.ksh52
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.out5
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.zcp101
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.ksh45
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.out5
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.zcp73
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_type.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_userquota.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh39
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_bookmarks.ksh120
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children.ksh125
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_clones.ksh116
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_holds.ksh121
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_snapshots.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_system_props.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_user_props.ksh147
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.parse_args_neg.ksh50
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.ksh55
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.zcp23
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_multiple.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple.ksh47
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh49
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.set_props.ksh39
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.set_props.zcp109
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_destroy.ksh39
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_destroy.zcp24
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_neg.ksh45
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_neg.zcp35
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_recursive.ksh61
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_recursive.zcp28
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_simple.ksh40
-rw-r--r--tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_simple.zcp26
-rwxr-xr-xtests/zfs-tests/tests/functional/channel_program/synctask_core/tst.terminate_by_signal.ksh98
-rw-r--r--tests/zfs-tests/tests/functional/chattr/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/chattr/chattr_001_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/chattr/chattr_002_neg.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/chattr/cleanup.ksh37
-rwxr-xr-xtests/zfs-tests/tests/functional/chattr/setup.ksh56
-rw-r--r--tests/zfs-tests/tests/functional/checksum/.gitignore4
-rw-r--r--tests/zfs-tests/tests/functional/checksum/Makefile.am32
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/cleanup.ksh38
-rw-r--r--tests/zfs-tests/tests/functional/checksum/default.cfg36
-rw-r--r--tests/zfs-tests/tests/functional/checksum/edonr_test.c218
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/run_edonr_test.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/run_sha2_test.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/run_skein_test.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/checksum/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/checksum/sha2_test.c250
-rw-r--r--tests/zfs-tests/tests/functional/checksum/skein_test.c340
-rw-r--r--tests/zfs-tests/tests/functional/clean_mirror/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_pos.ksh53
-rw-r--r--tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib83
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh41
-rw-r--r--tests/zfs-tests/tests/functional/clean_mirror/default.cfg37
-rwxr-xr-xtests/zfs-tests/tests/functional/clean_mirror/setup.ksh41
-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
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/Makefile.am6
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/misc/Makefile.am52
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh51
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg123
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/setup.ksh161
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zdb_001_neg.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_001_neg.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_neg.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_neg.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_get_001_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_neg.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_neg.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_neg.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_set_001_neg.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_001_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_neg.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_neg.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_001_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_neg.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_neg.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_neg.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_neg.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_neg.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_neg.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_neg.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_neg.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_neg.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_neg.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_neg.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_001_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/misc/zpool_wait_privilege.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/zfs_list/Makefile.am14
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/cleanup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/setup.ksh70
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.cfg35
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib118
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_001_pos.ksh116
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_pos.ksh176
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_003_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_neg.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_007_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.ksh56
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/zpool_iostat/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/setup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_neg.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh76
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/zpool_list/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_list/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_list/setup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_001_pos.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_neg.ksh57
-rw-r--r--tests/zfs-tests/tests/functional/cli_user/zpool_status/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/setup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_disable.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_003_pos.ksh76
-rw-r--r--tests/zfs-tests/tests/functional/compression/Makefile.am15
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/cleanup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/compression/compress.cfg33
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_001_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_002_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_003_pos.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/compress_004_pos.ksh140
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/l2arc_compressed_arc.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/l2arc_compressed_arc_disabled.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/l2arc_encrypted.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/l2arc_encrypted_no_compressed_arc.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/compression/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/cp_files/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/cp_files/Makefile.am13
-rwxr-xr-xtests/zfs-tests/tests/functional/cp_files/cleanup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/cp_files/cp_files.c58
-rwxr-xr-xtests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/cp_files/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/ctime/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/ctime/Makefile.am13
-rwxr-xr-xtests/zfs-tests/tests/functional/ctime/cleanup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/ctime/ctime.c376
-rwxr-xr-xtests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/ctime/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/deadman/Makefile.am7
-rw-r--r--tests/zfs-tests/tests/functional/deadman/deadman.cfg32
-rwxr-xr-xtests/zfs-tests/tests/functional/deadman/deadman_sync.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/deadman/deadman_zio.ksh113
-rw-r--r--tests/zfs-tests/tests/functional/delegate/Makefile.am28
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/cleanup.ksh54
-rw-r--r--tests/zfs-tests/tests/functional/delegate/delegate.cfg72
-rw-r--r--tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib1713
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/setup.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_001_pos.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_002_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_003_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_004_pos.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_005_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_007_pos.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_008_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_009_neg.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh194
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_011_neg.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_001_pos.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_002_pos.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_003_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_004_pos.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_005_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_006_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_007_neg.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/delegate/zfs_unallow_008_neg.ksh84
-rw-r--r--tests/zfs-tests/tests/functional/devices/Makefile.am11
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/cleanup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/devices/devices.cfg32
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/devices_001_pos.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/devices_002_neg.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/devices_003_pos.ksh49
-rw-r--r--tests/zfs-tests/tests/functional/devices/devices_common.kshlib119
-rwxr-xr-xtests/zfs-tests/tests/functional/devices/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/events/Makefile.am11
-rwxr-xr-xtests/zfs-tests/tests/functional/events/cleanup.ksh31
-rw-r--r--tests/zfs-tests/tests/functional/events/events.cfg38
-rwxr-xr-xtests/zfs-tests/tests/functional/events/events_001_pos.ksh153
-rwxr-xr-xtests/zfs-tests/tests/functional/events/events_002_pos.ksh103
-rw-r--r--tests/zfs-tests/tests/functional/events/events_common.kshlib130
-rwxr-xr-xtests/zfs-tests/tests/functional/events/setup.ksh33
-rwxr-xr-xtests/zfs-tests/tests/functional/events/zed_rc_filter.ksh104
-rw-r--r--tests/zfs-tests/tests/functional/exec/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/exec/Makefile.am9
-rwxr-xr-xtests/zfs-tests/tests/functional/exec/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/exec/exec_001_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/exec/exec_002_neg.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/exec/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/fallocate/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/cleanup.ksh27
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/fallocate/setup.ksh29
-rw-r--r--tests/zfs-tests/tests/functional/fault/Makefile.am19
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh191
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_online_001_pos.ksh155
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_spare_001_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_spare_002_pos.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_spare_ashift.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_spare_multiple.ksh155
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/auto_spare_shared.ksh119
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/cleanup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/decompress_fault.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/decrypt_fault.ksh58
-rw-r--r--tests/zfs-tests/tests/functional/fault/fault.cfg55
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/scrub_after_resilver.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/setup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/fault/zpool_status_-s.ksh77
-rw-r--r--tests/zfs-tests/tests/functional/features/Makefile.am3
-rw-r--r--tests/zfs-tests/tests/functional/features/async_destroy/Makefile.am5
-rwxr-xr-xtests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_pos.ksh102
-rwxr-xr-xtests/zfs-tests/tests/functional/features/async_destroy/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/features/async_destroy/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/features/large_dnode/Makefile.am13
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_pos.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_pos.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_003_pos.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_neg.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_pos.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_neg.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/features/large_dnode/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/grow/Makefile.am7
-rw-r--r--tests/zfs-tests/tests/functional/grow/grow.cfg42
-rwxr-xr-xtests/zfs-tests/tests/functional/grow/grow_pool_001_pos.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/grow/grow_replicas_001_pos.ksh89
-rw-r--r--tests/zfs-tests/tests/functional/history/Makefile.am23
-rwxr-xr-xtests/zfs-tests/tests/functional/history/cleanup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/history/history.cfg49
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_001_pos.ksh122
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_002_pos.ksh198
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_003_pos.ksh99
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_004_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_005_neg.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_006_neg.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_007_pos.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_008_pos.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_009_pos.ksh114
-rwxr-xr-xtests/zfs-tests/tests/functional/history/history_010_pos.ksh88
-rw-r--r--tests/zfs-tests/tests/functional/history/history_common.kshlib422
-rw-r--r--tests/zfs-tests/tests/functional/history/i386.migratedpool.DAT.Zbin0 -> 173047 bytes
-rw-r--r--tests/zfs-tests/tests/functional/history/i386.orig_history.txt12
-rwxr-xr-xtests/zfs-tests/tests/functional/history/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/history/sparc.migratedpool.DAT.Zbin0 -> 163879 bytes
-rw-r--r--tests/zfs-tests/tests/functional/history/sparc.orig_history.txt12
-rw-r--r--tests/zfs-tests/tests/functional/history/zfs-pool-v4.dat.Zbin0 -> 73415 bytes
-rw-r--r--tests/zfs-tests/tests/functional/hkdf/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/hkdf/Makefile.am17
-rwxr-xr-xtests/zfs-tests/tests/functional/hkdf/cleanup.ksh22
-rw-r--r--tests/zfs-tests/tests/functional/hkdf/hkdf_test.c235
-rwxr-xr-xtests/zfs-tests/tests/functional/hkdf/run_hkdf_test.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/hkdf/setup.ksh22
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/Makefile.am57
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/README.config67
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/README.state109
-rwxr-xr-xtests/zfs-tests/tests/functional/inheritance/cleanup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config001.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config002.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config003.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config004.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config005.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config006.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config007.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config008.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config009.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config010.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config011.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config012.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config013.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config014.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config015.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config016.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config017.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config018.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config019.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config020.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config021.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config022.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config023.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/config024.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/inherit.kshlib114
-rwxr-xr-xtests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh452
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state001.cfg44
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state002.cfg45
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state003.cfg43
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state004.cfg44
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state005.cfg45
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state006.cfg47
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state007.cfg45
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state008.cfg44
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state009.cfg57
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state010.cfg56
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state011.cfg58
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state012.cfg62
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state013.cfg56
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state014.cfg62
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state015.cfg66
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state016.cfg62
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state017.cfg67
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state018.cfg64
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state019.cfg63
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state020.cfg64
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state021.cfg64
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state022.cfg63
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state023.cfg65
-rw-r--r--tests/zfs-tests/tests/functional/inheritance/state024.cfg63
-rw-r--r--tests/zfs-tests/tests/functional/inuse/Makefile.am14
-rw-r--r--tests/zfs-tests/tests/functional/inuse/inuse.cfg62
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_001_pos.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_003_pos.ksh168
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_004_pos.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_005_pos.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_006_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_007_pos.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_008_pos.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/inuse_009_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/inuse/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/io/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/io/cleanup.ksh31
-rw-r--r--tests/zfs-tests/tests/functional/io/io.cfg25
-rwxr-xr-xtests/zfs-tests/tests/functional/io/libaio.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/io/mmap.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/io/posixaio.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/io/psync.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/io/setup.ksh31
-rwxr-xr-xtests/zfs-tests/tests/functional/io/sync.ksh65
-rw-r--r--tests/zfs-tests/tests/functional/large_files/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/large_files/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/large_files/large_files_001_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/large_files/large_files_002_pos.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/large_files/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/largest_pool/Makefile.am6
-rw-r--r--tests/zfs-tests/tests/functional/largest_pool/largest_pool.cfg43
-rwxr-xr-xtests/zfs-tests/tests/functional/largest_pool/largest_pool_001_pos.ksh161
-rw-r--r--tests/zfs-tests/tests/functional/libzfs/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/libzfs/Makefile.am17
-rwxr-xr-xtests/zfs-tests/tests/functional/libzfs/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/libzfs/libzfs_input.ksh30
-rw-r--r--tests/zfs-tests/tests/functional/libzfs/many_fds.c73
-rwxr-xr-xtests/zfs-tests/tests/functional/libzfs/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/limits/Makefile.am9
-rwxr-xr-xtests/zfs-tests/tests/functional/limits/cleanup.ksh21
-rwxr-xr-xtests/zfs-tests/tests/functional/limits/filesystem_count.ksh123
-rwxr-xr-xtests/zfs-tests/tests/functional/limits/filesystem_limit.ksh139
-rwxr-xr-xtests/zfs-tests/tests/functional/limits/setup.ksh28
-rwxr-xr-xtests/zfs-tests/tests/functional/limits/snapshot_count.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/limits/snapshot_limit.ksh166
-rw-r--r--tests/zfs-tests/tests/functional/link_count/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/link_count/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/link_count/link_count_001.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/link_count/link_count_root_inode.ksh119
-rwxr-xr-xtests/zfs-tests/tests/functional/link_count/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/log_spacemap/Makefile.am2
-rwxr-xr-xtests/zfs-tests/tests/functional/log_spacemap/log_spacemap_import_logs.ksh81
-rw-r--r--tests/zfs-tests/tests/functional/migration/Makefile.am20
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/cleanup.ksh63
-rw-r--r--tests/zfs-tests/tests/functional/migration/migration.cfg110
-rw-r--r--tests/zfs-tests/tests/functional/migration/migration.kshlib153
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_001_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_002_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_003_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_004_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_005_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_006_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_007_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_008_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_009_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_010_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_011_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/migration_012_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/migration/setup.ksh66
-rw-r--r--tests/zfs-tests/tests/functional/mmap/Makefile.am10
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/cleanup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/mmap/mmap.cfg59
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/mmap_libaio_001_pos.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/mmap_read_001_pos.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/mmap_write_001_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/mmap/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/mmp/Makefile.am21
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/cleanup.ksh28
-rw-r--r--tests/zfs-tests/tests/functional/mmp/mmp.cfg46
-rw-r--r--tests/zfs-tests/tests/functional/mmp/mmp.kshlib333
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_active_import.ksh125
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_exported_import.ksh106
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_hostid.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_inactive_import.ksh111
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_interval.ksh47
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_on_off.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_on_thread.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_on_zdb.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_reset_interval.ksh119
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_write_distribution.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/mmp_write_uberblocks.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/multihost_history.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/mmp/setup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/mount/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/mount/cleanup.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/mount/setup.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/mount/umount_001.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/mount/umount_unlinked_drain.ksh118
-rwxr-xr-xtests/zfs-tests/tests/functional/mount/umountall_001.ksh81
-rw-r--r--tests/zfs-tests/tests/functional/mv_files/Makefile.am11
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/cleanup.ksh48
-rw-r--r--tests/zfs-tests/tests/functional/mv_files/mv_files.cfg50
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/mv_files_001_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/mv_files_002_pos.ksh71
-rw-r--r--tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib205
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/random_creation.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/mv_files/setup.ksh47
-rw-r--r--tests/zfs-tests/tests/functional/nestedfs/Makefile.am5
-rwxr-xr-xtests/zfs-tests/tests/functional/nestedfs/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/nestedfs/nestedfs_001_pos.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/nestedfs/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/no_space/Makefile.am11
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/cleanup.ksh39
-rw-r--r--tests/zfs-tests/tests/functional/no_space/enospc.cfg39
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/enospc_001_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/enospc_002_pos.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/enospc_003_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/enospc_df.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/no_space/setup.ksh40
-rw-r--r--tests/zfs-tests/tests/functional/nopwrite/Makefile.am15
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/cleanup.ksh20
-rw-r--r--tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib68
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/nopwrite_copies.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/nopwrite_mtime.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/nopwrite_negative.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/nopwrite_promoted_clone.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/nopwrite_recsize.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/nopwrite_varying_compression.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/nopwrite_volume.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/nopwrite/setup.ksh23
-rw-r--r--tests/zfs-tests/tests/functional/online_offline/Makefile.am10
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/cleanup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/online_offline/online_offline.cfg42
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/online_offline_001_pos.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/online_offline_002_neg.ksh137
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/online_offline_003_neg.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/online_offline/setup.ksh47
-rw-r--r--tests/zfs-tests/tests/functional/pam/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/cleanup.ksh32
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/pam_basic.ksh49
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/pam_nounmount.ksh51
-rwxr-xr-xtests/zfs-tests/tests/functional/pam/setup.ksh41
-rw-r--r--tests/zfs-tests/tests/functional/pam/utilities.kshlib40
-rw-r--r--tests/zfs-tests/tests/functional/persist_l2arc/Makefile.am15
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/cleanup.ksh31
-rw-r--r--tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc.cfg37
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_001_pos.ksh106
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_002_pos.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_003_neg.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_004_pos.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_005_pos.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_006_pos.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_007_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_008_pos.ksh143
-rwxr-xr-xtests/zfs-tests/tests/functional/persist_l2arc/setup.ksh29
-rw-r--r--tests/zfs-tests/tests/functional/pool_checkpoint/Makefile.am26
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_after_rewind.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_big_rewind.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_capacity.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_conf_change.ksh43
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh110
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_many.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_indirect.ksh59
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_invalid.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_lun_expsz.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_open.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_removal.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_rewind.ksh49
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_ro_rewind.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_sm_scale.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_twice.ksh40
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_vdev_add.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zhack_feat.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/cleanup.ksh23
-rw-r--r--tests/zfs-tests/tests/functional/pool_checkpoint/pool_checkpoint.kshlib413
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_checkpoint/setup.ksh25
-rw-r--r--tests/zfs-tests/tests/functional/pool_names/Makefile.am4
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_names/pool_names_001_pos.ksh116
-rwxr-xr-xtests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh129
-rw-r--r--tests/zfs-tests/tests/functional/poolversion/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/poolversion/cleanup.ksh42
-rwxr-xr-xtests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/poolversion/poolversion_002_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/poolversion/setup.ksh45
-rw-r--r--tests/zfs-tests/tests/functional/privilege/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/privilege/cleanup.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/privilege/privilege_001_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/privilege/privilege_002_pos.ksh105
-rwxr-xr-xtests/zfs-tests/tests/functional/privilege/setup.ksh67
-rw-r--r--tests/zfs-tests/tests/functional/procfs/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/cleanup.ksh29
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/pool_state.ksh146
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/procfs_list_basic.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/procfs/setup.ksh29
-rw-r--r--tests/zfs-tests/tests/functional/projectquota/Makefile.am27
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/cleanup.ksh37
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectid_001_pos.ksh113
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectid_002_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectid_003_pos.ksh81
-rw-r--r--tests/zfs-tests/tests/functional/projectquota/projectquota.cfg46
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_001_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_002_pos.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_003_pos.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_004_neg.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_005_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_008_pos.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.ksh131
-rw-r--r--tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib101
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectspace_001_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectspace_002_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.ksh118
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projectspace_004_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projecttree_001_pos.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projecttree_002_pos.ksh120
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/projecttree_003_neg.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/projectquota/setup.ksh56
-rw-r--r--tests/zfs-tests/tests/functional/pyzfs/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/pyzfs/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in57
-rw-r--r--tests/zfs-tests/tests/functional/quota/Makefile.am14
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/cleanup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/quota/quota.cfg35
-rw-r--r--tests/zfs-tests/tests/functional/quota/quota.kshlib97
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_001_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_002_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_003_pos.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_004_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_005_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/quota_006_neg.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/quota/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/raidz/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_001_neg.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/raidz/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/redacted_send/Makefile.am25
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/cleanup.ksh33
-rw-r--r--tests/zfs-tests/tests/functional/redacted_send/redacted.cfg86
-rw-r--r--tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib266
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_compressed.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_contents.ksh162
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_deleted.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_disabled_feature.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_embedded.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_holes.ksh120
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_incrementals.ksh152
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_largeblocks.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_mixed_recsize.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_mounts.ksh109
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_negative.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_origin.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_props.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_resume.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_size.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/redacted_volume.ksh105
-rwxr-xr-xtests/zfs-tests/tests/functional/redacted_send/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/redundancy/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/cleanup.ksh38
-rw-r--r--tests/zfs-tests/tests/functional/redundancy/redundancy.cfg38
-rw-r--r--tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib335
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_001_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_002_pos.ksh84
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_003_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/redundancy_004_neg.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/redundancy/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/refquota/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/cleanup.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_001_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_002_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_003_pos.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_004_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_005_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_006_neg.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_007_neg.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/refquota_008_neg.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/refquota/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/refreserv/Makefile.am14
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/cleanup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/refreserv/refreserv.cfg31
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh114
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_003_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_004_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_005_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_multi_raidz.ksh201
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/refreserv_raidz.ksh135
-rwxr-xr-xtests/zfs-tests/tests/functional/refreserv/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/removal/Makefile.am37
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/cleanup.ksh23
-rw-r--r--tests/zfs-tests/tests/functional/removal/removal.kshlib156
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_all_vdev.ksh39
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_cancel.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_check_space.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_condense_export.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_multiple_indirection.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_remap_deadlists.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_reservation.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_resume_export.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_sanity.ksh39
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_add.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_create_fs.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_dedup.ksh49
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_errors.ksh114
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_export.ksh47
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_faulted.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_ganging.ksh47
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_remove.ksh35
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_scrub.ksh29
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_send.ksh37
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_send_recv.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_snapshot.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_write.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/removal_with_zdb.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/remove_expanded.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/remove_indirect.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/remove_mirror.ksh57
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/remove_mirror_sanity.ksh58
-rwxr-xr-xtests/zfs-tests/tests/functional/removal/remove_raidz.ksh50
-rw-r--r--tests/zfs-tests/tests/functional/rename_dirs/Makefile.am5
-rwxr-xr-xtests/zfs-tests/tests/functional/rename_dirs/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/rename_dirs/rename_dirs_001_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/rename_dirs/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/replacement/Makefile.am21
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/attach_import.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/attach_multiple.ksh111
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh173
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/attach_resilver.ksh172
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/cleanup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/detach.ksh161
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/rebuild_disabled_feature.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/rebuild_multiple.ksh126
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/rebuild_raidz.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/replace_import.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh158
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/replace_resilver.ksh155
-rw-r--r--tests/zfs-tests/tests/functional/replacement/replacement.cfg43
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/resilver_restart_001.ksh187
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/resilver_restart_002.ksh102
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/scrub_cancel.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/replacement/setup.ksh47
-rw-r--r--tests/zfs-tests/tests/functional/reservation/Makefile.am30
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/cleanup.ksh34
-rw-r--r--tests/zfs-tests/tests/functional/reservation/reservation.cfg44
-rw-r--r--tests/zfs-tests/tests/functional/reservation/reservation.shlib201
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_001_pos.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_002_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_003_pos.ksh134
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_004_pos.ksh130
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_005_pos.ksh118
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_006_pos.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_007_pos.ksh128
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_008_pos.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_009_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_010_pos.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_011_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_012_pos.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_013_pos.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_014_pos.ksh116
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_015_pos.ksh99
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_016_pos.ksh98
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_017_pos.ksh101
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_019_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_020_pos.ksh64
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_021_neg.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/reservation_022_pos.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/reservation/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/rootpool/Makefile.am7
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/cleanup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/rootpool_002_neg.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/rootpool_003_neg.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/rootpool_007_pos.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/rootpool/setup.ksh42
-rw-r--r--tests/zfs-tests/tests/functional/rsend/Makefile.am63
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/cleanup.ksh47
-rw-r--r--tests/zfs-tests/tests/functional/rsend/dedup.zsend.bz2bin0 -> 18561 bytes
-rw-r--r--tests/zfs-tests/tests/functional/rsend/dedup_encrypted_zvol.bz2bin0 -> 1482112 bytes
-rw-r--r--tests/zfs-tests/tests/functional/rsend/dedup_encrypted_zvol.zsend.bz2bin0 -> 836685 bytes
-rw-r--r--tests/zfs-tests/tests/functional/rsend/fs.tar.gzbin0 -> 13196 bytes
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/recv_dedup.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/recv_dedup_encrypted_zvol.ksh60
-rw-r--r--tests/zfs-tests/tests/functional/rsend/rsend.cfg39
-rw-r--r--tests/zfs-tests/tests/functional/rsend/rsend.kshlib850
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_001_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_002_pos.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_003_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_004_pos.ksh120
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_005_pos.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_006_pos.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_007_pos.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_008_pos.ksh131
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_009_pos.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_010_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_011_pos.ksh120
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh186
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_013_pos.ksh86
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_014_pos.ksh56
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_016_neg.ksh33
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh50
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-L_toggle.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_embedded_blocks.ksh109
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_incremental.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_lz4_disabled.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_mixed_compression.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_props.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_recv_dedup.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_recv_lz4_disabled.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_resume.ksh49
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_stream_size_estimate.ksh97
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_verify_contents.ksh55
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_verify_ratio.ksh67
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_volume.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-c_zstreamdump.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-cpL_varied_recsize.ksh203
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send-wR_encrypted_zvol.ksh108
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_encrypted_files.ksh120
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_encrypted_hierarchy.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh215
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_encrypted_truncated_files.ksh126
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_freeobjects.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_holds.ksh177
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_hole_birth.ksh123
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_mixed_raw.ksh118
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_partial_dataset.ksh110
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_realloc_dnode_size.ksh112
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_realloc_encrypted_files.ksh124
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_realloc_files.ksh111
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/send_spill_block.ksh155
-rwxr-xr-xtests/zfs-tests/tests/functional/rsend/setup.ksh46
-rw-r--r--tests/zfs-tests/tests/functional/scrub_mirror/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/cleanup.ksh42
-rw-r--r--tests/zfs-tests/tests/functional/scrub_mirror/default.cfg37
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_002_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_pos.ksh53
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_pos.ksh53
-rw-r--r--tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib76
-rwxr-xr-xtests/zfs-tests/tests/functional/scrub_mirror/setup.ksh42
-rw-r--r--tests/zfs-tests/tests/functional/slog/Makefile.am26
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/cleanup.ksh54
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/setup.ksh41
-rw-r--r--tests/zfs-tests/tests/functional/slog/slog.cfg39
-rw-r--r--tests/zfs-tests/tests/functional/slog/slog.kshlib157
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_001_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_002_pos.ksh68
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_003_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_004_pos.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_005_pos.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_006_pos.ksh73
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_007_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_008_neg.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_009_neg.ksh70
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_010_neg.ksh65
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_011_neg.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_012_neg.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_013_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_014_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_015_neg.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh223
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_replay_fs_002.ksh137
-rwxr-xr-xtests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh179
-rw-r--r--tests/zfs-tests/tests/functional/snapshot/Makefile.am28
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/cleanup.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/clone_001_pos.ksh171
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh115
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/rollback_002_pos.ksh133
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/rollback_003_pos.ksh111
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/setup.ksh40
-rw-r--r--tests/zfs-tests/tests/functional/snapshot/snapshot.cfg53
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_001_pos.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh129
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_003_pos.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_004_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_005_pos.ksh90
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_006_pos.ksh127
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.ksh107
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_008_pos.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_009_pos.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_010_pos.ksh100
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.ksh113
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_012_pos.ksh104
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_013_pos.ksh99
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_014_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh121
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_016_pos.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/snapshot/snapshot_017_pos.ksh202
-rw-r--r--tests/zfs-tests/tests/functional/snapused/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/snapused/snapused.kshlib185
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_001_pos.ksh91
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_002_pos.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_003_pos.ksh82
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_004_pos.ksh95
-rwxr-xr-xtests/zfs-tests/tests/functional/snapused/snapused_005_pos.ksh73
-rw-r--r--tests/zfs-tests/tests/functional/sparse/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/sparse/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/sparse/setup.ksh36
-rw-r--r--tests/zfs-tests/tests/functional/sparse/sparse.cfg43
-rwxr-xr-xtests/zfs-tests/tests/functional/sparse/sparse_001_pos.ksh80
-rw-r--r--tests/zfs-tests/tests/functional/suid/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/suid/Makefile.am16
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/setup.ksh35
-rw-r--r--tests/zfs-tests/tests/functional/suid/suid_write_to_file.c133
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh52
-rwxr-xr-xtests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh52
-rw-r--r--tests/zfs-tests/tests/functional/threadsappend/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/threadsappend/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/threadsappend/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/threadsappend/setup.ksh36
-rwxr-xr-xtests/zfs-tests/tests/functional/threadsappend/threadsappend_001_pos.ksh80
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/.gitignore5
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/Makefile.am16
-rwxr-xr-xtests/zfs-tests/tests/functional/tmpfile/cleanup.ksh34
-rwxr-xr-xtests/zfs-tests/tests/functional/tmpfile/setup.ksh42
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/tmpfile_001_pos.c109
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c98
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/tmpfile_003_pos.c68
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c121
-rw-r--r--tests/zfs-tests/tests/functional/tmpfile/tmpfile_test.c53
-rw-r--r--tests/zfs-tests/tests/functional/trim/Makefile.am12
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/autotrim_config.ksh103
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh87
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/cleanup.ksh48
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/setup.ksh43
-rw-r--r--tests/zfs-tests/tests/functional/trim/trim.cfg33
-rw-r--r--tests/zfs-tests/tests/functional/trim/trim.kshlib122
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/trim_config.ksh102
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/trim_integrity.ksh88
-rwxr-xr-xtests/zfs-tests/tests/functional/trim/trim_l2arc.ksh106
-rw-r--r--tests/zfs-tests/tests/functional/truncate/.gitignore1
-rw-r--r--tests/zfs-tests/tests/functional/truncate/Makefile.am18
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/cleanup.ksh30
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/truncate/truncate.cfg39
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/truncate_001_pos.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/truncate_002_pos.ksh67
-rw-r--r--tests/zfs-tests/tests/functional/truncate/truncate_test.c103
-rwxr-xr-xtests/zfs-tests/tests/functional/truncate/truncate_timestamps.ksh84
-rw-r--r--tests/zfs-tests/tests/functional/upgrade/Makefile.am10
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/cleanup.ksh42
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/setup.ksh43
-rw-r--r--tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib41
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_pos.ksh128
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/upgrade_readonly_pool.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/upgrade/upgrade_userobj_001_pos.ksh96
-rw-r--r--tests/zfs-tests/tests/functional/user_namespace/Makefile.am9
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/cleanup.ksh25
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/setup.ksh32
-rw-r--r--tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg23
-rwxr-xr-xtests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh89
-rw-r--r--tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib23
-rw-r--r--tests/zfs-tests/tests/functional/userquota/Makefile.am27
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/cleanup.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/groupspace_001_pos.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/groupspace_002_pos.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/groupspace_003_pos.ksh109
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/setup.ksh56
-rw-r--r--tests/zfs-tests/tests/functional/userquota/userquota.cfg46
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_001_pos.ksh74
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_002_pos.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_003_pos.ksh61
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_004_pos.ksh85
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_005_neg.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_006_pos.ksh79
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_007_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_008_pos.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_009_pos.ksh92
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_010_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_011_pos.ksh127
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_012_neg.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userquota_013_pos.ksh77
-rw-r--r--tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib123
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userspace_001_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userspace_002_pos.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh122
-rw-r--r--tests/zfs-tests/tests/functional/vdev_zaps/Makefile.am14
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/cleanup.ksh20
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/setup.ksh21
-rw-r--r--tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib114
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh42
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh47
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh94
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh46
-rwxr-xr-xtests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh74
-rw-r--r--tests/zfs-tests/tests/functional/write_dirs/Makefile.am6
-rwxr-xr-xtests/zfs-tests/tests/functional/write_dirs/cleanup.ksh37
-rwxr-xr-xtests/zfs-tests/tests/functional/write_dirs/setup.ksh38
-rwxr-xr-xtests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.ksh75
-rwxr-xr-xtests/zfs-tests/tests/functional/write_dirs/write_dirs_002_pos.ksh76
-rw-r--r--tests/zfs-tests/tests/functional/xattr/Makefile.am21
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/cleanup.ksh46
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/setup.ksh55
-rw-r--r--tests/zfs-tests/tests/functional/xattr/xattr.cfg30
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_001_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_002_neg.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh143
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_005_pos.ksh78
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_006_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_007_neg.ksh89
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_008_pos.ksh80
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_009_neg.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_010_neg.ksh66
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh241
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh122
-rwxr-xr-xtests/zfs-tests/tests/functional/xattr/xattr_013_pos.ksh104
-rw-r--r--tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib137
-rw-r--r--tests/zfs-tests/tests/functional/zvol/Makefile.am10
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol.cfg39
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/Makefile.am8
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup.ksh44
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.ksh50
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg41
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos.ksh80
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_cli/Makefile.am10
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup.ksh39
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh45
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg41
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos.ksh63
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos.ksh62
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg.ksh59
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_common.shlib134
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_misc/Makefile.am19
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh41
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh72
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg.ksh81
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos.ksh117
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg.ksh83
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos.ksh80
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib143
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_hierarchy.ksh93
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_rename_inuse.ksh71
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh121
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh242
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.ksh74
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_swap/Makefile.am13
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.ksh60
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/setup.ksh49
-rw-r--r--tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg44
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos.ksh77
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos.ksh96
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos.ksh76
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos.ksh69
-rwxr-xr-xtests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos.ksh108
-rw-r--r--tests/zfs-tests/tests/perf/Makefile.am9
-rw-r--r--tests/zfs-tests/tests/perf/fio/Makefile.am10
-rw-r--r--tests/zfs-tests/tests/perf/fio/mkfiles.fio33
-rw-r--r--tests/zfs-tests/tests/perf/fio/random_reads.fio32
-rw-r--r--tests/zfs-tests/tests/perf/fio/random_readwrite.fio39
-rw-r--r--tests/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio39
-rw-r--r--tests/zfs-tests/tests/perf/fio/random_writes.fio37
-rw-r--r--tests/zfs-tests/tests/perf/fio/sequential_reads.fio32
-rw-r--r--tests/zfs-tests/tests/perf/fio/sequential_readwrite.fio39
-rw-r--r--tests/zfs-tests/tests/perf/fio/sequential_writes.fio37
-rw-r--r--tests/zfs-tests/tests/perf/nfs-sample.cfg46
-rw-r--r--tests/zfs-tests/tests/perf/perf.shlib575
-rw-r--r--tests/zfs-tests/tests/perf/regression/Makefile.am13
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/random_reads.ksh114
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/random_readwrite.ksh114
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh106
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/random_writes.ksh105
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/random_writes_zil.ksh100
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/sequential_reads.ksh116
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/sequential_reads_arc_cached.ksh106
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/sequential_reads_arc_cached_clone.ksh132
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/sequential_reads_dbuf_cached.ksh112
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/sequential_writes.ksh105
-rwxr-xr-xtests/zfs-tests/tests/perf/regression/setup.ksh23
-rw-r--r--tests/zfs-tests/tests/perf/scripts/Makefile.am2
-rwxr-xr-xtests/zfs-tests/tests/perf/scripts/prefetch_io.sh82
-rw-r--r--tests/zfs-tests/tests/stress/Makefile.am1
2007 files changed, 144724 insertions, 0 deletions
diff --git a/tests/zfs-tests/tests/Makefile.am b/tests/zfs-tests/tests/Makefile.am
new file mode 100644
index 000000000000..f7494791524e
--- /dev/null
+++ b/tests/zfs-tests/tests/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = functional perf stress
diff --git a/tests/zfs-tests/tests/functional/Makefile.am b/tests/zfs-tests/tests/functional/Makefile.am
new file mode 100644
index 000000000000..c56518c55a03
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/Makefile.am
@@ -0,0 +1,90 @@
+SUBDIRS = \
+ acl \
+ alloc_class \
+ arc \
+ atime \
+ bootfs \
+ btree \
+ cache \
+ cachefile \
+ casenorm \
+ channel_program \
+ chattr \
+ checksum \
+ clean_mirror \
+ cli_root \
+ cli_user \
+ compression \
+ cp_files \
+ ctime \
+ deadman \
+ delegate \
+ devices \
+ events \
+ exec \
+ fallocate \
+ fault \
+ features \
+ grow \
+ history \
+ hkdf \
+ inheritance \
+ inuse \
+ io \
+ large_files \
+ largest_pool \
+ libzfs \
+ limits \
+ link_count \
+ log_spacemap \
+ migration \
+ mmap \
+ mmp \
+ mount \
+ mv_files \
+ nestedfs \
+ no_space \
+ nopwrite \
+ online_offline \
+ pam \
+ persist_l2arc \
+ pool_checkpoint \
+ pool_names \
+ poolversion \
+ privilege \
+ procfs \
+ projectquota \
+ pyzfs \
+ quota \
+ raidz \
+ redacted_send \
+ redundancy \
+ refquota \
+ refreserv \
+ removal \
+ rename_dirs \
+ replacement \
+ reservation \
+ rootpool \
+ rsend \
+ scrub_mirror \
+ slog \
+ snapshot \
+ snapused \
+ sparse \
+ suid \
+ threadsappend \
+ trim \
+ truncate \
+ upgrade \
+ user_namespace \
+ userquota \
+ vdev_zaps \
+ write_dirs \
+ xattr \
+ zvol
+
+if BUILD_LINUX
+SUBDIRS += \
+ tmpfile
+endif
diff --git a/tests/zfs-tests/tests/functional/acl/Makefile.am b/tests/zfs-tests/tests/functional/acl/Makefile.am
new file mode 100644
index 000000000000..6086930e36fa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/acl
+dist_pkgdata_DATA = \
+ acl.cfg \
+ acl_common.kshlib
+
+SUBDIRS = posix
diff --git a/tests/zfs-tests/tests/functional/acl/acl.cfg b/tests/zfs-tests/tests/functional/acl/acl.cfg
new file mode 100644
index 000000000000..8fa85d673bb7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/acl.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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export NISSTAFILE=$TEST_BASE_DIR/nis_state
+export TESTFILE=testfile$$
+export TESTFILE0=testfile0.$$
+export TESTFILE2=testfile2.$$
+
+# Define super user 'zfstest'
+export ZFS_ACL_ADMIN=zfstest
+
+export ZFS_ACL_STAFF_GROUP=zfsgrp
+export ZFS_ACL_STAFF1=staff1
+export ZFS_ACL_STAFF2=staff2
+
+export ZFS_ACL_OTHER_GROUP=othergrp
+export ZFS_ACL_OTHER1=other1
+export ZFS_ACL_OTHER2=other2
+
+# Define the current user who run 'usr_exec'
+export ZFS_ACL_CUR_USER=""
+
+# Define global error string
+export ZFS_ACL_ERR_STR=""
+
+# Define test file and test directory which will be operated by chmod
+export testfile=$TESTDIR/testfile
+export testdir=$TESTDIR/testdir
+
+# Define several directories for trivial ACLs function test.
+export RES_DIR=$TESTDIR/RES
+export INI_DIR=$TESTDIR/INIT
+export TST_DIR=$TESTDIR/TEST
+export TMP_DIR=$TESTDIR/TMP
+
+# Define test files and their attributes files number for trivial
+# ACLs function test
+export NUM_FILE=5
+export NUM_ATTR=10
diff --git a/tests/zfs-tests/tests/functional/acl/acl_common.kshlib b/tests/zfs-tests/tests/functional/acl/acl_common.kshlib
new file mode 100644
index 000000000000..ba08bcb48bef
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/acl_common.kshlib
@@ -0,0 +1,630 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/acl/acl.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Get the given file/directory access mode
+#
+# $1 object -- file or directory
+#
+function get_mode #<obj>
+{
+ typeset obj=$1
+ if (( ${#obj} == 0 )); then
+ return 1
+ fi
+
+ ls -ld $obj | awk '{print $1}'
+}
+
+#
+# Get the given file/directory ACL
+#
+# $1 object -- file or directory
+#
+function get_acl #<obj>
+{
+ typeset obj=$1
+ if (( ${#obj} == 0 )); then
+ return 1
+ fi
+
+ ls -vd $obj | nawk '(NR != 1) {print $0}'
+}
+
+#
+# Get the given file/directory ACL
+#
+# $1 object -- file or directory
+#
+function get_compact_acl #<obj>
+{
+ typeset obj=$1
+ if (( ${#obj} == 0 )); then
+ return 1
+ fi
+
+ ls -Vd $obj | nawk '(NR != 1) {print $0}'
+}
+
+#
+# Check the given two files/directories have the same ACLs
+#
+# Return 0, if source object acl is equal to target object acl.
+#
+# $1 source object
+# $2 target object
+#
+function compare_acls #<src> <tgt>
+{
+ typeset src=$1
+ typeset tgt=$2
+
+ (( ${#src} == 0 || ${#tgt} == 0 )) && return 1
+ [[ $src == $tgt ]] && return 0
+
+ typeset tmpsrc=$TEST_BASE_DIR/compare_acls.src.$$
+ typeset tmptgt=$TEST_BASE_DIR/compare_acls.tgt.$$
+
+ get_acl $src > $tmpsrc
+ get_acl $tgt > $tmptgt
+ typeset -i ret=0
+ diff $tmpsrc $tmptgt > /dev/null 2>&1
+ ret=$?
+ rm -f $tmpsrc $tmptgt
+
+ if (( ret != 0 )); then
+ return $ret
+ fi
+
+ get_compact_acl $src > $tmpsrc
+ get_compact_acl $tgt > $tmptgt
+ diff $tmpsrc $tmptgt > /dev/null 2>&1
+ ret=$?
+ rm -f $tmpsrc $tmptgt
+
+ return $ret
+}
+
+#
+# Check that the given two objects have the same modes.
+# Return 0, if their modes are equal with each other. Otherwise, return 1.
+#
+# $1 source object
+# $2 target object
+#
+function compare_modes #<src> <tgt>
+{
+ typeset src=$1
+ typeset tgt=$2
+ typeset -i i=0
+ set -A mode
+
+ (( ${#src} == 0 || ${#tgt} == 0 )) && return 1
+ [[ $src == $tgt ]] && return 0
+
+ typeset obj
+ for obj in $src $tgt
+ do
+ mode[i]=$(get_mode $obj)
+
+ (( i = i + 1 ))
+ done
+
+ [[ ${mode[0]} != ${mode[1]} ]] && return 1
+
+ return 0
+}
+
+#
+# Check that the given two objects have the same xattrs.
+# Return 0, if their xattrs are equal with each other. Otherwise, return 1.
+#
+# $1 source object
+# $2 target object
+#
+function compare_xattrs #<src> <tgt>
+{
+ typeset src=$1
+ typeset tgt=$2
+
+ (( ${#src} == 0 || ${#tgt} == 0 )) && return 1
+ [[ $src == $tgt ]] && return 0
+
+ typeset tmpsrc=$TEST_BASE_DIR/compare_xattrs.src.$$
+ typeset tmptgt=$TEST_BASE_DIR/compare_xattrs.tgt.$$
+
+ get_xattr $src > $tmpsrc
+ get_xattr $tgt > $tmptgt
+ typeset -i ret=0
+ diff $tmpsrc $tmptgt > /dev/null 2>&1
+ ret=$?
+ rm -f $tmpsrc $tmptgt
+
+ return $ret
+}
+
+#
+# Check '+' is set for a given file/directory with 'ls [-l]' command
+#
+# $1 object -- file or directory.
+#
+function plus_sign_check_l #<obj>
+{
+ typeset obj=$1
+ if (( ${#obj} == 0 )); then
+ return 1
+ fi
+
+ ls -ld $obj | awk '{print $1}' | grep "+$" > /dev/null
+
+ return $?
+}
+
+#
+# Check '+' is set for a given file/directory with 'ls [-v]' command
+#
+# $1 object -- file or directory.
+#
+function plus_sign_check_v #<obj>
+{
+ typeset obj=$1
+ if (( ${#obj} == 0 )); then
+ return 1
+ fi
+
+ ls -vd $obj | awk '(NR == 1) {print $1}' | grep "+$" > /dev/null
+
+ return $?
+}
+
+#
+# A wrapper function of c program
+#
+# $1 legal login name
+# $2-n commands and options
+#
+function chgusr_exec #<login_name> <commands> [...]
+{
+ chg_usr_exec $@
+ return $?
+}
+
+#
+# Export the current user for the following usr_exec operating.
+#
+# $1 legal login name
+#
+function set_cur_usr #<login_name>
+{
+ export ZFS_ACL_CUR_USER=$1
+}
+
+#
+# Run commands by $ZFS_ACL_CUR_USER
+#
+# $1-n commands and options
+#
+function usr_exec #<commands> [...]
+{
+ chg_usr_exec "$ZFS_ACL_CUR_USER" $@
+ return $?
+}
+
+#
+# Count how many ACEs for the specified file or directory.
+#
+# $1 file or directory name
+#
+function count_ACE #<file or dir name>
+{
+ if [[ ! -e $1 ]]; then
+ log_note "Need input file or directory name."
+ return 1
+ fi
+
+ ls -vd $1 | nawk 'BEGIN {count=0}
+ (NR != 1)&&(/[0-9]:/) {count++}
+ END {print count}'
+
+ return 0
+}
+
+#
+# Get specified number ACE content of specified file or directory.
+#
+# $1 file or directory name
+# $2 specified number
+#
+function get_ACE #<file or dir name> <specified number> <verbose|compact>
+{
+ if [[ ! -e $1 || $2 -ge $(count_ACE $1) ]]; then
+ return 1
+ fi
+
+ typeset file=$1
+ typeset -i num=$2
+ typeset format=${3:-verbose}
+ typeset -i next_num=-1
+
+ typeset tmpfile=$TEST_BASE_DIR/tmp_get_ACE.$$
+ typeset line=""
+ typeset args
+
+ case $format in
+ verbose) args="-vd"
+ ;;
+ compact) args="-Vd"
+ ;;
+ *) log_fail "Invalid parameter as ($format), " \
+ "only verbose|compact is supported."
+ ;;
+ esac
+
+ ls $args $file > $tmpfile
+ (( $? != 0 )) && log_fail "FAIL: ls $args $file > $tmpfile"
+ while read line; do
+ [[ -z $line ]] && continue
+ if [[ $args == -vd ]]; then
+ if [[ $line == "$num":* ]]; then
+ (( next_num = num + 1 ))
+ fi
+ if [[ $line == "$next_num":* ]]; then
+ break
+ fi
+ if (( next_num != -1 )); then
+ print -n $line
+ fi
+ else
+ if (( next_num == num )); then
+ print -n $line
+ fi
+ (( next_num += 1 ))
+ fi
+ done < $tmpfile
+
+ rm -f $tmpfile
+ (( $? != 0 )) && log_fail "FAIL: rm -f $tmpfile"
+}
+
+#
+# Cleanup exist user/group.
+#
+function cleanup_user_group
+{
+ del_user $ZFS_ACL_ADMIN
+
+ del_user $ZFS_ACL_STAFF1
+ del_user $ZFS_ACL_STAFF2
+ del_group $ZFS_ACL_STAFF_GROUP
+
+ del_user $ZFS_ACL_OTHER1
+ del_user $ZFS_ACL_OTHER2
+ del_group $ZFS_ACL_OTHER_GROUP
+
+ return 0
+}
+
+#
+# Clean up testfile and test directory
+#
+function cleanup
+{
+ if [[ -d $TESTDIR ]]; then
+ cd $TESTDIR
+ rm -rf $TESTDIR/*
+ fi
+}
+
+#
+# According to specified access or acl_spec, do relevant operating by using the
+# specified user.
+#
+# $1 specified user
+# $2 node
+# $3 acl_spec or access
+#
+function rwx_node #user node acl_spec|access
+{
+ typeset user=$1
+ typeset node=$2
+ typeset acl_spec=$3
+
+ if [[ $user == "" || $node == "" || $acl_spec == "" ]]; then
+ log_note "node or acl_spec are not defined."
+ return 1
+ fi
+
+ if [[ -d $node ]]; then
+ case $acl_spec in
+ *:read_data:*|read_data)
+ chgusr_exec $user ls -l $node > /dev/null 2>&1
+ return $? ;;
+ *:write_data:*|write_data)
+ if [[ -f ${node}/tmpfile ]]; then
+ log_must rm -f ${node}/tmpfile
+ fi
+ chgusr_exec $user touch ${node}/tmpfile > \
+ /dev/null 2>&1
+ return $? ;;
+ *"execute:"*|execute)
+ chgusr_exec $user find $node > /dev/null 2>&1
+ return $? ;;
+ esac
+ else
+ case $acl_spec in
+ *:read_data:*|read_data)
+ chgusr_exec $user cat $node > /dev/null 2>&1
+ return $? ;;
+ *:write_data:*|write_data)
+ chgusr_exec $user dd if=/usr/bin/ls of=$node > \
+ /dev/null 2>&1
+ return $? ;;
+ *"execute:"*|execute)
+ ZFS_ACL_ERR_STR=$(chgusr_exec $user $node 2>&1)
+ return $? ;;
+ esac
+ fi
+}
+
+#
+# Get the given file/directory xattr
+#
+# $1 object -- file or directory
+#
+function get_xattr #<obj>
+{
+ typeset obj=$1
+ typeset xattr
+ if (( ${#obj} == 0 )); then
+ return 1
+ fi
+
+ for xattr in `runat $obj ls | \
+ grep -E -v -e SUNWattr_ro -e SUNWattr_rw` ; do
+ runat $obj sum $xattr
+ done
+}
+
+#
+# Get the owner of a file/directory
+#
+function get_owner #node
+{
+ typeset node=$1
+ typeset value
+
+ if [[ -z $node ]]; then
+ log_fail "node are not defined."
+ fi
+
+ if [[ -d $node ]]; then
+ value=$(ls -dl $node | awk '{print $3}')
+ elif [[ -e $node ]]; then
+ value=$(ls -l $node | awk '{print $3}')
+ fi
+
+ echo $value
+}
+
+#
+# Get the group of a file/directory
+#
+function get_group #node
+{
+ typeset node=$1
+ typeset value
+
+ if [[ -z $node ]]; then
+ log_fail "node are not defined."
+ fi
+
+ if [[ -d $node ]]; then
+ value=$(ls -dl $node | awk '{print $4}')
+ elif [[ -e $node ]]; then
+ value=$(ls -l $node | awk '{print $4}')
+ fi
+
+ echo $value
+}
+
+
+#
+# Get the group name that a UID belongs to
+#
+function get_user_group #uid
+{
+ typeset uid=$1
+ typeset value
+
+ if [[ -z $uid ]]; then
+ log_fail "UID not defined."
+ fi
+
+ value=$(id $uid)
+
+ if [[ $? -eq 0 ]]; then
+ value=${value##*\(}
+ value=${value%%\)*}
+ echo $value
+ else
+ log_fail "Invalid UID (uid)."
+ fi
+}
+
+#
+# Get the specified item of the specified string
+#
+# $1: Item number, count from 0.
+# $2-n: strings
+#
+function getitem
+{
+ typeset -i n=$1
+ shift
+
+ (( n += 1 ))
+ eval echo \${$n}
+}
+
+#
+# This function calculate the specified directory files checksum and write
+# to the specified array.
+#
+# $1 directory in which the files will be cksum.
+# $2 file array name which was used to store file cksum information.
+# $3 attribute array name which was used to store attribute information.
+#
+function cksum_files #<dir> <file_array_name> <attribute_array_name>
+{
+ typeset dir=$1
+ typeset farr_name=$2
+ typeset aarr_name=$3
+
+ [[ ! -d $dir ]] && return
+ typeset oldpwd=$PWD
+ cd $dir
+ typeset files=$(ls file*)
+
+ typeset -i i=0
+ typeset -i n=0
+ while (( i < NUM_FILE )); do
+ typeset f=$(getitem $i $files)
+ eval $farr_name[$i]=\$\(\cksum $f\)
+
+ typeset -i j=0
+ while (( j < NUM_ATTR )); do
+ eval $aarr_name[$n]=\$\(\runat \$f \cksum \
+ attribute.$j\)
+
+ (( j += 1 ))
+ (( n += 1 ))
+ done
+
+ (( i += 1 ))
+ done
+
+ cd $oldpwd
+}
+
+#
+# This function compare two cksum results array.
+#
+# $1 The array name which stored the cksum before operation.
+# $2 The array name which stored the cksum after operation.
+#
+function compare_cksum #<array1> <array2>
+{
+ typeset before=$1
+ typeset after=$2
+ eval typeset -i count=\${#$before[@]}
+
+ typeset -i i=0
+ while (( i < count )); do
+ eval typeset var1=\${$before[$i]}
+ eval typeset var2=\${$after[$i]}
+
+ if [[ $var1 != $var2 ]]; then
+ return 1
+ fi
+
+ (( i += 1 ))
+ done
+
+ return 0
+}
+
+#
+# This function calculate all the files cksum information in current directory
+# and output them to the specified file.
+#
+# $1 directory from which the files will be cksum.
+# $2 cksum output file
+#
+function record_cksum #<outfile>
+{
+ typeset dir=$1
+ typeset outfile=$2
+
+ [[ ! -d ${outfile%/*} ]] && usr_exec mkdir -p ${outfile%/*}
+
+ usr_exec cd $dir ; find . -depth -type f -exec cksum {} \\\; | \
+ sort > $outfile
+ usr_exec cd $dir ; find . -depth -type f -xattr -exec runat {} \
+ cksum attribute* \\\; | sort >> $outfile
+}
+
+#
+# The function create_files creates the directories and files that the script
+# will operate on to test extended attribute functionality.
+#
+# $1 The base directory in which to create directories and files.
+#
+function create_files #<directory>
+{
+ typeset basedir=$1
+
+ [[ ! -d $basedir ]] && usr_exec mkdir -m 777 $basedir
+ [[ ! -d $RES_DIR ]] && usr_exec mkdir -m 777 $RES_DIR
+ [[ ! -d $INI_DIR ]] && usr_exec mkdir -m 777 $INI_DIR
+ [[ ! -d $TST_DIR ]] && usr_exec mkdir -m 777 $TST_DIR
+ [[ ! -d $TMP_DIR ]] && usr_exec mkdir -m 777 $TMP_DIR
+
+ #
+ # Create the original file and its attribute files.
+ #
+ [[ ! -a $RES_DIR/file ]] && \
+ usr_exec file_write -o create -f $RES_DIR/file \
+ -b 1024 -d 0 -c 1
+ [[ ! -a $RES_DIR/attribute ]] && \
+ usr_exec cp $RES_DIR/file $RES_DIR/attribute
+
+ typeset oldpwd=$PWD
+ cd $INI_DIR
+
+ typeset -i i=0
+ while (( i < NUM_FILE )); do
+ typeset dstfile=$INI_DIR/file.$$.$i
+ usr_exec cp $RES_DIR/file $dstfile
+
+ typeset -i j=0
+ while (( j < NUM_ATTR )); do
+ usr_exec runat $dstfile \
+ cp $RES_DIR/attribute ./attribute.$j
+ (( j += 1 ))
+ done
+
+ (( i += 1 ))
+ done
+
+ cd $oldpwd
+}
diff --git a/tests/zfs-tests/tests/functional/acl/posix/Makefile.am b/tests/zfs-tests/tests/functional/acl/posix/Makefile.am
new file mode 100644
index 000000000000..dcf278858090
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/posix/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/acl/posix
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ posix_001_pos.ksh \
+ posix_002_pos.ksh \
+ posix_003_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/acl/posix/cleanup.ksh b/tests/zfs-tests/tests/functional/acl/posix/cleanup.ksh
new file mode 100755
index 000000000000..bb58a8cf2e7b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/posix/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/acl/acl_common.kshlib
+
+cleanup_user_group
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/acl/posix/posix_001_pos.ksh b/tests/zfs-tests/tests/functional/acl/posix/posix_001_pos.ksh
new file mode 100755
index 000000000000..66124fe9cc31
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/posix/posix_001_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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/acl/acl_common.kshlib
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# DESCRIPTION:
+# Verify that user can access file/directory if acltype=posixacl.
+#
+# STRATEGY:
+# 1. Test access to file (mode=rw-)
+# a. Can modify file
+# b. Can't create new file
+# b. Can't execute file
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rmdir $TESTDIR/dir.0
+}
+
+log_assert "Verify acltype=posixacl works on file"
+log_onexit cleanup
+
+# Test access to FILE
+log_note "Testing access to FILE"
+log_must touch $TESTDIR/file.0
+log_must setfacl -m g:$ZFS_ACL_STAFF_GROUP:rw $TESTDIR/file.0
+getfacl $TESTDIR/file.0 2> /dev/null | egrep -q \
+ "^group:$ZFS_ACL_STAFF_GROUP:rw-$"
+if [ "$?" -eq "0" ]; then
+ # Should be able to write to file
+ log_must user_run $ZFS_ACL_STAFF1 \
+ "echo 'echo test > /dev/null' > $TESTDIR/file.0"
+
+ # Since $TESTDIR is 777, create a new dir with controlled permissions
+ # for testing that creating a new file is not allowed.
+ log_must mkdir $TESTDIR/dir.0
+ log_must chmod 700 $TESTDIR/dir.0
+ log_must setfacl -m g:$ZFS_ACL_STAFF_GROUP:rw $TESTDIR/dir.0
+ # Confirm permissions
+ ls -l $TESTDIR |grep "dir.0" |grep -q "drwxrw----+"
+ if [ "$?" -ne "0" ]; then
+ msk=$(ls -l $TESTDIR |grep "dir.0" | awk '{print $1}')
+ log_note "expected mask drwxrw----+ but found $msk"
+ log_fail "Expected permissions were not set."
+ fi
+ getfacl $TESTDIR/dir.0 2> /dev/null | egrep -q \
+ "^group:$ZFS_ACL_STAFF_GROUP:rw-$"
+ if [ "$?" -ne "0" ]; then
+ acl=$(getfacl $TESTDIR/dir.0 2> /dev/null)
+ log_note $acl
+ log_fail "ACL group:$ZFS_ACL_STAFF_GROUP:rw- was not set."
+ fi
+ # Should NOT be able to create new file
+ log_mustnot user_run $ZFS_ACL_STAFF1 "touch $TESTDIR/dir.0/file.1"
+
+ # Root should be able to run file, but not user
+ chmod +x $TESTDIR/file.0
+ log_must $TESTDIR/file.0
+ log_mustnot user_run $ZFS_ACL_STAFF1 $TESTDIR/file.0
+
+ log_pass "POSIX ACL mode works on files"
+else
+ log_fail "Group '$ZFS_ACL_STAFF_GROUP' does not have 'rw' as specified"
+fi
diff --git a/tests/zfs-tests/tests/functional/acl/posix/posix_002_pos.ksh b/tests/zfs-tests/tests/functional/acl/posix/posix_002_pos.ksh
new file mode 100755
index 000000000000..1aceffd15692
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/posix/posix_002_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/acl/acl_common.kshlib
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# DESCRIPTION:
+# Verify that user can access file/directory if acltype=posixacl.
+#
+# STRATEGY:
+# 1. Test access to directory (mode=-wx)
+# a. Can create file in dir
+# b. Can't list directory
+#
+
+verify_runnable "both"
+log_assert "Verify acltype=posixacl works on directory"
+
+# Test access to DIRECTORY
+log_note "Testing access to DIRECTORY"
+log_must mkdir $TESTDIR/dir.0
+# Eliminate access by "other" including our test group,
+# we want access controlled only by the ACLs.
+log_must chmod 700 $TESTDIR/dir.0
+log_must setfacl -m g:$ZFS_ACL_STAFF_GROUP:wx $TESTDIR/dir.0
+# Confirm permissions
+ls -l $TESTDIR |grep "dir.0" |grep -q "drwx-wx---+"
+if [ "$?" -ne "0" ]; then
+ msk=$(ls -l $TESTDIR |grep "dir.0" | awk '{print $1}')
+ log_note "expected mask drwx-wx---+ but found $msk"
+ log_fail "Expected permissions were not set."
+fi
+getfacl $TESTDIR/dir.0 2> /dev/null | egrep -q \
+ "^group:$ZFS_ACL_STAFF_GROUP:-wx$"
+if [ "$?" -eq "0" ]; then
+ # Should be able to create file in directory
+ log_must user_run $ZFS_ACL_STAFF1 "touch $TESTDIR/dir.0/file.0"
+
+ # Should NOT be able to list files in directory
+ log_mustnot user_run $ZFS_ACL_STAFF1 "ls -l $TESTDIR/dir.0"
+
+ log_pass "POSIX ACL mode works on directories"
+else
+ acl=$(getfacl $TESTDIR/dir.0 2> /dev/null)
+ log_note $acl
+ log_fail "Group '$ZFS_ACL_STAFF_GROUP' does not have '-wx' as specified"
+fi
diff --git a/tests/zfs-tests/tests/functional/acl/posix/posix_003_pos.ksh b/tests/zfs-tests/tests/functional/acl/posix/posix_003_pos.ksh
new file mode 100755
index 000000000000..dc6ef0d2477d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/posix/posix_003_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
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that ACLs survive remount.
+# Regression test for https://github.com/zfsonlinux/zfs/issues/4520
+#
+# STRATEGY:
+# 1. Test presence of default and regular ACLs after remount
+# a. Can set and list ACL before remount
+# b. Can list ACL after remount
+#
+
+verify_runnable "both"
+log_assert "Verify regular and default POSIX ACLs survive remount"
+
+typeset acl_str1="^group:$ZFS_ACL_STAFF_GROUP:-wx$"
+typeset acl_str2="^default:group:$ZFS_ACL_STAFF_GROUP:-wx$"
+typeset ACLDIR="$TESTDIR/dir.1"
+
+log_note "Testing access to DIRECTORY"
+log_must mkdir $ACLDIR
+log_must setfacl -m g:$ZFS_ACL_STAFF_GROUP:wx $ACLDIR
+log_must setfacl -d -m g:$ZFS_ACL_STAFF_GROUP:wx $ACLDIR
+getfacl $ACLDIR 2> /dev/null | egrep -q "$acl_str1"
+if [ "$?" -eq "0" ]; then
+ getfacl $ACLDIR 2> /dev/null | egrep -q "$acl_str2"
+fi
+
+if [ "$?" -eq "0" ]; then
+ log_must zfs unmount $TESTPOOL/$TESTFS
+ log_must zfs mount $TESTPOOL/$TESTFS
+ log_must eval "getfacl $ACLDIR 2> /dev/null | egrep -q \"$acl_str1\""
+ log_must eval "getfacl $ACLDIR 2> /dev/null | egrep -q \"$acl_str2\""
+ log_pass "POSIX ACLs survive remount"
+else
+ log_fail "Group '$ZFS_ACL_STAFF_GROUP' does not have 'rwx'"
+fi
diff --git a/tests/zfs-tests/tests/functional/acl/posix/setup.ksh b/tests/zfs-tests/tests/functional/acl/posix/setup.ksh
new file mode 100755
index 000000000000..5d6d15864134
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/acl/posix/setup.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 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/acl/acl_common.kshlib
+
+log_must getfacl --version
+log_must setfacl --version
+
+cleanup_user_group
+
+# Create staff group and add user to it
+log_must add_group $ZFS_ACL_STAFF_GROUP
+log_must add_user $ZFS_ACL_STAFF_GROUP $ZFS_ACL_STAFF1
+
+DISK=${DISKS%% *}
+default_setup_noexit $DISK
+log_must chmod 777 $TESTDIR
+
+# Use POSIX ACLs on filesystem
+log_must zfs set acltype=posixacl $TESTPOOL/$TESTFS
+log_must zfs set xattr=sa $TESTPOOL/$TESTFS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/alloc_class/Makefile.am b/tests/zfs-tests/tests/functional/alloc_class/Makefile.am
new file mode 100644
index 000000000000..7cffb2eac450
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/Makefile.am
@@ -0,0 +1,21 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/alloc_class
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ alloc_class_001_pos.ksh \
+ alloc_class_002_neg.ksh \
+ alloc_class_003_pos.ksh \
+ alloc_class_004_pos.ksh \
+ alloc_class_005_pos.ksh \
+ alloc_class_006_pos.ksh \
+ alloc_class_007_pos.ksh \
+ alloc_class_008_pos.ksh \
+ alloc_class_009_pos.ksh \
+ alloc_class_010_pos.ksh \
+ alloc_class_011_neg.ksh \
+ alloc_class_012_pos.ksh \
+ alloc_class_013_pos.ksh
+
+dist_pkgdata_DATA = \
+ alloc_class.cfg \
+ alloc_class.kshlib
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class.cfg b/tests/zfs-tests/tests/functional/alloc_class/alloc_class.cfg
new file mode 100644
index 000000000000..0bdae47f209d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class.cfg
@@ -0,0 +1,31 @@
+#
+# 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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export ZPOOL_DISK0="$TEST_BASE_DIR/device-0"
+export ZPOOL_DISK1="$TEST_BASE_DIR/device-1"
+export ZPOOL_DISK2="$TEST_BASE_DIR/device-2"
+export ZPOOL_DISKS="${ZPOOL_DISK0} ${ZPOOL_DISK1} ${ZPOOL_DISK2}"
+
+export CLASS_DISK0="$TEST_BASE_DIR/device-3"
+export CLASS_DISK1="$TEST_BASE_DIR/device-4"
+export CLASS_DISK2="$TEST_BASE_DIR/device-5"
+export CLASS_DISK3="$TEST_BASE_DIR/device-6"
+export CLASS_DISKS="${CLASS_DISK0} ${CLASS_DISK1} ${CLASS_DISK2} ${CLASS_DISK3}"
+
+export ZPOOL_DEVSIZE=1G
+export CLASS_DEVSIZE=512M
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class.kshlib b/tests/zfs-tests/tests/functional/alloc_class/alloc_class.kshlib
new file mode 100644
index 000000000000..4c64cff69643
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class.kshlib
@@ -0,0 +1,67 @@
+#
+# 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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.cfg
+
+function disk_setup
+{
+ truncate -s $ZPOOL_DEVSIZE $ZPOOL_DISKS
+ truncate -s $CLASS_DEVSIZE $CLASS_DISKS
+}
+
+function disk_cleanup
+{
+ rm -f $ZPOOL_DEVSIZE $ZPOOL_DISKS 2> /dev/null
+ rm -f $CLASS_DEVSIZE $CLASS_DISKS 2> /dev/null
+}
+
+function cleanup
+{
+ if datasetexists $TESTPOOL ; then
+ zpool destroy -f $TESTPOOL 2> /dev/null
+ fi
+
+ disk_cleanup
+}
+
+#
+# Try zpool status/iostat for given pool
+#
+# $1 pool
+#
+function display_status
+{
+ typeset pool=$1
+
+ typeset -i ret=0
+ zpool status -xv $pool > /dev/null 2>&1
+ ret=$?
+
+ zpool iostat > /dev/null 2>&1
+ ((ret |= $?))
+
+ typeset mntpnt=$(get_prop mountpoint $pool)
+ dd if=/dev/random of=$mntpnt/testfile.$$ &
+ typeset pid=$!
+
+ zpool iostat -v 1 3 > /dev/null
+ ((ret |= $?))
+
+ kill -9 $pid
+
+ return $ret
+}
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_001_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_001_pos.ksh
new file mode 100755
index 000000000000..3237d7cb784f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_001_pos.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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Creating a pool with a special device succeeds, but only if
+# "feature@allocation_classes" is enabled.
+#
+
+verify_runnable "global"
+
+claim="Creating a pool with a special device succeeds."
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+for type in special dedup; do
+ log_mustnot zpool create -d $TESTPOOL $CLASS_DISK0 $type $CLASS_DISK1
+done
+log_must zpool create $TESTPOOL raidz $ZPOOL_DISKS special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+log_must display_status "$TESTPOOL"
+log_must zpool destroy -f "$TESTPOOL"
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh
new file mode 100755
index 000000000000..b2cac59fd414
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh
@@ -0,0 +1,48 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Creating a pool fails when an invalid special device type is specified.
+#
+claim="Creating a pool with an invalid special device type fails."
+
+verify_runnable "global"
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+
+log_mustnot zpool create $TESTPOOL raidz $ZPOOL_DISKS special $CLASS_DISK0
+log_mustnot display_status $TESTPOOL
+log_mustnot zpool destroy -f $TESTPOOL
+
+log_mustnot zpool create $TESTPOOL $ZPOOL_DISKS special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+log_mustnot display_status $TESTPOOL
+log_mustnot zpool destroy -f $TESTPOOL
+
+log_mustnot zpool create $TESTPOOL raidz $ZPOOL_DISKS special raidz \
+ $CLASS_DISK0 $CLASS_DISK1 $CLASS_DISK2
+log_mustnot display_status $TESTPOOL
+log_mustnot zpool destroy -f $TESTPOOL
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.ksh
new file mode 100755
index 000000000000..78d40ce56d4e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.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) 2017, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Adding a special device to a normal pool succeeds.
+#
+claim="Adding a special device to a normal pool succeeds."
+
+verify_runnable "global"
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+
+for type in "" "mirror" "raidz"
+do
+ log_must zpool create $TESTPOOL $type $ZPOOL_DISKS
+
+ if [ "$type" = "mirror" ]; then
+ log_must zpool add $TESTPOOL special mirror \
+ $CLASS_DISK0 $CLASS_DISK1 $CLASS_DISK2
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK0
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK1
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK2
+ elif [ "$type" = "raidz" ]; then
+ log_must zpool add $TESTPOOL special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK0
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK1
+ else
+ log_must zpool add $TESTPOOL special $CLASS_DISK0
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK0
+ fi
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_004_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_004_pos.ksh
new file mode 100755
index 000000000000..79ac9364c257
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_004_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) 2017, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Checking if allocation_classes feature flag status is active after
+# creating a pool with a special device.
+#
+claim="Checking active allocation classes feature flag status successful."
+
+verify_runnable "global"
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+
+typeset ac_value
+typeset stype=""
+typeset sdisks=""
+
+for type in "" "mirror" "raidz"
+do
+ if [ "$type" = "mirror" ]; then
+ stype="mirror"
+ sdisks="${CLASS_DISK0} ${CLASS_DISK1} ${CLASS_DISK2}"
+ elif [ "$type" = "raidz" ]; then
+ stype="mirror"
+ sdisks="${CLASS_DISK0} ${CLASS_DISK1}"
+ else
+ stype=""
+ sdisks="${CLASS_DISK0}"
+ fi
+
+ log_must zpool create $TESTPOOL $type $ZPOOL_DISKS \
+ special $stype $sdisks
+
+ ac_value="$(zpool get -H -o property,value all | \
+ egrep allocation_classes | nawk '{print $2}')"
+ if [ "$ac_value" = "active" ]; then
+ log_note "feature@allocation_classes is active"
+ else
+ log_fail "feature@allocation_classes not active, \
+ status = $ac_value"
+ fi
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_005_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_005_pos.ksh
new file mode 100755
index 000000000000..337114cdb59e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_005_pos.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) 2017, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Checking allocation_classes feature flag value after pool is created
+# (should be enabled) and also after a special device added to existing
+# pool (should be active).
+#
+
+verify_runnable "global"
+
+log_assert "Values of allocation_classes feature flag correct."
+log_onexit cleanup
+
+log_must disk_setup
+
+typeset ac_value
+
+for type in "" "mirror" "raidz"
+do
+ if [ "$type" = "mirror" ]; then
+ log_must zpool create $TESTPOOL $type $ZPOOL_DISK0 $ZPOOL_DISK1
+ else
+ log_must zpool create $TESTPOOL $type $ZPOOL_DISKS
+ fi
+ ac_value="$(zpool get -H -o property,value all | \
+ egrep allocation_classes | awk '{print $2}')"
+ if [ "$ac_value" = "enabled" ]; then
+ log_note "feature@allocation_classes is enabled"
+ else
+ log_fail "feature@allocation_classes not enabled, \
+ status = $ac_value"
+ fi
+
+ if [ "$type" = "" ]; then
+ log_must zpool add $TESTPOOL special $CLASS_DISK0
+ else
+ log_must zpool add $TESTPOOL special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+ fi
+ ac_value="$(zpool get -H -o property,value all | \
+ egrep allocation_classes | awk '{print $2}')"
+ if [ "$ac_value" = "active" ]; then
+ log_note "feature@allocation_classes is active"
+ else
+ log_fail "feature@allocation_classes not active, \
+ status = $ac_value"
+ fi
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Values of allocation_classes feature flag correct."
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_006_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_006_pos.ksh
new file mode 100755
index 000000000000..5852b2876e89
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_006_pos.ksh
@@ -0,0 +1,41 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Using zpool split command to detach disks from mirrored special pool
+# to create a new pool with the detached disks.
+#
+claim="zpool split command succeeds with special devices present."
+
+verify_runnable "global"
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+
+log_must zpool create $TESTPOOL \
+ mirror $ZPOOL_DISK0 $ZPOOL_DISK1 \
+ special mirror $CLASS_DISK0 $CLASS_DISK1
+log_must zpool split $TESTPOOL split_pool
+log_must zpool destroy -f $TESTPOOL
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_007_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_007_pos.ksh
new file mode 100755
index 000000000000..106a6d933aac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_007_pos.ksh
@@ -0,0 +1,41 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Replacing a special device succeeds
+#
+claim="Replacing a special device is successful."
+
+verify_runnable "global"
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+
+log_must zpool create $TESTPOOL raidz $ZPOOL_DISKS \
+ special mirror $CLASS_DISK0 $CLASS_DISK1
+log_must zpool replace $TESTPOOL $CLASS_DISK1 $CLASS_DISK2
+log_must sleep 10
+log_must zpool iostat -H $TESTPOOL $CLASS_DISK2
+log_must zpool destroy -f $TESTPOOL
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_008_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_008_pos.ksh
new file mode 100755
index 000000000000..f73fbbe38c9b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_008_pos.ksh
@@ -0,0 +1,56 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Adding an additional special device to a pool with special succeeds.
+#
+claim="Adding an additional special device succeeds."
+
+verify_runnable "global"
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+
+typeset special_type=""
+typeset create_disks=""
+typeset added_disks=""
+
+for type in "" "raidz"
+do
+ if [ "$type" = "raidz" ]; then
+ special_type="mirror"
+ create_disks="${CLASS_DISK0} ${CLASS_DISK1}"
+ added_disks="${CLASS_DISK2} ${CLASS_DISK3}"
+ else
+ special_type=""
+ create_disks="${CLASS_DISK0}"
+ added_disks="${CLASS_DISK1}"
+ fi
+ log_must zpool create $TESTPOOL $type $ZPOOL_DISKS \
+ special $special_type $create_disks
+ log_must zpool add $TESTPOOL special $special_type $added_disks
+ log_must zpool iostat $TESTPOOL $added_disks
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh
new file mode 100755
index 000000000000..e8061fdabcbd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh
@@ -0,0 +1,69 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018, 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Importing and exporting pool with special device succeeds.
+#
+claim="Import/export of pool with special device mirror succeeds."
+
+verify_runnable "global"
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+
+typeset stype=""
+typeset sdisks=""
+typeset props=""
+
+for type in "" "mirror" "raidz"
+do
+ if [ "$type" = "mirror" ]; then
+ stype="mirror"
+ sdisks="${CLASS_DISK0} ${CLASS_DISK1} ${CLASS_DISK2}"
+ props="-o ashift=12"
+ elif [ "$type" = "raidz" ]; then
+ stype="mirror"
+ sdisks="${CLASS_DISK0} ${CLASS_DISK1}"
+ else
+ stype=""
+ sdisks="${CLASS_DISK0}"
+ fi
+
+ #
+ # 1/3 of the time add the special vdev after creating the pool
+ #
+ if [ $((RANDOM % 3)) -eq 0 ]; then
+ log_must zpool create ${props} $TESTPOOL $type $ZPOOL_DISKS
+ log_must zpool add ${props} $TESTPOOL special $stype $sdisks
+ else
+ log_must zpool create ${props} $TESTPOOL $type $ZPOOL_DISKS \
+ special $stype $sdisks
+ fi
+
+ log_must zpool export $TESTPOOL
+ log_must zpool import -d $TEST_BASE_DIR -s $TESTPOOL
+ log_must display_status $TESTPOOL
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh
new file mode 100755
index 000000000000..2c14c69d8b20
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh
@@ -0,0 +1,50 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Setting the special_small_blocks property to a valid value succeeds.
+#
+
+verify_runnable "global"
+
+claim="Setting the special_small_blocks property to a valid value succeeds."
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+
+log_must zpool create $TESTPOOL raidz $ZPOOL_DISKS special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+
+for value in 0 512 1024 2048 4096 8192 16384 32768 65536 131072
+do
+ log_must zfs set special_small_blocks=$value $TESTPOOL
+ ACTUAL=$(zfs get -p special_small_blocks $TESTPOOL | \
+ grep special_small_blocks | awk '{print $3}')
+ if [ "$ACTUAL" != "$value" ]
+ then
+ log_fail "v. $ACTUAL set for $TESTPOOL, expected v. $value!"
+ fi
+done
+
+log_must zpool destroy -f "$TESTPOOL"
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh
new file mode 100755
index 000000000000..d804e5371ebb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh
@@ -0,0 +1,44 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Setting the special_small_blocks property to invalid values fails.
+# Powers of two from 512 to 1M are allowed.
+#
+
+verify_runnable "global"
+
+claim="Setting the special_small_blocks property to invalid values fails."
+
+log_assert $claim
+log_onexit cleanup
+
+log_must disk_setup
+log_must zpool create $TESTPOOL raidz $ZPOOL_DISKS special mirror \
+ $CLASS_DISK0 $CLASS_DISK1
+
+for value in 256 1025 2097152
+do
+ log_mustnot zfs set special_small_blocks=$value $TESTPOOL
+done
+
+log_must zpool destroy -f "$TESTPOOL"
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_012_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_012_pos.ksh
new file mode 100755
index 000000000000..1cfe6642d8a8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_012_pos.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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Removing a special device from a pool succeeds.
+#
+
+verify_runnable "global"
+
+#
+# Verify the file identified by the input <inode> is written on a special vdev
+# According to the pool layout used in this test vdev_id 3 and 4 are special
+# XXX: move this function to libtest.shlib once we get "Vdev Properties"
+#
+function file_in_special_vdev # <dataset> <inode>
+{
+ typeset dataset="$1"
+ typeset inum="$2"
+
+ zdb -dddddd $dataset $inum | awk '{
+# find DVAs from string "offset level dva" only for L0 (data) blocks
+if (match($0,"L0 [0-9]+")) {
+ dvas[0]=$3
+ dvas[1]=$4
+ dvas[2]=$5
+ for (i = 0; i < 3; ++i) {
+ if (match(dvas[i],"([^:]+):.*")) {
+ dva = substr(dvas[i], RSTART, RLENGTH);
+ # parse DVA from string "vdev:offset:asize"
+ if (split(dva,arr,":") != 3) {
+ print "Error parsing DVA: <" dva ">";
+ exit 1;
+ }
+ # verify vdev is "special"
+ if (arr[1] < 3) {
+ exit 1;
+ }
+ }
+ }
+}}'
+}
+
+#
+# Check that device removal works for special class vdevs
+#
+function check_removal
+{
+ #
+ # Create a non-raidz pool so we can remove top-level vdevs
+ #
+ log_must disk_setup
+ log_must zpool create $TESTPOOL $ZPOOL_DISKS \
+ special $CLASS_DISK0 special $CLASS_DISK1
+ log_must display_status "$TESTPOOL"
+
+ #
+ # Generate some metadata and small blocks in the special class vdev
+ # before removal
+ #
+ typeset -l i=1
+ typeset -l blocks=25
+
+ log_must zfs create -o special_small_blocks=32K -o recordsize=32K \
+ $TESTPOOL/$TESTFS
+ for i in 1 2 3 4; do
+ log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/testfile.$i \
+ bs=1M count=$blocks
+ ((blocks = blocks + 25))
+ done
+ log_must sync_pool $TESTPOOL
+ log_must zpool list -v $TESTPOOL
+
+ # Verify the files were written in the special class vdevs
+ for i in 1 2 3 4; do
+ dataset="$TESTPOOL/$TESTFS"
+ inum="$(get_objnum /$TESTPOOL/$TESTFS/testfile.$i)"
+ log_must file_in_special_vdev $dataset $inum
+ done
+
+ log_must zpool remove $TESTPOOL $CLASS_DISK0
+
+ sleep 5
+ log_must sync_pool $TESTPOOL
+ sleep 1
+
+ log_must zdb -bbcc $TESTPOOL
+ log_must zpool list -v $TESTPOOL
+ log_must zpool destroy -f "$TESTPOOL"
+ log_must disk_cleanup
+}
+
+claim="Removing a special device from a pool succeeds."
+
+log_assert $claim
+log_onexit cleanup
+
+typeset CLASS_DEVSIZE=$CLASS_DEVSIZE
+for CLASS_DEVSIZE in $CLASS_DEVSIZE $ZPOOL_DEVSIZE; do
+ typeset ZPOOL_DISKS=$ZPOOL_DISKS
+ for ZPOOL_DISKS in "$ZPOOL_DISKS" $ZPOOL_DISK0; do
+ check_removal
+ done
+done
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_013_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_013_pos.ksh
new file mode 100755
index 000000000000..2ce22a624291
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_013_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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+#
+# DESCRIPTION:
+# Removing a dedup device from a pool succeeds.
+#
+
+verify_runnable "global"
+
+claim="Removing a dedup device from a pool succeeds."
+
+log_assert $claim
+log_onexit cleanup
+
+#
+# Create a non-raidz pool so we can remove top-level vdevs
+#
+log_must disk_setup
+log_must zpool create $TESTPOOL $ZPOOL_DISKS dedup $CLASS_DISK0
+log_must display_status "$TESTPOOL"
+
+#
+# Generate some dedup data in the dedup class before removal
+#
+
+log_must zfs create -o dedup=on -V 2G $TESTPOOL/$TESTVOL
+
+log_must eval "new_fs $ZVOL_DEVDIR/$TESTPOOL/$TESTVOL >/dev/null 2>&1"
+
+sync_pool
+log_must zpool list -v $TESTPOOL
+
+#
+# remove a dedup allocation vdev
+#
+log_must zpool remove $TESTPOOL $CLASS_DISK0
+
+sleep 5
+log_must sync_pool $TESTPOOL
+sleep 1
+
+log_must zdb -bbcc $TESTPOOL
+
+log_must zpool destroy -f "$TESTPOOL"
+
+log_pass $claim
diff --git a/tests/zfs-tests/tests/functional/alloc_class/cleanup.ksh b/tests/zfs-tests/tests/functional/alloc_class/cleanup.ksh
new file mode 100755
index 000000000000..13775da91936
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/cleanup.ksh
@@ -0,0 +1,27 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018, Delphix
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+verify_runnable "global"
+
+default_cleanup_noexit
+disk_cleanup
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/alloc_class/setup.ksh b/tests/zfs-tests/tests/functional/alloc_class/setup.ksh
new file mode 100755
index 000000000000..bdccdb989563
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/alloc_class/setup.ksh
@@ -0,0 +1,26 @@
+#!/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, Intel Corporation.
+# Copyright (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
+
+verify_runnable "global"
+
+disk_cleanup
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/arc/Makefile.am b/tests/zfs-tests/tests/functional/arc/Makefile.am
new file mode 100644
index 000000000000..809d0346f872
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/arc/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/arc
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ arcstats_runtime_tuning.ksh \
+ dbufstats_001_pos.ksh \
+ dbufstats_002_pos.ksh \
+ dbufstats_003_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/arc/arcstats_runtime_tuning.ksh b/tests/zfs-tests/tests/functional/arc/arcstats_runtime_tuning.ksh
new file mode 100755
index 000000000000..6650b2e1a4d7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/arc/arcstats_runtime_tuning.ksh
@@ -0,0 +1,46 @@
+#!/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, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # Set tunables to their recorded actual size and then to their original
+ # value: this works for previously unconfigured tunables.
+ log_must set_tunable64 ARC_MIN "$MINSIZE"
+ log_must set_tunable64 ARC_MIN "$ZFS_ARC_MIN"
+ log_must set_tunable64 ARC_MAX "$MAXSIZE"
+ log_must set_tunable64 ARC_MAX "$ZFS_ARC_MAX"
+}
+
+log_onexit cleanup
+
+ZFS_ARC_MAX="$(get_tunable ARC_MAX)"
+ZFS_ARC_MIN="$(get_tunable ARC_MIN)"
+MINSIZE="$(get_min_arc_size)"
+MAXSIZE="$(get_max_arc_size)"
+
+log_assert "ARC tunables should be updated dynamically"
+
+for size in $((MAXSIZE/4)) $((MAXSIZE/3)) $((MAXSIZE/2)) $MAXSIZE; do
+ log_must set_tunable64 ARC_MAX "$size"
+ log_must test "$(get_max_arc_size)" == "$size"
+ log_must set_tunable64 ARC_MIN "$size"
+ log_must test "$(get_min_arc_size)" == "$size"
+done
+
+log_pass "ARC tunables can be updated dynamically"
diff --git a/tests/zfs-tests/tests/functional/arc/cleanup.ksh b/tests/zfs-tests/tests/functional/arc/cleanup.ksh
new file mode 100755
index 000000000000..63a47ba7daf3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/arc/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) 2017, Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/arc/dbufstats_001_pos.ksh b/tests/zfs-tests/tests/functional/arc/dbufstats_001_pos.ksh
new file mode 100755
index 000000000000..4884f11bb811
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/arc/dbufstats_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 (c) 2017, Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+
+#
+# DESCRIPTION:
+# Ensure stats presented in /proc/spl/kstat/zfs/dbufstats are correct
+# based on /proc/spl/kstat/zfs/dbufs.
+#
+# STRATEGY:
+# 1. Generate a file with random data in it
+# 2. Store output from dbufs kstat
+# 3. Store output from dbufstats kstat
+# 4. Compare stats presented in dbufstats with stat generated using
+# dbufstat and the dbufs kstat output
+#
+
+DBUFSTATS_FILE=$(mktemp $TEST_BASE_DIR/dbufstats.out.XXXXXX)
+DBUFS_FILE=$(mktemp $TEST_BASE_DIR/dbufs.out.XXXXXX)
+
+function cleanup
+{
+ log_must rm -f $TESTDIR/file $DBUFS_FILE $DBUFSTATS_FILE
+}
+
+function testdbufstat # stat_name dbufstat_filter
+{
+ name=$1
+ filter=""
+
+ [[ -n "$2" ]] && filter="-F $2"
+
+ from_dbufstat=$(grep -w "$name" "$DBUFSTATS_FILE" | awk '{ print $3 }')
+ from_dbufs=$(dbufstat -bxn -i "$DBUFS_FILE" "$filter" | wc -l)
+
+ within_tolerance $from_dbufstat $from_dbufs 15 \
+ || log_fail "Stat $name exceeded tolerance"
+}
+
+verify_runnable "both"
+
+log_assert "dbufstats produces correct statistics"
+
+log_onexit cleanup
+
+log_must file_write -o create -f "$TESTDIR/file" -b 1048576 -c 20 -d R
+log_must zpool sync
+
+log_must eval "cat /proc/spl/kstat/zfs/dbufs > $DBUFS_FILE"
+log_must eval "cat /proc/spl/kstat/zfs/dbufstats > $DBUFSTATS_FILE"
+
+for level in {0..11}; do
+ testdbufstat "cache_level_$level" "dbc=1,level=$level"
+done
+
+testdbufstat "cache_count" "dbc=1"
+testdbufstat "hash_elements" ""
+
+log_pass "dbufstats produces correct statistics passed"
diff --git a/tests/zfs-tests/tests/functional/arc/dbufstats_002_pos.ksh b/tests/zfs-tests/tests/functional/arc/dbufstats_002_pos.ksh
new file mode 100755
index 000000000000..dc30b660656d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/arc/dbufstats_002_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 (c) 2017, Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+
+#
+# DESCRIPTION:
+# Ensure that dbufs move from mru to mfu as expected.
+#
+# STRATEGY:
+# 1. Set dbuf cache size to a small size (10M for this test)
+# 2. Generate a file with random data (small enough to fit in cache)
+# 3. zpool sync to remove dbufs from anon list in ARC
+# 4. Obtain the object ID using linux stat command
+# 5. Ensure that all dbufs are on the mru list in the ARC
+# 6. Generate another random file large enough to flush dbuf cache
+# 7. cat the first generated file
+# 8. Ensure that at least some dbufs moved to the mfu list in the ARC
+#
+
+DBUFS_FILE=$(mktemp $TEST_BASE_DIR/dbufs.out.XXXXXX)
+
+function cleanup
+{
+ log_must rm -f $TESTDIR/file $TESTDIR/file2 $DBUFS_FILE
+}
+
+verify_runnable "both"
+
+log_assert "dbufs move from mru to mfu list"
+
+log_onexit cleanup
+
+log_must file_write -o create -f "$TESTDIR/file" -b 1048576 -c 1 -d R
+log_must zpool sync
+
+objid=$(stat --format="%i" "$TESTDIR/file")
+log_note "Object ID for $TESTDIR/file is $objid"
+
+log_must eval "cat /proc/spl/kstat/zfs/dbufs > $DBUFS_FILE"
+dbuf=$(dbufstat -bxn -i "$DBUFS_FILE" -F "object=$objid" | wc -l)
+mru=$(dbufstat -bxn -i "$DBUFS_FILE" -F "object=$objid,list=1" | wc -l)
+mfu=$(dbufstat -bxn -i "$DBUFS_FILE" -F "object=$objid,list=3" | wc -l)
+log_note "dbuf count is $dbuf, mru count is $mru, mfu count is $mfu"
+verify_ne "0" "$mru" "mru count"
+verify_eq "0" "$mfu" "mfu count"
+
+log_must eval "cat $TESTDIR/file > /dev/null"
+log_must eval "cat /proc/spl/kstat/zfs/dbufs > $DBUFS_FILE"
+dbuf=$(dbufstat -bxn -i "$DBUFS_FILE" -F "object=$objid" | wc -l)
+mru=$(dbufstat -bxn -i "$DBUFS_FILE" -F "object=$objid,list=1" | wc -l)
+mfu=$(dbufstat -bxn -i "$DBUFS_FILE" -F "object=$objid,list=3" | wc -l)
+log_note "dbuf count is $dbuf, mru count is $mru, mfu count is $mfu"
+verify_ne "0" "$mfu" "mfu count"
+
+log_pass "dbufs move from mru to mfu list passed"
diff --git a/tests/zfs-tests/tests/functional/arc/dbufstats_003_pos.ksh b/tests/zfs-tests/tests/functional/arc/dbufstats_003_pos.ksh
new file mode 100755
index 000000000000..91cec74881a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/arc/dbufstats_003_pos.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 (c) 2015 by Lawrence Livermore National Security, LLC.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+set -A args "" "-b" "-d" "-r" "-v" "-s \",\"" "-x" "-n"
+
+log_assert "dbufstat generates output and doesn't return an error code"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_must eval "dbufstat ${args[i]} >/dev/null"
+ ((i = i + 1))
+done
+
+# A simple test of dbufstat filter functionality
+log_must eval "dbufstat -F object=10,dbc=1,pool=$TESTPOOL >/dev/null"
+
+log_pass "dbufstat generates output and doesn't return an error code"
diff --git a/tests/zfs-tests/tests/functional/arc/setup.ksh b/tests/zfs-tests/tests/functional/arc/setup.ksh
new file mode 100755
index 000000000000..37b8f352cc64
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/arc/setup.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 (c) 2017, Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/atime/Makefile.am b/tests/zfs-tests/tests/functional/atime/Makefile.am
new file mode 100644
index 000000000000..63d510b99e75
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/atime
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ atime_001_pos.ksh \
+ atime_002_neg.ksh \
+ atime_003_pos.ksh \
+ root_atime_off.ksh \
+ root_atime_on.ksh \
+ root_relatime_on.ksh
+
+dist_pkgdata_DATA = \
+ atime.cfg \
+ atime_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/atime/atime.cfg b/tests/zfs-tests/tests/functional/atime/atime.cfg
new file mode 100644
index 000000000000..c1532eb47fd3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/atime.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+export TESTCLONE=testclone$$
+export TESTSNAP=testsnap$$
+
+export TESTFILE=testfile
diff --git a/tests/zfs-tests/tests/functional/atime/atime_001_pos.ksh b/tests/zfs-tests/tests/functional/atime/atime_001_pos.ksh
new file mode 100755
index 000000000000..274a4da0dcb9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/atime_001_pos.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/tests/functional/atime/atime_common.kshlib
+
+#
+# DESCRIPTION:
+# When atime=on, verify the access time for files is updated when read. It
+# is available to fs and clone. To snapshot, it is unavailable.
+#
+# STRATEGY:
+# 1. Create pool and fs.
+# 2. Create '$TESTFILE' for fs.
+# 3. Create snapshot and clone.
+# 4. Setting atime=on on datasets except snapshot, and read '$TESTFILE'.
+# 5. Expect the access time is updated on datasets except snapshot.
+#
+
+verify_runnable "both"
+
+log_assert "Setting atime=on, the access time for files is updated when read."
+log_onexit cleanup
+
+#
+# Create $TESTFILE, snapshot and clone.
+#
+setup_snap_clone
+
+for dst in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE $TESTPOOL/$TESTFS@$TESTSNAP
+do
+ typeset mtpt=$(get_prop mountpoint $dst)
+
+ if [[ $dst == $TESTPOOL/$TESTFS@$TESTSNAP ]]; then
+ mtpt=$(snapshot_mountpoint $dst)
+ log_mustnot check_atime_updated $mtpt/$TESTFILE
+ else
+ if is_linux; then
+ log_must zfs set relatime=off $dst
+ fi
+
+ log_must zfs set atime=on $dst
+ log_must check_atime_updated $mtpt/$TESTFILE
+ log_must check_atime_updated $mtpt/$TESTFILE
+ fi
+done
+
+log_pass "Verify the property atime=on passed."
diff --git a/tests/zfs-tests/tests/functional/atime/atime_002_neg.ksh b/tests/zfs-tests/tests/functional/atime/atime_002_neg.ksh
new file mode 100755
index 000000000000..c8579337c053
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/atime_002_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/tests/functional/atime/atime_common.kshlib
+
+#
+# DESCRIPTION:
+# When atime=off, verify the access time for files is not updated when read.
+# It is available to pool, fs snapshot and clone.
+#
+# STRATEGY:
+# 1. Create pool, fs.
+# 2. Create '$TESTFILE' for fs.
+# 3. Create snapshot and clone.
+# 4. Setting atime=off on dataset and read '$TESTFILE'.
+# 5. Verify the access time is not updated.
+#
+
+verify_runnable "both"
+
+log_assert "Setting atime=off, the access time for files will not be updated \
+ when read."
+log_onexit cleanup
+
+#
+# Create $TESTFILE, snapshot and clone.
+#
+setup_snap_clone
+
+for dst in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE $TESTPOOL/$TESTFS@$TESTSNAP
+do
+ typeset mtpt=$(get_prop mountpoint $dst)
+
+ if [[ $dst == $TESTPOOL/$TESTFS@$TESTSNAP ]]; then
+ mtpt=$(snapshot_mountpoint $dst)
+ else
+ log_must zfs set atime=off $dst
+ fi
+
+ log_mustnot check_atime_updated $mtpt/$TESTFILE
+done
+
+log_pass "Verify the property atime=off passed."
diff --git a/tests/zfs-tests/tests/functional/atime/atime_003_pos.ksh b/tests/zfs-tests/tests/functional/atime/atime_003_pos.ksh
new file mode 100755
index 000000000000..d3eec92effbc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/atime_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/tests/functional/atime/atime_common.kshlib
+
+#
+# DESCRIPTION:
+# When relatime=on, verify the access time for files is updated when first
+# read but not on second.
+# It is available to fs and clone. To snapshot, it is unavailable.
+#
+# STRATEGY:
+# 1. Create pool and fs.
+# 2. Create '$TESTFILE' for fs.
+# 3. Create snapshot and clone.
+# 4. Setting atime=on and relatime=on on datasets.
+# 5. Expect the access time is updated for first read but not on second.
+#
+
+verify_runnable "both"
+
+log_assert "Setting relatime=on, the access time for files is updated when \
+ when read the first time, but not second time."
+log_onexit cleanup
+
+#
+# Create $TESTFILE, snapshot and clone.
+#
+setup_snap_clone
+
+for dst in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE $TESTPOOL/$TESTFS@$TESTSNAP
+do
+ typeset mtpt=$(get_prop mountpoint $dst)
+
+ if [[ $dst == $TESTPOOL/$TESTFS@$TESTSNAP ]]; then
+ mtpt=$(snapshot_mountpoint $dst)
+ log_mustnot check_atime_updated $mtpt/$TESTFILE
+ else
+ log_must zfs set atime=on $dst
+ log_must zfs set relatime=on $dst
+ log_must check_atime_updated $mtpt/$TESTFILE
+ log_mustnot check_atime_updated $mtpt/$TESTFILE
+ fi
+done
+
+log_pass "Verify the property relatime=on passed."
diff --git a/tests/zfs-tests/tests/functional/atime/atime_common.kshlib b/tests/zfs-tests/tests/functional/atime/atime_common.kshlib
new file mode 100644
index 000000000000..fce85c379865
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/atime_common.kshlib
@@ -0,0 +1,102 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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/atime/atime.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Check if the access time for specified file is updated.
+#
+# $1 Given an absolute path to a file name
+#
+# Return value:
+# 0 -> The access time is updated.
+# 1 -> The access time is not updated.
+#
+function check_atime_updated
+{
+ typeset filename=$1
+
+ if is_linux; then
+ typeset before=$(stat -c %X $filename)
+ sleep 2
+ elif is_freebsd; then
+ typeset before=$(stat -f %a $filename)
+ sleep 2
+ else
+ typeset before=$(ls -Eu $filename | awk '{print $7}')
+ fi
+
+ log_must cat $filename
+
+ if is_linux; then
+ typeset after=$(stat -c %X $filename)
+ elif is_freebsd; then
+ typeset after=$(stat -f %a $filename)
+ else
+ typeset after=$(ls -Eu $filename | awk '{print $7}')
+ fi
+
+ if [[ $before != $after ]]; then
+ return 0
+ else
+ return 1
+ fi
+}
+
+function setup_snap_clone
+{
+ if [ -d "/$TESTPOOL/$TESTFS" ]; then
+ # No mountpoint case (default).
+ log_must touch /$TESTPOOL/$TESTFS/$TESTFILE
+ else
+ # Create two file to verify snapshot.
+ log_must touch $TESTDIR/$TESTFILE
+ fi
+
+ create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+ create_clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE
+}
+
+function reset_atime
+{
+ zfs inherit atime $TESTPOOL
+ zfs inherit atime $TESTPOOL/$TESTFS
+ zfs inherit atime $TESTPOOL/$TESTCLONE
+ zfs inherit relatime $TESTPOOL
+ zfs inherit relatime $TESTPOOL/$TESTFS
+ zfs inherit relatime $TESTPOOL/$TESTCLONE
+}
+
+function cleanup
+{
+ destroy_clone $TESTPOOL/$TESTCLONE
+ destroy_snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+}
diff --git a/tests/zfs-tests/tests/functional/atime/cleanup.ksh b/tests/zfs-tests/tests/functional/atime/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/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/atime/root_atime_off.ksh b/tests/zfs-tests/tests/functional/atime/root_atime_off.ksh
new file mode 100755
index 000000000000..2fbf06b13773
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/root_atime_off.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.
+# Copyright (c) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/atime/atime_common.kshlib
+
+#
+# DESCRIPTION:
+# When atime=off, verify the access time for files is not updated when read.
+# It is available to pool, fs snapshot and clone.
+#
+# STRATEGY:
+# 1. Create pool, fs.
+# 2. Create '$TESTFILE' for fs.
+# 3. Create snapshot and clone.
+# 4. Setting atime=off on dataset and read '$TESTFILE'.
+# 5. Verify the access time is not updated.
+#
+
+verify_runnable "both"
+
+log_assert "Setting atime=off, the access time for files will not be updated \
+ when read."
+log_onexit cleanup
+
+#
+# Create $TESTFILE, snapshot and clone.
+# Same as 002 except that atime applies to root dataset (ZoL#8675).
+#
+setup_snap_clone
+reset_atime
+
+for dst in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE $TESTPOOL/$TESTFS@$TESTSNAP
+do
+ typeset mtpt=$(get_prop mountpoint $dst)
+
+ if [[ $dst == $TESTPOOL/$TESTFS@$TESTSNAP ]]; then
+ mtpt=$(snapshot_mountpoint $dst)
+ else
+ log_must zfs set atime=off $(dirname $dst)
+ fi
+
+ log_mustnot check_atime_updated $mtpt/$TESTFILE
+done
+
+log_pass "Verify the property atime=off passed."
diff --git a/tests/zfs-tests/tests/functional/atime/root_atime_on.ksh b/tests/zfs-tests/tests/functional/atime/root_atime_on.ksh
new file mode 100755
index 000000000000..3976523b0b13
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/root_atime_on.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) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/atime/atime_common.kshlib
+
+#
+# DESCRIPTION:
+# When atime=on, verify the access time for files is updated when read. It
+# is available to fs and clone. To snapshot, it is unavailable.
+#
+# STRATEGY:
+# 1. Create pool and fs.
+# 2. Create '$TESTFILE' for fs.
+# 3. Create snapshot and clone.
+# 4. Setting atime=on on datasets except snapshot, and read '$TESTFILE'.
+# 5. Expect the access time is updated on datasets except snapshot.
+#
+
+verify_runnable "both"
+
+log_assert "Setting atime=on, the access time for files is updated when read."
+log_onexit cleanup
+
+#
+# Create $TESTFILE, snapshot and clone.
+# Same as 001 except that atime/relatime applies to root dataset (ZoL#8675).
+#
+setup_snap_clone
+reset_atime
+
+for dst in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE $TESTPOOL/$TESTFS@$TESTSNAP
+do
+ typeset mtpt=$(get_prop mountpoint $dst)
+
+ if [[ $dst == $TESTPOOL/$TESTFS@$TESTSNAP ]]; then
+ mtpt=$(snapshot_mountpoint $dst)
+ log_mustnot check_atime_updated $mtpt/$TESTFILE
+ else
+ if is_linux; then
+ log_must zfs set relatime=off $(dirname $dst)
+ fi
+
+ log_must zfs set atime=on $(dirname $dst)
+ log_must check_atime_updated $mtpt/$TESTFILE
+ log_must check_atime_updated $mtpt/$TESTFILE
+ fi
+done
+
+log_pass "Verify the property atime=on passed."
diff --git a/tests/zfs-tests/tests/functional/atime/root_relatime_on.ksh b/tests/zfs-tests/tests/functional/atime/root_relatime_on.ksh
new file mode 100755
index 000000000000..c919e9f29883
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/root_relatime_on.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) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/atime/atime_common.kshlib
+
+#
+# DESCRIPTION:
+# When relatime=on, verify the access time for files is updated when first
+# read but not on second.
+# It is available to fs and clone. To snapshot, it is unavailable.
+#
+# STRATEGY:
+# 1. Create pool and fs.
+# 2. Create '$TESTFILE' for fs.
+# 3. Create snapshot and clone.
+# 4. Setting atime=on and relatime=on on datasets.
+# 5. Expect the access time is updated for first read but not on second.
+#
+
+verify_runnable "both"
+
+log_assert "Setting relatime=on, the access time for files is updated when \
+ when read the first time, but not second time."
+log_onexit cleanup
+
+#
+# Create $TESTFILE, snapshot and clone.
+# Same as 003 except that atime/relatime applies to root dataset (ZoL#8675).
+#
+setup_snap_clone
+reset_atime
+
+for dst in $TESTPOOL/$TESTFS $TESTPOOL/$TESTCLONE $TESTPOOL/$TESTFS@$TESTSNAP
+do
+ typeset mtpt=$(get_prop mountpoint $dst)
+
+ if [[ $dst == $TESTPOOL/$TESTFS@$TESTSNAP ]]; then
+ mtpt=$(snapshot_mountpoint $dst)
+ log_mustnot check_atime_updated $mtpt/$TESTFILE
+ else
+ log_must zfs set atime=on $(dirname $dst)
+ log_must zfs set relatime=on $(dirname $dst)
+ log_must check_atime_updated $mtpt/$TESTFILE
+ log_mustnot check_atime_updated $mtpt/$TESTFILE
+ fi
+done
+
+log_pass "Verify the property relatime=on passed."
diff --git a/tests/zfs-tests/tests/functional/atime/setup.ksh b/tests/zfs-tests/tests/functional/atime/setup.ksh
new file mode 100755
index 000000000000..3720e7521cc2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/atime/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_setup_no_mountpoint $DISK
diff --git a/tests/zfs-tests/tests/functional/bootfs/Makefile.am b/tests/zfs-tests/tests/functional/bootfs/Makefile.am
new file mode 100644
index 000000000000..15a6e202c311
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/bootfs
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ bootfs_001_pos.ksh \
+ bootfs_002_neg.ksh \
+ bootfs_003_pos.ksh \
+ bootfs_004_neg.ksh \
+ bootfs_005_neg.ksh \
+ bootfs_006_pos.ksh \
+ bootfs_007_pos.ksh \
+ bootfs_008_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_001_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_001_pos.ksh
new file mode 100755
index 000000000000..3e9357063bed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_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 2015 Nexenta Systems, Inc.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+#
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Valid datasets and snapshots are accepted as bootfs property values
+#
+# STRATEGY:
+# 1. Create a set of datasets and snapshots in a test pool
+# 2. Try setting them as boot filesystems
+#
+
+verify_runnable "global"
+
+function cleanup {
+ if poolexists $TESTPOOL ; then
+ log_must zpool destroy $TESTPOOL
+ fi
+
+ if [[ -f $VDEV ]]; then
+ log_must rm -f $VDEV
+ fi
+}
+
+zpool set 2>&1 | grep bootfs > /dev/null
+if [ $? -ne 0 ]
+then
+ log_unsupported "bootfs pool property not supported on this release."
+fi
+
+log_assert "Valid datasets are accepted as bootfs property values"
+log_onexit cleanup
+
+typeset VDEV=$TESTDIR/bootfs_001_pos_a.$$.dat
+
+log_must mkfile $MINVDEVSIZE $VDEV
+create_pool "$TESTPOOL" "$VDEV"
+log_must zfs create $TESTPOOL/$TESTFS
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap
+log_must zfs clone $TESTPOOL/$TESTFS@snap $TESTPOOL/clone
+
+log_must zpool set bootfs=$TESTPOOL/$TESTFS $TESTPOOL
+log_must zpool set bootfs=$TESTPOOL/$TESTFS@snap $TESTPOOL
+log_must zpool set bootfs=$TESTPOOL/clone $TESTPOOL
+
+log_must zfs promote $TESTPOOL/clone
+log_must zpool set bootfs=$TESTPOOL/clone $TESTPOOL
+log_pass "Valid datasets are accepted as bootfs property values"
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_002_neg.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_002_neg.ksh
new file mode 100755
index 000000000000..6a72bfcdc40c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_002_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 2015 Nexenta Systems, Inc.
+#
+
+#
+# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
+#
+
+#
+# Copyright (c) 2012, 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Invalid datasets are rejected as boot property values
+#
+# STRATEGY:
+#
+# 1. Create a zvol
+# 2. Verify that we can't set the bootfs to that dataset
+#
+
+verify_runnable "global"
+
+function cleanup {
+ if datasetexists $TESTPOOL/vol
+ then
+ log_must zfs destroy $TESTPOOL/vol
+ fi
+ if poolexists $TESTPOOL
+ then
+ log_must zpool destroy $TESTPOOL
+ fi
+ if [[ -f $VDEV ]]; then
+ log_must rm -f $VDEV
+ fi
+}
+
+
+zpool set 2>&1 | grep bootfs > /dev/null
+if [ $? -ne 0 ]
+then
+ log_unsupported "bootfs pool property not supported on this release."
+fi
+
+log_assert "Invalid datasets are rejected as boot property values"
+log_onexit cleanup
+
+typeset VDEV=$TESTDIR/bootfs_002_neg_a.$$.dat
+
+log_must mkfile 400m $VDEV
+create_pool "$TESTPOOL" "$VDEV"
+log_must zfs create -V 10m $TESTPOOL/vol
+block_device_wait
+
+log_mustnot zpool set bootfs=$TESTPOOL/vol $TESTPOOL
+
+log_pass "Invalid datasets are rejected as boot property values"
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_003_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_003_pos.ksh
new file mode 100755
index 000000000000..e719b94e2763
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_003_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 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
+
+#
+# DESCRIPTION:
+#
+# Valid pool names are accepted
+#
+# STRATEGY:
+# 1. Using a list of valid pool names
+# 2. Create a filesystem in that pool
+# 2. Verify we can set the bootfs to that filesystem
+#
+
+verify_runnable "global"
+
+set -A pools "pool.$$" "pool123" "mypool"
+
+function cleanup {
+ if poolexists $POOL ; then
+ log_must zpool destroy $POOL
+ fi
+ rm $TESTDIR/bootfs_003.$$.dat
+}
+
+
+zpool set 2>&1 | grep bootfs > /dev/null
+if [ $? -ne 0 ]
+then
+ log_unsupported "bootfs pool property not supported on this release."
+fi
+
+log_onexit cleanup
+
+log_assert "Valid pool names are accepted by zpool set bootfs"
+mkfile $MINVDEVSIZE $TESTDIR/bootfs_003.$$.dat
+
+typeset -i i=0;
+
+while [ $i -lt "${#pools[@]}" ]
+do
+ POOL=${pools[$i]}
+ log_must zpool create $POOL $TESTDIR/bootfs_003.$$.dat
+ log_must zfs create $POOL/$TESTFS
+
+ log_must zpool set bootfs=$POOL/$TESTFS $POOL
+ RES=$(zpool get bootfs $POOL | tail -1 | awk '{print $3}' )
+ if [ $RES != "$POOL/$TESTFS" ]
+ then
+ log_fail "Expected $RES == $POOL/$TESTFS"
+ fi
+ log_must zpool destroy $POOL
+ i=$(( $i + 1 ))
+done
+
+log_pass "Valid pool names are accepted by zpool set bootfs"
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_004_neg.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_004_neg.ksh
new file mode 100755
index 000000000000..97b456aade3e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_004_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 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:
+#
+# Invalid pool names are rejected by zpool set bootfs
+#
+# STRATEGY:
+# 1. Try to set bootfs on some non-existent pools
+#
+#
+#
+
+verify_runnable "global"
+
+set -A pools "pool//$$" "pool%d123" "mirror" "c0t0d0s0" "pool*23*" "*po!l" \
+ "%s££%^"
+
+function cleanup {
+ if poolexists $POOL; then
+ log_must zpool destroy $POOL
+ fi
+ rm $TESTDIR/bootfs_004.$$.dat
+}
+
+
+zpool set 2>&1 | grep bootfs > /dev/null
+if [ $? -ne 0 ]
+then
+ log_unsupported "bootfs pool property not supported on this release."
+fi
+
+log_assert "Invalid pool names are rejected by zpool set bootfs"
+log_onexit cleanup
+
+# here, we build up a large string and add it to the list of pool names
+# 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
+pools[${#pools[@]}]="$bigname"
+
+
+
+mkfile $MINVDEVSIZE $TESTDIR/bootfs_004.$$.dat
+
+typeset -i i=0;
+
+while [ $i -lt "${#pools[@]}" ]
+do
+ POOL=${pools[$i]}/$TESTFS
+ log_mustnot zpool create $POOL $TESTDIR/bootfs_004.$$.dat
+ log_mustnot zfs create $POOL/$TESTFS
+ log_mustnot zpool set bootfs=$POOL/$TESTFS $POOL
+
+ i=$(( $i + 1 ))
+done
+
+log_pass "Invalid pool names are rejected by zpool set bootfs"
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.ksh
new file mode 100755
index 000000000000..42c82b88fba6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_005_neg.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 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
+. $STF_SUITE/tests/functional/cli_root/zpool_upgrade/zpool_upgrade.kshlib
+
+#
+# DESCRIPTION:
+#
+# Boot properties cannot be set on pools with older versions
+#
+# STRATEGY:
+# 1. Copy and import some pools of older versions
+# 2. Create a filesystem on each
+# 3. Verify that zpool set bootfs fails on each
+#
+
+verify_runnable "global"
+
+function cleanup {
+
+ #
+ # we need destroy pools that created on top of $TESTPOOL first
+ #
+ typeset pool_name
+ for config in $CONFIGS; do
+ pool_name=$(eval echo \$ZPOOL_VERSION_${config}_NAME)
+ destroy_pool $pool_name
+ done
+
+ destroy_pool $TESTPOOL
+}
+
+log_assert "Boot properties cannot be set on pools with older versions"
+
+# These are configs from zpool_upgrade.cfg - see that file for more info.
+CONFIGS="1 2 3"
+
+log_onexit cleanup
+log_must zpool create -f $TESTPOOL $DISKS
+
+for config in $CONFIGS
+do
+ create_old_pool $config
+ POOL_NAME=$(eval echo \$ZPOOL_VERSION_${config}_NAME)
+ log_must zfs create $POOL_NAME/$TESTFS
+ log_mustnot zpool set bootfs=$POOL_NAME/$TESTFS $POOL_NAME
+ log_must destroy_upgraded_pool $config
+done
+
+log_pass "Boot properties cannot be set on pools with older versions"
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_006_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_006_pos.ksh
new file mode 100755
index 000000000000..d29fe7e89c50
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_006_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 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
+
+#
+# DESCRIPTION:
+#
+# Pools of correct vdev types accept boot property
+#
+# STRATEGY:
+# 1. create pools of each vdev type (raid, raidz, raidz2, mirror + hotspares)
+# 2. verify we can set bootfs on each pool type according to design
+#
+
+verify_runnable "global"
+
+
+zpool set 2>&1 | grep bootfs > /dev/null
+if [ $? -ne 0 ]
+then
+ log_unsupported "bootfs pool property not supported on this release."
+fi
+
+VDEV1=$TESTDIR/bootfs_006_pos_a.$$.dat
+VDEV2=$TESTDIR/bootfs_006_pos_b.$$.dat
+VDEV3=$TESTDIR/bootfs_006_pos_c.$$.dat
+VDEV4=$TESTDIR/bootfs_006_pos_d.$$.dat
+
+function verify_bootfs { # $POOL
+ POOL=$1
+ log_must zfs create $POOL/$TESTFS
+
+ log_must zpool set bootfs=$POOL/$TESTFS $POOL
+ VAL=$(zpool get bootfs $POOL | tail -1 | awk '{print $3}' )
+ if [ $VAL != "$POOL/$TESTFS" ]
+ then
+ log_must zpool status -v $POOL
+ log_fail \
+ "set/get failed on $POOL - expected $VAL == $POOL/$TESTFS"
+ fi
+ log_must zpool destroy $POOL
+}
+
+function verify_no_bootfs { # $POOL
+ POOL=$1
+ log_must zfs create $POOL/$TESTFS
+ log_mustnot zpool set bootfs=$POOL/$TESTFS $POOL
+ VAL=$(zpool get bootfs $POOL | tail -1 | awk '{print $3}' )
+ if [ $VAL == "$POOL/$TESTFS" ]
+ then
+ log_must zpool status -v $POOL
+ log_fail "set/get unexpectedly failed $VAL != $POOL/$TESTFS"
+ fi
+ log_must zpool destroy $POOL
+}
+
+function cleanup {
+ if poolexists $TESTPOOL
+ then
+ log_must zpool destroy $TESTPOOL
+ fi
+ log_must rm $VDEV1 $VDEV2 $VDEV3 $VDEV4
+}
+
+log_assert "Pools of correct vdev types accept boot property"
+
+
+
+log_onexit cleanup
+log_must mkfile $MINVDEVSIZE $VDEV1 $VDEV2 $VDEV3 $VDEV4
+
+
+## the following configurations are supported bootable pools
+
+# normal
+log_must zpool create $TESTPOOL $VDEV1
+verify_bootfs $TESTPOOL
+
+# normal + hotspare
+log_must zpool create $TESTPOOL $VDEV1 spare $VDEV2
+verify_bootfs $TESTPOOL
+
+# mirror
+log_must zpool create $TESTPOOL mirror $VDEV1 $VDEV2
+verify_bootfs $TESTPOOL
+
+# mirror + hotspare
+log_must zpool create $TESTPOOL mirror $VDEV1 $VDEV2 spare $VDEV3
+verify_bootfs $TESTPOOL
+
+if is_linux || is_freebsd; then
+ # stripe
+ log_must zpool create $TESTPOOL $VDEV1 $VDEV2
+ verify_bootfs $TESTPOOL
+
+ # stripe + hotspare
+ log_must zpool create $TESTPOOL $VDEV1 $VDEV2 spare $VDEV3
+ verify_bootfs $TESTPOOL
+else
+ ## the following configurations are not supported as bootable pools
+
+ # stripe
+ log_must zpool create $TESTPOOL $VDEV1 $VDEV2
+ verify_no_bootfs $TESTPOOL
+
+ # stripe + hotspare
+ log_must zpool create $TESTPOOL $VDEV1 $VDEV2 spare $VDEV3
+ verify_no_bootfs $TESTPOOL
+fi
+
+# raidz
+log_must zpool create $TESTPOOL raidz $VDEV1 $VDEV2
+verify_bootfs $TESTPOOL
+
+# raidz + hotspare
+log_must zpool create $TESTPOOL raidz $VDEV1 $VDEV2 spare $VDEV3
+verify_bootfs $TESTPOOL
+
+# raidz2
+log_must zpool create $TESTPOOL raidz2 $VDEV1 $VDEV2 $VDEV3
+verify_bootfs $TESTPOOL
+
+# raidz2 + hotspare
+log_must zpool create $TESTPOOL raidz2 $VDEV1 $VDEV2 $VDEV3 spare $VDEV4
+verify_bootfs $TESTPOOL
+
+log_pass "Pools of correct vdev types accept boot property"
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_007_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_007_pos.ksh
new file mode 100755
index 000000000000..2e71df86c62b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_007_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2015 Nexenta Systems, Inc.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Setting bootfs on a pool which was configured with the whole disk
+# (i.e. EFI) works.
+#
+# STRATEGY:
+# 1. create a pool with a whole disk
+# 2. create a filesystem on this pool
+# 3. verify we can set bootfs on the filesystem we just created.
+#
+
+verify_runnable "global"
+
+function cleanup {
+ if poolexists $TESTPOOL ; then
+ destroy_pool "$TESTPOOL"
+ fi
+}
+
+log_onexit cleanup
+
+DISK=${DISKS%% *}
+typeset EFI_BOOTFS=$TESTPOOL/efs
+typeset assert_mesg="setting bootfs on a pool which was configured with the \
+ whole disk works"
+
+log_assert $assert_mesg
+create_pool "$TESTPOOL" "$DISK"
+log_must zfs create $EFI_BOOTFS
+
+log_must zpool set bootfs=$EFI_BOOTFS $TESTPOOL
+
+log_pass $assert_mesg
diff --git a/tests/zfs-tests/tests/functional/bootfs/bootfs_008_pos.ksh b/tests/zfs-tests/tests/functional/bootfs/bootfs_008_pos.ksh
new file mode 100755
index 000000000000..bcf74f2cdee2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/bootfs_008_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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# setting bootfs on a dataset which has gzip compression enabled will not fail
+#
+# STRATEGY:
+# 1. create pools based on a valid vdev
+# 2. create a filesystem on this pool and set the compression property to
+# gzip1-9
+# 3. set the pool's bootfs property to filesystem we just configured which
+# should not fail
+#
+
+verify_runnable "global"
+
+function cleanup {
+ if poolexists $TESTPOOL ; then
+ destroy_pool "$TESTPOOL"
+ fi
+
+ if [[ -f $VDEV ]]; then
+ log_must rm -f $VDEV
+ fi
+}
+
+typeset assert_msg="setting bootfs on a dataset which has gzip \
+ compression enabled will not fail"
+
+typeset VDEV=$TEST_BASE_DIR/bootfs_008_pos_a.$$.dat
+typeset COMP_FS=$TESTPOOL/COMP_FS
+
+log_onexit cleanup
+log_assert $assert_msg
+
+log_must mkfile $MINVDEVSIZE $VDEV
+log_must zpool create $TESTPOOL $VDEV
+log_must zfs create $COMP_FS
+
+typeset -i i=0
+set -A gtype "gzip" "gzip-1" "gzip-2" "gzip-3" "gzip-4" "gzip-5" \
+ "gzip-6" "gzip-7" "gzip-8" "gzip-9"
+
+while (( i < ${#gtype[@]} )); do
+ log_must zfs set compression=${gtype[i]} $COMP_FS
+ log_must zpool set bootfs=$COMP_FS $TESTPOOL
+ log_must zfs set compression=off $COMP_FS
+ (( i += 1 ))
+done
+
+log_pass $assert_msg
diff --git a/tests/zfs-tests/tests/functional/bootfs/cleanup.ksh b/tests/zfs-tests/tests/functional/bootfs/cleanup.ksh
new file mode 100755
index 000000000000..71d8ced18206
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/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 (c) 2015 by Lawrence Livermore National Security, LLC
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+[[ -e $TESTDIR ]] && rm -rf $TESTDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/bootfs/setup.ksh b/tests/zfs-tests/tests/functional/bootfs/setup.ksh
new file mode 100755
index 000000000000..273f239137b0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/bootfs/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 (c) 2015 by Lawrence Livermore National Security, LLC.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_must mkdir $TESTDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/btree/Makefile.am b/tests/zfs-tests/tests/functional/btree/Makefile.am
new file mode 100644
index 000000000000..333209d98f2b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/btree/Makefile.am
@@ -0,0 +1,20 @@
+#
+# 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 Delphix. All rights reserved.
+#
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/btree
+
+dist_pkgdata_SCRIPTS = \
+ btree_positive.ksh \
+ btree_negative.ksh
diff --git a/tests/zfs-tests/tests/functional/btree/btree_negative.ksh b/tests/zfs-tests/tests/functional/btree/btree_negative.ksh
new file mode 100755
index 000000000000..cefcbc51e796
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/btree/btree_negative.ksh
@@ -0,0 +1,38 @@
+#!/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) 2019 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# Verify that the btree functions don't allow bad inputs
+#
+# insert_duplicate - Callers may not add values that are already in the tree
+# remove_missing - Callers may not remove values that are not in the tree
+#
+# Note: These invocations cause btree_test to crash, but the program disables
+# core dumps first. As such, we can't use log_mustnot because it explicitly
+# looks for return values that correspond to a core dump and cause a test
+# failure.
+
+btree_test -n insert_duplicate
+[[ $? -eq 0 ]] && log_fail "Failure from insert_duplicate"
+
+btree_test -n remove_missing
+[[ $? -eq 0 ]] && log_fail "Failure from remove_missing"
+
+log_pass "Btree negative tests passed"
diff --git a/tests/zfs-tests/tests/functional/btree/btree_positive.ksh b/tests/zfs-tests/tests/functional/btree/btree_positive.ksh
new file mode 100755
index 000000000000..badbac2fab50
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/btree/btree_positive.ksh
@@ -0,0 +1,35 @@
+#!/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) 2019 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# The `btree_test` binary runs a series of positive tests when called
+# without arguments.
+#
+# insert_find_remove - Basic functionality test
+# find_without_index - Using the find function with a NULL argument
+# drain_tree - Fill the tree then empty it using the first and last
+# functions
+# stress_tree - Allow the tree to have items added and removed for a
+# given amount of time
+#
+
+log_must btree_test
+
+log_pass "Btree positive tests passed"
diff --git a/tests/zfs-tests/tests/functional/cache/Makefile.am b/tests/zfs-tests/tests/functional/cache/Makefile.am
new file mode 100644
index 000000000000..f28130ee9e4d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/Makefile.am
@@ -0,0 +1,20 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cache
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ cache_001_pos.ksh \
+ cache_002_pos.ksh \
+ cache_003_pos.ksh \
+ cache_004_neg.ksh \
+ cache_005_neg.ksh \
+ cache_006_pos.ksh \
+ cache_007_neg.ksh \
+ cache_008_neg.ksh \
+ cache_009_pos.ksh \
+ cache_010_pos.ksh \
+ cache_011_pos.ksh \
+ cache_012_pos.ksh
+
+dist_pkgdata_DATA = \
+ cache.cfg \
+ cache.kshlib
diff --git a/tests/zfs-tests/tests/functional/cache/cache.cfg b/tests/zfs-tests/tests/functional/cache/cache.cfg
new file mode 100644
index 000000000000..07e482d7df96
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache.cfg
@@ -0,0 +1,71 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export DISK_ARRAY_NUM=0
+
+function set_disks
+{
+ set -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 ))
+ done
+ export DISK_ARRAY_NUM=$i
+ export DISKSARRAY
+ fi
+
+ if (( $DISK_ARRAY_NUM == 0 )); then
+ export disk=$DISK
+ else
+ export disk=$DISK0
+ fi
+}
+
+set_disks
+set_device_dir
+
+export SIZE=$MINVDEVSIZE
+
+export VDIR=$TESTDIR/disk.cache
+export VDIR2=$TESTDIR/disk2.cache
+
+export VDEV="$VDIR/a $VDIR/b $VDIR/c"
+export LDEV="$DISK0"
+export VDEV2="$VDIR2/a $VDIR2/b $VDIR2/c"
+export LDEV2="$DISK1"
diff --git a/tests/zfs-tests/tests/functional/cache/cache.kshlib b/tests/zfs-tests/tests/functional/cache/cache.kshlib
new file mode 100644
index 000000000000..2e258e22cd39
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache.kshlib
@@ -0,0 +1,154 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+function cleanup
+{
+ if datasetexists $TESTPOOL ; then
+ log_must zpool destroy -f $TESTPOOL
+ fi
+ if datasetexists $TESTPOOL2 ; then
+ log_must zpool destroy -f $TESTPOOL2
+ fi
+}
+
+#
+# Try zpool status/iostat for given pool
+#
+# $1 pool
+#
+function display_status
+{
+ typeset pool=$1
+
+ typeset -i ret=0
+ zpool status -xv $pool > /dev/null 2>&1
+ ret=$?
+
+ zpool iostat > /dev/null 2>&1
+ ((ret |= $?))
+
+ typeset mntpnt=$(get_prop mountpoint $pool)
+ dd if=/dev/urandom of=$mntpnt/testfile.$$ &
+ typeset pid=$!
+
+ zpool iostat -v 1 3 > /dev/null
+ ((ret |= $?))
+
+ kill -9 $pid
+ wait
+
+ return $ret
+}
+
+#
+# Verify the given cache device have correct type and status
+#
+# $1 pool name
+# $2 device name
+# $3 device status
+# $4 device type
+#
+function verify_cache_device
+{
+ typeset pool=$1
+ typeset device=$2
+ typeset status=$3
+ typeset type=$4
+
+ if [[ -z $pool || -z $device || -z $status ]]; then
+ log_fail "Usage: verify_cache_device <pool> <device> " \
+ "<status> [type]"
+ fi
+
+ #
+ # Get all the cache devices and status table like below
+ #
+ # mirror:/disks/d ONLINE mirror:/disks/e ONLINE stripe:/disks/f ONLINE
+ #
+ set -A dev_stat_tab $(zpool status -v $pool | nawk 'BEGIN {start=0} \
+ /\tcache/ {start=1}
+ /\tmirror/ || /\tspares/ || /^$/ {start=0}
+ (start==1) && /\t (\/|[a-zA-Z])/ \
+ {print "stripe:" $1 " " $2}
+ (start==1) && /\t (\/|[a-zA-Z])/ \
+ {print "mirror:" $1 " " $2}
+ # When hotspare is replacing
+ (start==1) && /\t (\/|[a-zA-Z])/ \
+ {print "mirror:" $1 " " $2}'
+ )
+
+ typeset -i i=0
+ typeset find=0
+ while (( i < ${#dev_stat_tab[@]} )); do
+ typeset dev=${dev_stat_tab[$i]}
+ typeset stat=${dev_stat_tab[((i+1))]}
+
+ case $dev in
+ stripe:$device)
+ if [[ "$type" == 'mirror' ]]; then
+ log_note "Unexpected type: mirror"
+ return 1
+ else
+ if [[ $stat != $status ]]; then
+ log_note "Status($stat) " \
+ "!= Expected stat($status)"
+ return 1
+ fi
+ return 0
+ fi
+ ;;
+ mirror:$device)
+ if [[ -z "$type" || $type == 'stripe' ]]; then
+ log_note "Unexpected type: stripe"
+ return 1
+ else
+ if [[ $stat != $status ]]; then
+ log_note "Status($stat) " \
+ "!= Expected stat($status)"
+ return 1
+ fi
+ return 0
+ fi
+ ;;
+ esac
+ ((i += 2))
+ done
+
+ log_note "Can not find device: $device"
+ return 1
+}
+
+function verify_cache_support
+{
+ zpool upgrade -v | grep "Cache devices" > /dev/null 2>&1
+ return $?
+}
diff --git a/tests/zfs-tests/tests/functional/cache/cache_001_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_001_pos.ksh
new file mode 100755
index 000000000000..955c9f12019f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Creating a pool with a cache device succeeds.
+#
+# STRATEGY:
+# 1. Create pool with separated cache devices.
+# 2. Display pool status
+# 3. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Creating a pool with a cache device succeeds."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ cache $LDEV
+ log_must display_status $TESTPOOL
+
+ ldev=$(random_get $LDEV)
+ log_must verify_cache_device $TESTPOOL $ldev 'ONLINE'
+
+ log_must zpool remove $TESTPOOL $ldev
+ log_must check_vdev_state $TESTPOOL $ldev ""
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Creating a pool with a cache device succeeds."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_002_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_002_pos.ksh
new file mode 100755
index 000000000000..888645c353e8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Adding a cache device to normal pool works.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Add cache devices with different configuration
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Adding a cache device to normal pool works."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ log_must zpool create $TESTPOOL $type $VDEV
+ log_must zpool add $TESTPOOL cache $LDEV
+ log_must display_status $TESTPOOL
+ typeset ldev=$(random_get $LDEV)
+ log_must verify_cache_device $TESTPOOL $ldev 'ONLINE'
+
+ log_must zpool remove $TESTPOOL $ldev
+ log_must check_vdev_state $TESTPOOL $ldev ""
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Adding a cache device to normal pool works."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_003_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_003_pos.ksh
new file mode 100755
index 000000000000..566c5c6ac675
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Adding an extra cache device works
+#
+# STRATEGY:
+# 1. Create pool with separated cache devices.
+# 2. Add an extra cache devices
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+verify_disk_count "$LDEV2"
+
+log_assert "Adding an extra cache device works."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ cache $LDEV
+ log_must zpool add $TESTPOOL \
+ cache $LDEV2
+
+ log_must display_status $TESTPOOL
+ ldev=$(random_get $LDEV2)
+ log_must verify_cache_device $TESTPOOL $ldev 'ONLINE'
+
+ log_must zpool remove $TESTPOOL $ldev
+ log_must check_vdev_state $TESTPOOL $ldev ""
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Adding an extra cache device works."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_004_neg.ksh b/tests/zfs-tests/tests/functional/cache/cache_004_neg.ksh
new file mode 100755
index 000000000000..38fee608bbc8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_004_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Attaching a cache device fails.
+#
+# STRATEGY:
+# 1. Create pool with separated cache devices.
+# 2. Attaching a cache device for existing cache device
+# 3. Verify the operation fails
+#
+
+verify_runnable "global"
+verify_disk_count "$LDEV2"
+
+log_assert "Attaching a cache device fails for an existing cache device."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ cache $LDEV
+
+ ldev=$(random_get $LDEV)
+ typeset ldev2=$(random_get $LDEV2)
+ log_mustnot zpool attach $TESTPOOL $ldev $ldev2
+ log_must check_vdev_state $TESTPOOL $ldev2 ""
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Attaching a cache device fails for an existing cache device."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_005_neg.ksh b/tests/zfs-tests/tests/functional/cache/cache_005_neg.ksh
new file mode 100755
index 000000000000..35e15abe2602
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_005_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Replacing a cache device fails.
+#
+# STRATEGY:
+# 1. Create pool with cache devices.
+# 2. Replacing one cache device
+# 3. Verify replace fails
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+verify_disk_count "$LDEV2"
+
+log_assert "Replacing a cache device fails."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ cache $LDEV
+ sdev=$(random_get $LDEV)
+ tdev=$(random_get $LDEV2)
+ log_mustnot zpool replace $TESTPOOL $sdev $tdev
+ log_must verify_cache_device $TESTPOOL $sdev 'ONLINE'
+ log_must check_vdev_state $TESTPOOL $tdev ""
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Replacing a cache device fails."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_006_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_006_pos.ksh
new file mode 100755
index 000000000000..46bd5fc8b3ef
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_006_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Exporting and importing pool with cache devices passes.
+#
+# STRATEGY:
+# 1. Create pool with cache devices.
+# 2. Export and import the pool
+# 3. Display pool status
+# 4. Destroy and import the pool again
+# 5. Display pool status
+# 6. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+verify_disk_count "$LDEV2"
+
+log_assert "Exporting and importing pool with cache devices passes."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ cache $LDEV $LDEV2
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must verify_cache_device \
+ $TESTPOOL $ldev 'ONLINE'
+
+ #
+ # Nomal export/import operating
+ #
+ log_must zpool export $TESTPOOL
+ log_must zpool import -d $VDIR $TESTPOOL
+ log_must display_status $TESTPOOL
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must verify_cache_device \
+ $TESTPOOL $ldev 'ONLINE'
+
+ #
+ # Destroy the pool and import again
+ #
+ log_must zpool destroy $TESTPOOL
+ log_must zpool import -Df -d $VDIR $TESTPOOL
+ log_must display_status $TESTPOOL
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must verify_cache_device \
+ $TESTPOOL $ldev 'ONLINE'
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Exporting and importing pool with cache devices passes."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_007_neg.ksh b/tests/zfs-tests/tests/functional/cache/cache_007_neg.ksh
new file mode 100755
index 000000000000..e2cdc0a28d38
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_007_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# A mirror/raidz/raidz2 cache is not supported.
+#
+# STRATEGY:
+# 1. Try to create pool with unsupported type
+# 2. Verify failed to create pool.
+#
+
+verify_runnable "global"
+verify_disk_count "$LDEV2"
+
+log_assert "A mirror/raidz/raidz2 cache is not supported."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for cachetype in "mirror" "raidz" "raidz1" "raidz2"
+ do
+ log_mustnot zpool create $TESTPOOL $type $VDEV \
+ cache $cachetype $LDEV $LDEV2
+ ldev=$(random_get $LDEV $LDEV2)
+ log_mustnot verify_cache_device \
+ $TESTPOOL $ldev 'ONLINE' $cachetype
+ log_must datasetnonexists $TESTPOOL
+ done
+done
+
+log_pass "A mirror/raidz/raidz2 cache is not supported."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_008_neg.ksh b/tests/zfs-tests/tests/functional/cache/cache_008_neg.ksh
new file mode 100755
index 000000000000..93866dd3097f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_008_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# A mirror/raidz/raidz2 cache can not be added to existed pool.
+#
+# STRATEGY:
+# 1. Create pool with or without cache.
+# 2. Add a mirror/raidz/raidz2 cache to this pool.
+# 3. Verify failed to add.
+#
+
+verify_runnable "global"
+verify_disk_count "$LDEV2"
+
+log_assert "A raidz/raidz2 cache can not be added to existed pool."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for cachetype in "mirror" "raidz" "raidz1" "raidz2"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ cache $LDEV
+
+ log_mustnot zpool add $TESTPOOL cache $cachetype $LDEV2
+ ldev=$(random_get $LDEV2)
+ log_mustnot verify_cache_device \
+ $TESTPOOL $ldev 'ONLINE' $cachetype
+
+ log_must zpool destroy $TESTPOOL
+ done
+done
+
+log_pass "A mirror/raidz/raidz2 cache can not be added to existed pool."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_009_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_009_pos.ksh
new file mode 100755
index 000000000000..7a0586648f84
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_009_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Offline and online a cache device succeed.
+#
+# STRATEGY:
+# 1. Create pool with mirror cache devices.
+# 2. Offine and online a cache device
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+verify_disk_count "$LDEV2"
+
+log_assert "Offline and online a cache device succeed."
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ cache $LDEV $LDEV2
+
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must zpool offline $TESTPOOL $ldev
+ log_must display_status $TESTPOOL
+ log_must verify_cache_device $TESTPOOL $ldev 'OFFLINE' ''
+
+ log_must zpool online $TESTPOOL $ldev
+ log_must display_status $TESTPOOL
+ log_must verify_cache_device $TESTPOOL $ldev 'ONLINE' ''
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Offline and online a cache device succeed."
diff --git a/tests/zfs-tests/tests/functional/cache/cache_010_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_010_pos.ksh
new file mode 100755
index 000000000000..1d9fc5a8922b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_010_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Verify that cache devices can be block devices, files or character devices
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Add different object as cache
+# 3. Verify character devices and files pass
+#
+
+verify_runnable "global"
+
+function cleanup_testenv
+{
+ cleanup
+ if [[ -n $lofidev ]]; then
+ if is_linux; then
+ losetup -d $lofidev
+ elif is_freebsd; then
+ mdconfig -du ${lofidev#md}
+ else
+ lofiadm -d $lofidev
+ fi
+ fi
+}
+
+log_assert "Verify cache devices can be disk, file, lofi device or any " \
+ "device that presents a block interface"
+
+verify_disk_count "$DISKS" 2
+log_onexit cleanup_testenv
+
+TESTVOL=testvol1$$
+dsk1=${DISKS%% *}
+log_must zpool create $TESTPOOL ${DISKS#$dsk1}
+
+# Add normal ${DEV_RDSKDIR} device
+log_must zpool add $TESTPOOL cache \
+ ${DEV_RDSKDIR}/${dsk1}
+log_must zpool remove $TESTPOOL ${DEV_RDSKDIR}/${dsk1}
+
+
+# Add provided disk
+log_must zpool add $TESTPOOL cache $dsk1
+log_must verify_cache_device $TESTPOOL $dsk1 'ONLINE'
+log_must zpool remove $TESTPOOL $dsk1
+
+# Add normal file
+log_must zpool add $TESTPOOL cache $VDEV
+ldev=$(random_get $VDEV)
+log_must verify_cache_device $TESTPOOL $ldev 'ONLINE'
+
+# Add loop back device
+if is_linux; then
+ lofidev=$(losetup -f)
+ log_must losetup $lofidev ${VDEV2%% *}
+ lofidev=${lofidev##*/}
+elif is_freebsd; then
+ lofidev=$(mdconfig -a ${VDEV2%% *})
+else
+ lofidev=${VDEV2%% *}
+ log_must lofiadm -a $lofidev
+ lofidev=$(lofiadm $lofidev)
+fi
+
+log_must zpool add $TESTPOOL cache $lofidev
+log_must verify_cache_device $TESTPOOL $lofidev 'ONLINE'
+
+log_pass "Verify cache devices can be disk, file, lofi device or any " \
+ "device that presents a block interface"
diff --git a/tests/zfs-tests/tests/functional/cache/cache_011_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_011_pos.ksh
new file mode 100755
index 000000000000..caa7e6e900b7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_011_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Remove cache device from pool with spare device should succeed.
+#
+# STRATEGY:
+# 1. Create pool with cache devices and spare devices
+# 2. Remove cache device from the pool
+# 3. The upper action should succeed
+#
+
+verify_runnable "global"
+verify_disk_count "$LDEV2"
+
+function cleanup {
+ if datasetexists $TESTPOOL ; then
+ log_must zpool destroy -f $TESTPOOL
+ fi
+}
+
+log_assert "Remove cache device from pool with spare device should succeed"
+log_onexit cleanup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ cache $LDEV spare $LDEV2
+
+ log_must zpool remove $TESTPOOL $LDEV
+ log_must display_status $TESTPOOL
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Remove cache device from pool with spare device should succeed"
diff --git a/tests/zfs-tests/tests/functional/cache/cache_012_pos.ksh b/tests/zfs-tests/tests/functional/cache/cache_012_pos.ksh
new file mode 100755
index 000000000000..edefe9c1bf68
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cache_012_pos.ksh
@@ -0,0 +1,110 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+#
+# DESCRIPTION:
+# Looping around a cache device with l2arc_write_size exceeding
+# the device size succeeds.
+#
+# STRATEGY:
+# 1. Create pool with a cache device.
+# 2. Set l2arc_write_max to a value larger than the cache device.
+# 3. Create a file larger than the cache device and random read
+# for 10 sec.
+# 4. Verify that l2arc_write_max is set back to the default.
+# 5. Set l2arc_write_max to a value less than the cache device size but
+# larger than the default (64MB).
+# 6. Record the l2_size.
+# 7. Random read for 1 sec.
+# 8. Record the l2_size again.
+# 9. If (6) <= (8) then we have not looped around yet.
+# 10. If (6) > (8) then we looped around. Break out of the loop and test.
+# 11. Destroy pool.
+#
+
+verify_runnable "global"
+
+log_assert "Looping around a cache device succeeds."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_WRITE_MAX $write_max
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+}
+log_onexit cleanup
+
+typeset write_max=$(get_tunable L2ARC_WRITE_MAX)
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+
+typeset VDEV="$VDIR/vdev.disk"
+typeset VDEV_SZ=$(( 4 * 1024 * 1024 * 1024 ))
+typeset VCACHE="$VDIR/vdev.cache"
+typeset VCACHE_SZ=$(( $VDEV_SZ / 2 ))
+
+typeset fill_mb=$(( floor($VDEV_SZ * 3 / 4 ) ))
+export DIRECTORY=/$TESTPOOL
+export NUMJOBS=4
+export RUNTIME=10
+export PERF_RANDSEED=1234
+export PERF_COMPPERCENT=66
+export PERF_COMPCHUNK=0
+export BLOCKSIZE=128K
+export SYNC_TYPE=0
+export DIRECT=1
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))
+
+log_must set_tunable32 L2ARC_WRITE_MAX $(( $VCACHE_SZ * 2 ))
+
+log_must truncate -s $VCACHE_SZ $VCACHE
+log_must truncate -s $VDEV_SZ $VDEV
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VCACHE
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+typeset write_max2=$(get_tunable L2ARC_WRITE_MAX)
+
+log_must test $write_max2 -eq $write_max
+
+log_must set_tunable32 L2ARC_WRITE_MAX $(( 64 * 1024 * 1024 ))
+export RUNTIME=1
+
+typeset do_once=true
+while $do_once || [[ $l2_size1 -le $l2_size2 ]]; do
+ typeset l2_size1=$(get_arcstat l2_size)
+ log_must fio $FIO_SCRIPTS/random_reads.fio
+ typeset l2_size2=$(get_arcstat l2_size)
+ do_once=false
+done
+
+log_must test $l2_size1 -gt $l2_size2
+
+log_must zpool destroy $TESTPOOL
+
+log_pass "Looping around a cache device succeeds."
diff --git a/tests/zfs-tests/tests/functional/cache/cleanup.ksh b/tests/zfs-tests/tests/functional/cache/cleanup.ksh
new file mode 100755
index 000000000000..258f92d19e0e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/cleanup.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+verify_runnable "global"
+
+if datasetexists $TESTPOOL ; then
+ log_must zpool destroy -f $TESTPOOL
+fi
+if datasetexists $TESTPOOL2 ; then
+ log_must zpool destroy -f $TESTPOOL2
+fi
+
+log_must rm -rf $VDIR $VDIR2
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cache/setup.ksh b/tests/zfs-tests/tests/functional/cache/setup.ksh
new file mode 100755
index 000000000000..0493637fcca8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cache/setup.ksh
@@ -0,0 +1,41 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cache/cache.cfg
+. $STF_SUITE/tests/functional/cache/cache.kshlib
+
+verify_runnable "global"
+
+log_must rm -rf $VDIR $VDIR2
+log_must mkdir -p $VDIR $VDIR2
+log_must mkfile $SIZE $VDEV $VDEV2
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cachefile/Makefile.am b/tests/zfs-tests/tests/functional/cachefile/Makefile.am
new file mode 100644
index 000000000000..53d8c8c6c9d5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cachefile
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ cachefile_001_pos.ksh \
+ cachefile_002_pos.ksh \
+ cachefile_003_pos.ksh \
+ cachefile_004_pos.ksh
+
+dist_pkgdata_DATA = \
+ cachefile.cfg \
+ cachefile.kshlib
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile.cfg b/tests/zfs-tests/tests/functional/cachefile/cachefile.cfg
new file mode 100644
index 000000000000..d93ec3ed6f3b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export CPATH="/etc/zfs/zpool.cache"
+export CPATH1=$TEST_BASE_DIR/cachefile.1.$$
+export CPATH2=$TEST_BASE_DIR/cachefile.2.$$
+
+export DISKSARRAY=$DISKS
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+set_device_dir
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib b/tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib
new file mode 100644
index 000000000000..7723e3083f1d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile.kshlib
@@ -0,0 +1,46 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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.
+#
+
+#
+# A function to determine if a given pool name has an entry in cachefile
+# returns 1 if the pool is not in the cache, 0 otherwise.
+function pool_in_cache {
+
+ # checking for the pool name in the strings output of
+ # the given cachefile, default is /etc/zfs/zpool.cache
+ typeset cachefile=${2:-$CPATH}
+
+ RESULT=$(strings $cachefile | grep -w $1)
+ if [ -z "$RESULT" ]
+ then
+ return 1
+ fi
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_001_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_001_pos.ksh
new file mode 100755
index 000000000000..f164a1fad32f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_001_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 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/cachefile/cachefile.cfg
+. $STF_SUITE/tests/functional/cachefile/cachefile.kshlib
+
+#
+# DESCRIPTION:
+#
+# Creating a pool with "cachefile" set doesn't update zpool.cache
+#
+# STRATEGY:
+# 1. Create a pool with the cachefile property set
+# 2. Verify that the pool doesn't have an entry in zpool.cache
+# 3. Verify the cachefile property is set
+# 4. Create a pool without the cachefile property
+# 5. Verify the cachefile property isn't set
+# 6. Verify that zpool.cache contains an entry for the pool
+#
+
+function cleanup
+{
+ typeset file
+
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+ for file in $CPATH1 $CPATH2 ; do
+ if [[ -f $file ]] ; then
+ log_must rm $file
+ fi
+ done
+}
+
+verify_runnable "global"
+
+log_assert "Creating a pool with \"cachefile\" set doesn't update zpool.cache"
+log_onexit cleanup
+
+set -A opts "none" "false" "none" \
+ "$CPATH" "true" "-" \
+ "$CPATH1" "true" "$CPATH1" \
+ "$CPATH2" "true" "$CPATH2"
+
+typeset -i i=0
+
+while (( i < ${#opts[*]} )); do
+ log_must zpool create -o cachefile=${opts[i]} $TESTPOOL $DISKS
+ case ${opts[((i+1))]} in
+ false) log_mustnot pool_in_cache $TESTPOOL
+ ;;
+ true) log_must pool_in_cache $TESTPOOL ${opts[i]}
+ ;;
+ esac
+
+ PROP=$(get_pool_prop cachefile $TESTPOOL)
+ if [[ $PROP != ${opts[((i+2))]} ]]; then
+ log_fail "cachefile property not set as expected. " \
+ "Expect: ${opts[((i+2))]}, Current: $PROP"
+ fi
+ log_must zpool destroy $TESTPOOL
+ (( i = i + 3 ))
+done
+
+log_pass "Creating a pool with \"cachefile\" set doesn't update zpool.cache"
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_002_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_002_pos.ksh
new file mode 100755
index 000000000000..9268f9786355
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_002_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 2009 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/cachefile/cachefile.cfg
+. $STF_SUITE/tests/functional/cachefile/cachefile.kshlib
+
+#
+# DESCRIPTION:
+#
+# Importing a pool with "cachefile" set doesn't update zpool.cache
+#
+# STRATEGY:
+# 1. Create a pool with the cachefile property set
+# 2. Verify the pool doesn't have an entry in zpool.cache
+# 3. Export the pool
+# 4. Import the pool
+# 5. Verify the pool does have an entry in zpool.cache
+# 6. Export the pool
+# 7. Import the pool -o cachefile=<cachefile>
+# 8. Verify the pool doesn't have an entry in zpool.cache
+#
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+}
+
+verify_runnable "global"
+
+log_assert "Importing a pool with \"cachefile\" set doesn't update zpool.cache"
+log_onexit cleanup
+
+log_must zpool create -o cachefile=none $TESTPOOL $DISKS
+typeset DEVICEDIR=$(get_device_dir $DISKS)
+log_mustnot pool_in_cache $TESTPOOL
+
+log_must zpool export $TESTPOOL
+log_must zpool import -d $DEVICEDIR $TESTPOOL
+log_must pool_in_cache $TESTPOOL
+
+log_must zpool export $TESTPOOL
+log_must zpool import -o cachefile=none -d $DEVICEDIR $TESTPOOL
+log_mustnot pool_in_cache $TESTPOOL
+
+log_must zpool export $TESTPOOL
+log_must zpool import -o cachefile=$CPATH -d $DEVICEDIR $TESTPOOL
+log_must pool_in_cache $TESTPOOL
+
+log_must zpool destroy $TESTPOOL
+
+log_pass "Importing a pool with \"cachefile\" set doesn't update zpool.cache"
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_003_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_003_pos.ksh
new file mode 100755
index 000000000000..a5f427cb4135
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_003_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 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/cachefile/cachefile.cfg
+. $STF_SUITE/tests/functional/cachefile/cachefile.kshlib
+
+#
+# DESCRIPTION:
+#
+# Setting altroot=<path> and cachefile=$CPATH for zpool create is succeed
+#
+# STRATEGY:
+# 1. Attempt to create a pool with -o altroot=<path> -o cachefile=<value>
+# 2. Verify the command succeed
+#
+#
+
+TESTDIR=/altdir.$$
+
+function cleanup
+{
+ typeset file
+
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ for file in $CPATH1 $CPATH2 ; do
+ if [[ -f $file ]] ; then
+ log_must rm $file
+ fi
+ done
+
+ if [ -d $TESTDIR ]
+ then
+ rmdir $TESTDIR
+ fi
+}
+
+verify_runnable "global"
+
+log_assert "Setting altroot=path and cachefile=$CPATH for zpool create succeed."
+log_onexit cleanup
+
+typeset -i i=0
+
+set -A opts "none" "none" \
+ "$CPATH" "-" \
+ "$CPATH1" "$CPATH1" \
+ "$CPATH2" "$CPATH2"
+
+
+while (( i < ${#opts[*]} )); do
+ log_must zpool create -o altroot=$TESTDIR -o cachefile=${opts[i]} \
+ $TESTPOOL $DISKS
+ if [[ ${opts[i]} != none ]]; then
+ log_must pool_in_cache $TESTPOOL ${opts[i]}
+ else
+ log_mustnot pool_in_cache $TESTPOOL
+ fi
+
+ PROP=$(get_pool_prop cachefile $TESTPOOL)
+ if [[ $PROP != ${opts[((i+1))]} ]]; then
+ log_fail "cachefile property not set as expected. " \
+ "Expect: ${opts[((i+1))]}, Current: $PROP"
+ fi
+ log_must zpool destroy $TESTPOOL
+ (( i = i + 2 ))
+done
+
+log_pass "Setting altroot=path and cachefile=$CPATH for zpool create succeed."
diff --git a/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh b/tests/zfs-tests/tests/functional/cachefile/cachefile_004_pos.ksh
new file mode 100755
index 000000000000..841b141e16fc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/cachefile_004_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cachefile/cachefile.cfg
+. $STF_SUITE/tests/functional/cachefile/cachefile.kshlib
+
+#
+# DESCRIPTION:
+# Verify set, export and destroy when cachefile is set on pool.
+#
+# STRATEGY:
+# 1. Create two pools with one same cachefile1.
+# 2. Set cachefile of the two pools to another same cachefile2.
+# 3. Verify cachefile1 does not exist.
+# 4. Export the two pools.
+# 5. Verify cachefile2 not exist.
+# 6. Import the two pools and set cachefile to cachefile2.
+# 7. Destroy the two pools.
+# 8. Verify cachefile2 not exist.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+
+ mntpnt=$(get_prop mountpoint $TESTPOOL)
+ typeset -i i=0
+ while ((i < 2)); do
+ if [[ -e $mntpnt/vdev$i ]]; then
+ log_must rm -f $mntpnt/vdev$i
+ fi
+ ((i += 1))
+ done
+
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ for file in $CPATH1 $CPATH2 ; do
+ if [[ -f $file ]] ; then
+ log_must rm $file
+ fi
+ done
+}
+
+
+log_assert "Verify set, export and destroy when cachefile is set on pool."
+log_onexit cleanup
+
+log_must zpool create $TESTPOOL $DISKS
+
+mntpnt=$(get_prop mountpoint $TESTPOOL)
+typeset -i i=0
+while ((i < 2)); do
+ log_must mkfile $MINVDEVSIZE $mntpnt/vdev$i
+ eval vdev$i=$mntpnt/vdev$i
+ ((i += 1))
+done
+
+log_must zpool create -o cachefile=$CPATH1 $TESTPOOL1 $vdev0
+log_must pool_in_cache $TESTPOOL1 $CPATH1
+log_must zpool create -o cachefile=$CPATH1 $TESTPOOL2 $vdev1
+log_must pool_in_cache $TESTPOOL2 $CPATH1
+
+log_must zpool set cachefile=$CPATH2 $TESTPOOL1
+log_must pool_in_cache $TESTPOOL1 $CPATH2
+log_must zpool set cachefile=$CPATH2 $TESTPOOL2
+log_must pool_in_cache $TESTPOOL2 $CPATH2
+if [[ -s $CPATH1 ]]; then
+ log_fail "Verify set when cachefile is set on pool."
+fi
+
+log_must zpool export $TESTPOOL1
+log_must zpool export $TESTPOOL2
+if [[ -s $CPATH2 ]]; then
+ log_fail "Verify export when cachefile is set on pool."
+fi
+
+log_must zpool import -d $mntpnt $TESTPOOL1
+log_must zpool set cachefile=$CPATH2 $TESTPOOL1
+log_must pool_in_cache $TESTPOOL1 $CPATH2
+log_must zpool import -d $mntpnt $TESTPOOL2
+log_must zpool set cachefile=$CPATH2 $TESTPOOL2
+log_must pool_in_cache $TESTPOOL2 $CPATH2
+
+log_must zpool destroy $TESTPOOL1
+log_must zpool destroy $TESTPOOL2
+if [[ -s $CPATH2 ]]; then
+ log_fail "Verify destroy when cachefile is set on pool."
+fi
+
+log_pass "Verify set, export and destroy when cachefile is set on pool."
diff --git a/tests/zfs-tests/tests/functional/cachefile/cleanup.ksh b/tests/zfs-tests/tests/functional/cachefile/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/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/cachefile/setup.ksh b/tests/zfs-tests/tests/functional/cachefile/setup.ksh
new file mode 100755
index 000000000000..47c7893bfdd6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cachefile/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cachefile/cachefile.cfg
+. $STF_SUITE/tests/functional/cachefile/cachefile.kshlib
+
+for pool in "$TESTPOOL" "$TESTPOOL2" "$TESTPOOL3" ; do
+ if poolexists $pool ; then
+ destroy_pool $pool
+ fi
+done
+
+for file in $CPATH1 $CPATH2 ; do
+ if [[ -f $file ]] ; then
+ log_must rm $file
+ fi
+done
+
+if pool_in_cache $TESTPOOL; then
+ log_unsupported "Skipping test group due to existing pool"
+fi
diff --git a/tests/zfs-tests/tests/functional/casenorm/Makefile.am b/tests/zfs-tests/tests/functional/casenorm/Makefile.am
new file mode 100644
index 000000000000..b284a2560b27
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/Makefile.am
@@ -0,0 +1,25 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/casenorm
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ case_all_values.ksh \
+ insensitive_formd_delete.ksh \
+ insensitive_formd_lookup.ksh \
+ insensitive_none_delete.ksh \
+ insensitive_none_lookup.ksh \
+ mixed_create_failure.ksh \
+ mixed_formd_delete.ksh \
+ mixed_formd_lookup_ci.ksh \
+ mixed_formd_lookup.ksh \
+ mixed_none_delete.ksh \
+ mixed_none_lookup_ci.ksh \
+ mixed_none_lookup.ksh \
+ norm_all_values.ksh \
+ sensitive_formd_delete.ksh \
+ sensitive_formd_lookup.ksh \
+ sensitive_none_delete.ksh \
+ sensitive_none_lookup.ksh
+
+dist_pkgdata_DATA = \
+ casenorm.cfg \
+ casenorm.kshlib
diff --git a/tests/zfs-tests/tests/functional/casenorm/case_all_values.ksh b/tests/zfs-tests/tests/functional/casenorm/case_all_values.ksh
new file mode 100755
index 000000000000..6e73b5c2c63d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/case_all_values.ksh
@@ -0,0 +1,42 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# Check that we can create FS with any supported casesensitivity value.
+#
+# STRATEGY:
+# For all supported casesensitivity values:
+# 1. Create FS with given casesensitivity value.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "Can create FS with any supported casesensitivity value"
+
+for caseval in sensitive insensitive mixed; do
+ create_testfs "-o casesensitivity=$caseval"
+ destroy_testfs
+done
+
+log_pass "Can create FS with any supported casesensitivity value"
diff --git a/tests/zfs-tests/tests/functional/casenorm/casenorm.cfg b/tests/zfs-tests/tests/functional/casenorm/casenorm.cfg
new file mode 100644
index 000000000000..5d2efbf000b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/casenorm.cfg
@@ -0,0 +1,35 @@
+#
+# 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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+# Ksh on linux may have locale env variables undefined
+export LANG="C.UTF-8"
+export LC_ALL="C.UTF-8"
+
+NAME_C_ORIG=$(printf '\u0046\u00ef\u004c\u00eb\u004e\u00c4\u006d\u00eb')
+NAME_C_UPPER=$(printf '\u0046\u00cf\u004c\u00cb\u004e\u00c4\u004d\u00cb')
+NAME_C_LOWER=$(printf '\u0066\u00ef\u006c\u00eb\u006e\u00e4\u006d\u00eb')
+NAME_D_ORIG=$(printf '\u0046\u0069\u0308\u004c\u0065\u0308\u004e\u0041\u0308\u006d\u0065\u0308')
+NAME_D_UPPER=$(printf '\u0046\u0049\u0308\u004c\u0045\u0308\u004e\u0041\u0308\u004d\u0045\u0308')
+NAME_D_LOWER=$(printf '\u0066\u0069\u0308\u006c\u0065\u0308\u006e\u0061\u0308\u006d\u0065\u0308')
+NAMES_ORIG="$NAME_C_ORIG $NAME_D_ORIG"
+NAMES_UPPER="$NAME_C_UPPER $NAME_D_UPPER"
+NAMES_LOWER="$NAME_C_LOWER $NAME_D_LOWER"
+NAMES_C="$NAME_C_ORIG $NAME_C_UPPER $NAME_C_LOWER"
+NAMES_D="$NAME_D_ORIG $NAME_D_UPPER $NAME_D_LOWER"
+NAMES_ALL="$NAMES_C $NAMES_D"
diff --git a/tests/zfs-tests/tests/functional/casenorm/casenorm.kshlib b/tests/zfs-tests/tests/functional/casenorm/casenorm.kshlib
new file mode 100644
index 000000000000..cb61798d7be7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/casenorm.kshlib
@@ -0,0 +1,131 @@
+#
+# 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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/casenorm/casenorm.cfg
+
+function create_testfs
+{
+ typeset opts=$1
+
+ rm -rf $TESTDIR || log_unresolved Could not remove $TESTDIR
+ mkdir -p $TESTDIR || log_unresolved Could not create $TESTDIR
+
+ log_must zfs create $opts $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+function destroy_testfs
+{
+ if datasetexists $TESTPOOL/$TESTFS ; then
+ log_must zfs destroy -f $TESTPOOL/$TESTFS
+ rm -rf $TESTDIR || log_unresolved Could not remove $TESTDIR
+ fi
+}
+
+function create_file
+{
+ typeset name=$TESTDIR/$1
+
+ echo $name > $name
+}
+
+function delete_file
+{
+ typeset name=$TESTDIR/$1
+
+ rm $name >/dev/null 2>&1
+
+ if [[ $? -ne 0 ]] ; then
+ return 1
+ fi
+
+ if [[ -f $name ]] ; then
+ return 2
+ fi
+}
+
+function lookup_file
+{
+ typeset name=$1
+
+ if is_illumos; then
+ zlook -l $TESTDIR $name >/dev/null 2>&1
+ else
+ test -f "${TESTDIR}/${name}" >/dev/null 2>&1
+ fi
+}
+
+function lookup_file_ci
+{
+ typeset name=$1
+
+ if is_illumos; then
+ zlook -il $TESTDIR $name >/dev/null 2>&1
+ else
+ test -f "${TESTDIR}/${name}" >/dev/null 2>&1
+ fi
+}
+
+function lookup_any
+{
+ for name in $NAMES_ALL ; do
+ lookup_file $name
+ if [[ $? -eq 0 ]] ; then
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+function switch_norm
+{
+ typeset norm=$(get_norm $1)
+
+ if [[ $norm == "C" ]] ; then
+ print "D"
+ else
+ print "C"
+ fi
+}
+
+function get_norm
+{
+ if [[ "${NAMES_C#*$1}" != "${NAMES_C}" ]] ; then
+ print "C"
+ elif [[ "${NAMES_D#*$1}" != "${NAMES_D}" ]] ; then
+ print "D"
+ else
+ return 1
+ fi
+}
+
+function get_case
+{
+ if [[ ${NAMES_UPPER#*$1} != ${NAMES_UPPER} ]] ; then
+ print "UPPER"
+ elif [[ ${NAMES_LOWER#*$1} != ${NAMES_LOWER} ]] ; then
+ print "LOWER"
+ elif [[ ${NAMES_ORIG#*$1} != ${NAMES_ORIG} ]] ; then
+ print "ORIG"
+ else
+ return 1
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/casenorm/cleanup.ksh b/tests/zfs-tests/tests/functional/casenorm/cleanup.ksh
new file mode 100755
index 000000000000..98af72d2e7ab
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/casenorm/insensitive_formd_delete.ksh b/tests/zfs-tests/tests/functional/casenorm/insensitive_formd_delete.ksh
new file mode 100755
index 000000000000..00caea997c1e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/insensitive_formd_delete.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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=insensitive, normalization=formD,
+# check that file can be deleted using any name form.
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that deleting file using other c/n name forms succeeds.
+# 3. Check that file isn't accessible by any c/n name form.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CI-UN FS: delete succeeds using any name form"
+
+# Can delete using any case/normalization form
+create_testfs "-o casesensitivity=insensitive -o normalization=formD"
+
+for name1 in $NAMES_ALL ; do
+ for name2 in $NAMES_ALL ; do
+ log_must create_file $name1
+ log_must delete_file $name2
+ log_mustnot lookup_any
+ done
+done
+
+destroy_testfs
+
+log_pass "CI-UN FS: delete succeeds using any name form"
diff --git a/tests/zfs-tests/tests/functional/casenorm/insensitive_formd_lookup.ksh b/tests/zfs-tests/tests/functional/casenorm/insensitive_formd_lookup.ksh
new file mode 100755
index 000000000000..1ef9d2756fc8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/insensitive_formd_lookup.ksh
@@ -0,0 +1,51 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=insensitive, normalization=formD,
+# check that lookup succeeds using any name form.
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that lookup succeeds for any other c/n name form.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CI-UN FS: lookup succeeds using any name form"
+
+create_testfs "-o casesensitivity=insensitive -o normalization=formD"
+
+for name1 in $NAMES_ALL ; do
+ log_must create_file $name1
+ for name2 in $NAMES_ALL ; do
+ log_must lookup_file $name2
+ done
+ delete_file $name1
+done
+
+destroy_testfs
+
+log_pass "CI-UN FS: lookup succeeds using any name form"
diff --git a/tests/zfs-tests/tests/functional/casenorm/insensitive_none_delete.ksh b/tests/zfs-tests/tests/functional/casenorm/insensitive_none_delete.ksh
new file mode 100755
index 000000000000..51f6a3c1aa08
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/insensitive_none_delete.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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=insensitive, normalization=none,
+# check that delete succeeds if (norm=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that delete succeeds if (norm=same).
+# 3. Check that file is no longer accessible using any name form.
+# 4. Check that delete fails if (norm=other).
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CI-not-UN FS: delete succeeds if (norm=same)"
+
+create_testfs "-o casesensitivity=insensitive -o normalization=none"
+
+for name1 in $NAMES_C ; do
+ for name2 in $NAMES_C ; do
+ log_must create_file $name1
+ log_must delete_file $name2
+ log_mustnot lookup_any
+ done
+ for name2 in $NAMES_D ; do
+ log_must create_file $name1
+ log_mustnot delete_file $name2
+ delete_file $name1
+ done
+done
+
+for name1 in $NAMES_D ; do
+ for name2 in $NAMES_D ; do
+ log_must create_file $name1
+ log_must delete_file $name2
+ log_mustnot lookup_any
+ done
+ for name2 in $NAMES_C ; do
+ log_must create_file $name1
+ log_mustnot delete_file $name2
+ delete_file $name1
+ done
+done
+
+destroy_testfs
+
+log_pass "CI-not-UN FS: delete succeeds if (norm=same)"
diff --git a/tests/zfs-tests/tests/functional/casenorm/insensitive_none_lookup.ksh b/tests/zfs-tests/tests/functional/casenorm/insensitive_none_lookup.ksh
new file mode 100755
index 000000000000..12b7951e1a80
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/insensitive_none_lookup.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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=insensitive, normalization=none,
+# check that lookup succeeds only if (norm=same)
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that lookup succeeds if (norm=same).
+# 3. Check that lookup fails if (norm=other).
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CI-not-UN FS: lookup succeeds only if (norm=same)"
+
+create_testfs "-o casesensitivity=insensitive -o normalization=none"
+
+for name1 in $NAMES_C ; do
+ log_must create_file $name1
+ for name2 in $NAMES_C ; do
+ log_must lookup_file $name2
+ done
+ for name2 in $NAMES_D; do
+ log_mustnot lookup_file $name2
+ done
+ delete_file $name1
+done
+
+for name1 in $NAMES_D ; do
+ log_must create_file $name1
+ for name2 in $NAMES_D ; do
+ log_must lookup_file $name2
+ done
+ for name2 in $NAMES_C; do
+ log_mustnot lookup_file $name2
+ done
+ delete_file $name1
+done
+
+destroy_testfs
+
+log_pass "CI-not-UN FS: lookup succeeds only if (norm=same)"
diff --git a/tests/zfs-tests/tests/functional/casenorm/mixed_create_failure.ksh b/tests/zfs-tests/tests/functional/casenorm/mixed_create_failure.ksh
new file mode 100755
index 000000000000..51b5bb3f6584
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/mixed_create_failure.ksh
@@ -0,0 +1,136 @@
+#!/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 Nutanix Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=mixed, normalization=none,
+# when multiple files with the same name (differing only in case) are created,
+# the number of files is limited to what can fit in a fatzap leaf-block.
+# And beyond that, it fails with ENOSPC.
+#
+# Ensure that the create/rename operations fail gracefully and not trigger an
+# ASSERT.
+#
+# STRATEGY:
+# Repeat the below steps for objects: files, directories, symlinks and hardlinks
+# 1. Create objects with same name but varying in case.
+# E.g. 'abcdefghijklmnop', 'Abcdefghijklmnop', 'ABcdefghijklmnop' etc.
+# The create should fail with ENOSPC.
+# 2. Create an object with name 'tmp_obj' and try to rename it to name that we
+# failed to add in step 1 above.
+# This should fail as well.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "With mixed mode: ensure create fails with ENOSPC beyond a certain limit"
+
+create_testfs "-o casesensitivity=mixed -o normalization=none"
+
+# Different object types
+obj_type=('file' 'dir' 'symlink' 'hardlink')
+
+# Commands to create different object types
+typeset -A ops
+ops['file']='touch'
+ops['dir']='mkdir'
+ops['symlink']='ln -s'
+ops['hardlink']='ln'
+
+# This function tests the following for a give object type :
+# - Create multiple objects with the same name (varying only in case).
+# Ensure that it eventually fails once the leaf-block limit is exceeded.
+# - Create another object with a different name. And attempt rename it to the
+# name (for which the create had failed in the previous step).
+# This should fail as well.
+# Args :
+# $1 - object type (file/dir/symlink/hardlink)
+# $2 - test directory
+#
+function test_ops
+{
+ typeset obj_type=$1
+ typeset testdir=$2
+
+ target_obj='target-file'
+
+ op="${ops[$obj_type]}"
+
+ log_note "The op : $op"
+ log_note "testdir=$testdir obj_type=$obj_type"
+
+ test_path="$testdir/$obj_type"
+ mkdir $test_path
+ log_note "Created test dir $test_path"
+
+ if [[ $obj_type = "symlink" || $obj_type = "hardlink" ]]; then
+ touch $test_path/$target_obj
+ log_note "Created target: $test_path/$target_obj"
+ op="$op $test_path/$target_obj"
+ fi
+
+ log_note "op : $op"
+ names='{a,A}{b,B}{c,C}{d,D}{e,E}{f,F}{g,G}{h,H}{i,I}{j,J}{k,K}{l,L}'
+ for name in $names; do
+ cmd="$op $test_path/$name"
+ out=$($cmd 2>&1)
+ ret=$?
+ log_note "cmd: $cmd ret: $ret out=$out"
+ if (($ret != 0)); then
+ if [[ $out = *@(No space left on device)* ]]; then
+ save_name="$test_path/$name"
+ break;
+ else
+ log_err "$cmd failed with unexpected error : $out"
+ fi
+ fi
+ done
+
+ log_note 'Test rename \"sample_name\" rename'
+ TMP_OBJ="$test_path/tmp_obj"
+ cmd="$op $TMP_OBJ"
+ out=$($cmd 2>&1)
+ ret=$?
+ if (($ret != 0)); then
+ log_err "cmd:$cmd failed out:$out"
+ fi
+
+ # Now, try to rename the tmp_obj to the name which we failed to add earlier.
+ # This should fail as well.
+ out=$(mv $TMP_OBJ $save_name 2>&1)
+ ret=$?
+ if (($ret != 0)); then
+ if [[ $out = *@(No space left on device)* ]]; then
+ log_note "$cmd failed as expected : $out"
+ else
+ log_err "$cmd failed with : $out"
+ fi
+ fi
+}
+
+for obj_type in ${obj_type[*]};
+do
+ log_note "Testing create of $obj_type"
+ test_ops $obj_type $TESTDIR
+done
+
+log_pass "Mixed mode FS: Ops on large number of colliding names fail gracefully"
diff --git a/tests/zfs-tests/tests/functional/casenorm/mixed_formd_delete.ksh b/tests/zfs-tests/tests/functional/casenorm/mixed_formd_delete.ksh
new file mode 100755
index 000000000000..451acbbfa89c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/mixed_formd_delete.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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=mixed, normalization=formD,
+# check that delete succeeds if (case=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that delete succeeds if (case=same).
+# 3. Check that file is no longer accessible using any name form.
+# 4. Check that delete fails for all other name forms other than original.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CM-UN FS: delete succeeds if (case=same)"
+
+create_testfs "-o casesensitivity=mixed -o normalization=formD"
+
+for name1 in $NAMES_ALL; do
+ typeset -n namen=NAME_$(switch_norm $name1)_$(get_case $name1)
+ for name2 in $NAMES_ALL; do
+ log_must create_file $name1
+ if [[ $name2 == $namen || $name2 == $name1 ]]; then
+ log_must delete_file $name2
+ log_mustnot lookup_any
+ else
+ log_mustnot delete_file $name2
+ fi
+ delete_file $name1
+ done
+done
+
+destroy_testfs
+
+log_pass "CM-UN FS: delete succeeds if (case=same)"
diff --git a/tests/zfs-tests/tests/functional/casenorm/mixed_formd_lookup.ksh b/tests/zfs-tests/tests/functional/casenorm/mixed_formd_lookup.ksh
new file mode 100755
index 000000000000..105415db5fd9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/mixed_formd_lookup.ksh
@@ -0,0 +1,56 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=mixed, normalization=formD,
+# check that lookup succeeds only if (case=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that lookup succeeds if (case=same).
+# 3. Check that lookup fails if (case=other).
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CM-UN FS: lookup succeeds if (case=same)"
+
+create_testfs "-o casesensitivity=mixed -o normalization=formD"
+
+for name1 in $NAMES_ALL; do
+ log_must create_file $name1
+ for name2 in $NAMES_ALL; do
+ if [[ $(get_case $name2) == $(get_case $name1) ]]; then
+ log_must lookup_file $name2
+ else
+ log_mustnot lookup_file $name2
+ fi
+ done
+ delete_file $name1
+done
+
+destroy_testfs
+
+log_pass "CM-UN FS: lookup succeeds if (case=same)"
diff --git a/tests/zfs-tests/tests/functional/casenorm/mixed_formd_lookup_ci.ksh b/tests/zfs-tests/tests/functional/casenorm/mixed_formd_lookup_ci.ksh
new file mode 100755
index 000000000000..50827ff585f1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/mixed_formd_lookup_ci.ksh
@@ -0,0 +1,51 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=insensitive, normalization=formD,
+# check that CI lookup succeeds using any name form.
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that CI lookup succeeds for any c/n name form.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CM-UN FS: CI lookup succeeds using any name form"
+
+create_testfs "-o casesensitivity=mixed -o normalization=formD"
+
+for name1 in $NAMES_ALL ; do
+ log_must create_file $name1
+ for name2 in $NAMES_ALL ; do
+ log_must lookup_file_ci $name2
+ done
+ delete_file $name1
+done
+
+destroy_testfs
+
+log_pass "CM-UN FS: CI lookup succeeds using any name form"
diff --git a/tests/zfs-tests/tests/functional/casenorm/mixed_none_delete.ksh b/tests/zfs-tests/tests/functional/casenorm/mixed_none_delete.ksh
new file mode 100755
index 000000000000..708fea8b87f1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/mixed_none_delete.ksh
@@ -0,0 +1,56 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=mixed, normalization=none,
+# check that delete succeeds only if (case=same and norm=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file in given c/n name form.
+# 2. Check that delete fails for all other name forms.
+# 3. Check that delete succeeds if (case=same and norm=same).
+# 4. Check that file is no longer accessible by any name form.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CM-not-UN FS: delete succeeds only if using exact name form"
+
+create_testfs "-o casesensitivity=mixed -o normalization=none"
+
+for name1 in $NAMES_ALL ; do
+ log_must create_file $name1
+ for name2 in $NAMES_ALL ; do
+ if [[ $name2 != $name1 ]] ; then
+ log_mustnot delete_file $name2
+ fi
+ done
+ delete_file $name1
+ log_mustnot lookup_any
+done
+
+destroy_testfs
+
+log_pass "CM-not-UN FS: delete succeeds only if using exact name form"
diff --git a/tests/zfs-tests/tests/functional/casenorm/mixed_none_lookup.ksh b/tests/zfs-tests/tests/functional/casenorm/mixed_none_lookup.ksh
new file mode 100755
index 000000000000..12d8495aacd7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/mixed_none_lookup.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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=mixed, normalization=none,
+# check that lookup succeeds only if (case=same and norm=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that lookup fails for all other c/n name forms.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CM-not-UN FS: lookup succeeds only if using exact name form"
+
+create_testfs "-o casesensitivity=mixed -o normalization=none"
+
+for name1 in $NAMES_ALL; do
+ for name2 in $NAMES_ALL; do
+ log_must create_file $name1
+ if [[ $name2 != $name1 ]]; then
+ log_mustnot lookup_file $name2
+ fi
+ delete_file $name1
+ done
+done
+
+destroy_testfs
+
+log_pass "CM-not-UN FS: lookup succeeds only if using exact name form"
diff --git a/tests/zfs-tests/tests/functional/casenorm/mixed_none_lookup_ci.ksh b/tests/zfs-tests/tests/functional/casenorm/mixed_none_lookup_ci.ksh
new file mode 100755
index 000000000000..c798ec788ed2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/mixed_none_lookup_ci.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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=mixed, normalization=none,
+# check that CI lookup succeeds only if (norm=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that CI lookup succeeds if (norm=same).
+# 3. Check that CI lookup fails if (norm=other).
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CM-not-UN FS: CI lookup succeeds only if (norm=same)"
+
+create_testfs "-o casesensitivity=mixed -o normalization=none"
+
+for name1 in $NAMES_C ; do
+ log_must create_file $name1
+ for name2 in $NAMES_C ; do
+ log_must lookup_file_ci $name2
+ done
+ for name2 in $NAMES_D; do
+ log_mustnot lookup_file_ci $name2
+ done
+ delete_file $name1
+done
+
+for name1 in $NAMES_D ; do
+ log_must create_file $name1
+ for name2 in $NAMES_D ; do
+ log_must lookup_file_ci $name2
+ done
+ for name2 in $NAMES_C; do
+ log_mustnot lookup_file_ci $name2
+ done
+ delete_file $name1
+done
+
+destroy_testfs
+
+log_pass "CM-not-UN FS: CI lookup succeeds only if (norm=same)"
diff --git a/tests/zfs-tests/tests/functional/casenorm/norm_all_values.ksh b/tests/zfs-tests/tests/functional/casenorm/norm_all_values.ksh
new file mode 100755
index 000000000000..87779a710d16
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/norm_all_values.ksh
@@ -0,0 +1,61 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# Check that we can create FS with all supported normalization forms.
+#
+# STRATEGY:
+# 1. Create FS with all supported normalization forms.
+# 2. Check that utf8only is set on except for normalization=none.
+# 3. Check that it's not possible to create FS with utf8only=off
+# and normalization other than none.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "Can create FS with all supported normalization forms"
+
+for form in none formC formD formKC formKD; do
+ create_testfs "-o normalization=$form"
+ if [[ $form != "none" ]] ; then
+ utf8only=$(zfs get -H -o value utf8only $TESTPOOL/$TESTFS)
+ if [[ $utf8only != "on" ]]; then
+ log_fail "Turning on normalization didn't set " \
+ "utf8only to on"
+ fi
+ fi
+ destroy_testfs
+done
+
+for form in formC formD formKC formKD; do
+ log_mustnot zfs create -o utf8only=off -o normalization=$form \
+ $TESTPOOL/$TESTFS
+ destroy_testfs
+done
+
+log_pass "Can create FS with all supported normalization forms"
diff --git a/tests/zfs-tests/tests/functional/casenorm/sensitive_formd_delete.ksh b/tests/zfs-tests/tests/functional/casenorm/sensitive_formd_delete.ksh
new file mode 100755
index 000000000000..285bd4e31ed9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/sensitive_formd_delete.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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=sensitive, normalization=formD,
+# check that delete succeeds if (case=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that delete succeeds if (case=same).
+# 3. Check that file is no longer accessible using any name form.
+# 4. Check that delete fails for all other name forms.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CS-UN FS: delete succeeds if (case=same)"
+
+create_testfs "-o casesensitivity=sensitive -o normalization=formD"
+
+for name1 in $NAMES_ALL ; do
+ typeset -n namen=NAME_$(switch_norm $name1)_$(get_case $name1)
+ for name2 in $NAMES_ALL ; do
+ log_must create_file $name1
+ if [[ $name2 == $namen || $name2 == $name1 ]] ; then
+ log_must delete_file $name2
+ log_mustnot lookup_any
+ else
+ log_mustnot delete_file $name2
+ fi
+ delete_file $name1
+ done
+done
+
+destroy_testfs
+
+log_pass "CS-UN FS: delete succeeds if (case=same)"
diff --git a/tests/zfs-tests/tests/functional/casenorm/sensitive_formd_lookup.ksh b/tests/zfs-tests/tests/functional/casenorm/sensitive_formd_lookup.ksh
new file mode 100755
index 000000000000..d00c7b5fca9e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/sensitive_formd_lookup.ksh
@@ -0,0 +1,56 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=sensitive, normalization=formD,
+# check that lookup only if (case=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that lookup succeeds if (case=same).
+# 3. Check that lookup fails if (case=other).
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CS-UN FS: lookup succeeds if (case=same)"
+
+create_testfs "-o casesensitivity=sensitive -o normalization=formD"
+
+for name1 in $NAMES_ALL; do
+ log_must create_file $name1
+ for name2 in $NAMES_ALL; do
+ if [[ $(get_case $name2) == $(get_case $name1) ]]; then
+ log_must lookup_file $name2
+ else
+ log_mustnot lookup_file $name2
+ fi
+ done
+ delete_file $name1
+done
+
+destroy_testfs
+
+log_pass "CS-UN FS: lookup succeeds if (case=same)"
diff --git a/tests/zfs-tests/tests/functional/casenorm/sensitive_none_delete.ksh b/tests/zfs-tests/tests/functional/casenorm/sensitive_none_delete.ksh
new file mode 100755
index 000000000000..addebcdbc29d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/sensitive_none_delete.ksh
@@ -0,0 +1,56 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=sensitive, normalization=none,
+# check that delete succeeds only if (case=same and norm=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file in given c/n name form.
+# 2. Check that delete fails for all other name forms.
+# 3. Check that delete succeeds if (case=same and norm=same).
+# 4. Check that file is no longer accessible by any name form.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CS-not-UN FS: delete succeeds only if using exact name form"
+
+create_testfs "-o casesensitivity=sensitive -o normalization=none"
+
+for name1 in $NAMES_ALL ; do
+ log_must create_file $name1
+ for name2 in $NAMES_ALL ; do
+ if [[ $name2 != $name1 ]] ; then
+ log_mustnot delete_file $name2
+ fi
+ done
+ delete_file $name1
+ log_mustnot lookup_any
+done
+
+destroy_testfs
+
+log_pass "CS-not-UN FS: delete succeeds only if using exact name form"
diff --git a/tests/zfs-tests/tests/functional/casenorm/sensitive_none_lookup.ksh b/tests/zfs-tests/tests/functional/casenorm/sensitive_none_lookup.ksh
new file mode 100755
index 000000000000..b945d8102988
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/sensitive_none_lookup.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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/casenorm/casenorm.kshlib
+
+# DESCRIPTION:
+# For the filesystem with casesensitivity=sensitive, normalization=none,
+# check that lookup succeeds only if (case=same and norm=same).
+#
+# STRATEGY:
+# For each c/n name form:
+# 1. Create file with given c/n name form.
+# 2. Check that lookup fails for all other c/n name forms.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_testfs
+}
+
+log_onexit cleanup
+log_assert "CS-not-UN FS: lookup succeeds only if using exact name form"
+
+create_testfs "-o casesensitivity=sensitive -o normalization=none"
+
+for name1 in $NAMES_ALL; do
+ for name2 in $NAMES_ALL; do
+ log_must create_file $name1
+ if [[ $name2 != $name1 ]]; then
+ log_mustnot lookup_file $name2
+ fi
+ delete_file $name1
+ done
+done
+
+destroy_testfs
+
+log_pass "CS-not-UN FS: lookup succeeds only if using exact name form"
diff --git a/tests/zfs-tests/tests/functional/casenorm/setup.ksh b/tests/zfs-tests/tests/functional/casenorm/setup.ksh
new file mode 100755
index 000000000000..9eee108195bd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/casenorm/setup.ksh
@@ -0,0 +1,27 @@
+#!/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 2015 Nexenta Systems, Inc. All rights reserved.
+#
+
+#
+# Copyright (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+DISK=${DISKS%% *}
+log_must zpool create $TESTPOOL $DISK
+log_pass
diff --git a/tests/zfs-tests/tests/functional/channel_program/Makefile.am b/tests/zfs-tests/tests/functional/channel_program/Makefile.am
new file mode 100644
index 000000000000..3886863d1dfb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = \
+ lua_core \
+ synctask_core
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/channel_program
+dist_pkgdata_DATA = channel_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib b/tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib
new file mode 100644
index 000000000000..a828ba29065e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/channel_common.kshlib
@@ -0,0 +1,230 @@
+#
+# 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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+ZCP_ROOT=$STF_SUITE/tests/functional/channel_program
+
+#
+# Note: In case of failure (log_fail) in this function
+# we delete the file passed as <input file> so the
+# test suite doesn't leak temp files on failures. So it
+# is expected that <input file> is a temp file and not
+# an installed file.
+#
+# <exitcode> <expected error string> <input file> <zfs program args>
+# e.g. log_program 0 "" tmp.7a12V $POOL foo.zcp arg1 arg2
+function log_program
+{
+ typeset expectexit=$1
+ shift
+ typeset expecterror=$1
+ shift
+ typeset tmpin=$1
+ shift
+ typeset cmdargs=$@ tmpout=$(mktemp) tmperr=$(mktemp)
+
+ # Expected output/error filename is the same as the .zcp name
+ typeset basename
+ if [[ $2 != "-" ]]; then
+ basename=${2%.*}
+ fi
+
+ log_note "running: zfs program $cmdargs:"
+
+ zfs program $cmdargs >$tmpout 2>$tmperr
+ typeset ret=$?
+
+ log_note "input:\n$(cat $tmpin)"
+ log_note "output:\n$(cat $tmpout)"
+ log_note "error:\n$(cat $tmperr)"
+
+ #
+ # Verify correct return value
+ #
+ if [[ $ret -ne $expectexit ]]; then
+ rm $tmpout $tmperr $tmpin
+ log_fail "return mismatch: expected $expectexit, got $ret"
+ fi
+
+ #
+ # Check the output or reported error for successful or error returns,
+ # respectively.
+ #
+ if [[ -f "$basename.out" ]] && [[ $expectexit -eq 0 ]]; then
+
+ outdiff=$(diff "$basename.out" "$tmpout")
+ if [[ $? -ne 0 ]]; then
+ output=$(<$tmpout)
+ rm $tmpout $tmperr $tmpin
+ log_fail "Output mismatch. Expected:\n" \
+ "$(<$basename.out)\nBut got:\n$output\n" \
+ "Diff:\n$outdiff"
+ fi
+
+ elif [[ -f "$basename.err" ]] && [[ $expectexit -ne 0 ]]; then
+
+ outdiff=$(diff "$basename.err" "$tmperr")
+ if [[ $? -ne 0 ]]; then
+ outputerror=$(<$tmperr)
+ rm $tmpout $tmperr $tmpin
+ log_fail "Error mismatch. Expected:\n" \
+ "$(<$basename.err)\nBut got:\n$outputerror\n" \
+ "Diff:\n$outdiff"
+ fi
+
+ elif [[ -n $expecterror ]] && [[ $expectexit -ne 0 ]]; then
+
+ grep -q "$expecterror" $tmperr
+ if [[ $? -ne 0 ]]; then
+ outputerror=$(<$tmperr)
+ rm $tmpout $tmperr $tmpin
+ log_fail "Error mismatch. Expected to contain:\n" \
+ "$expecterror\nBut got:\n$outputerror\n"
+ fi
+
+ elif [[ $expectexit -ne 0 ]]; then
+ #
+ # If there's no expected output, error reporting is allowed to
+ # vary, but ensure that we didn't fail silently.
+ #
+ if [[ -z "$(<$tmperr)" ]]; then
+ rm $tmpout $tmperr $tmpin
+ log_fail "error with no stderr output"
+ fi
+ fi
+
+ #
+ # Clean up all temp files except $tmpin which is
+ # reused for the second invocation of log_program.
+ #
+ rm $tmpout $tmperr
+}
+
+#
+# Even though the command's arguments are passed correctly
+# to the log_must_program family of wrappers the majority
+# of the time, zcp scripts passed as HERE documents can
+# make things trickier (see comment within the function
+# below) in the ordering of the commands arguments and how
+# they are passed. Thus, with this function we reconstruct
+# them to ensure that they are passed properly.
+#
+function log_program_construct_args
+{
+ typeset tmpin=$1
+ shift
+
+ args=""
+ i=0
+ while getopts "nt:m:" opt; do
+ case $opt in
+ t) args="$args -t $OPTARG"; i=$(($i + 2)) ;;
+ m) args="$args -m $OPTARG"; i=$(($i + 2)) ;;
+ n) args="$args -n"; i=$(($i + 1)) ;;
+ esac
+ done
+ shift $i
+
+ pool=$1
+ shift
+
+ infile=$1
+ shift
+
+ #
+ # Copy the contents of the original channel program to $tmpin.
+ #
+ # If $infile currently holds "-" (a dash) it means that we consume a
+ # HERE doc from stdin, otherwise $infile is a file path.
+ #
+ cat $infile > $tmpin
+
+ lua_args=$@
+
+ echo "$args $pool $tmpin $lua_args"
+}
+
+#
+# Program should complete successfully
+# when run in either context.
+#
+function log_must_program
+{
+ typeset tmpin=$(mktemp)
+
+ program_args=$(log_program_construct_args $tmpin $@)
+
+ log_program 0 "" $tmpin "-n $program_args"
+ log_program 0 "" $tmpin "$program_args"
+
+ rm $tmpin
+}
+#
+# Program should error as expected in
+# the same way in both contexts.
+#
+function log_mustnot_checkerror_program
+{
+ typeset expecterror=$1
+ shift
+ typeset tmpin=$(mktemp)
+
+ program_args=$(log_program_construct_args $tmpin $@)
+
+ log_program 1 "$expecterror" $tmpin "-n $program_args"
+ log_program 1 "$expecterror" $tmpin "$program_args"
+
+ rm $tmpin
+}
+
+#
+# Program should fail when run in either
+# context.
+#
+function log_mustnot_program
+{
+ log_mustnot_checkerror_program "" $@
+}
+
+
+#
+# Program should error as expected in
+# open context but complete successfully
+# in syncing context.
+#
+function log_mustnot_checkerror_program_open
+{
+ typeset expecterror=$1
+ shift
+ typeset tmpin=$(mktemp)
+
+ program_args=$(log_program_construct_args $tmpin $@)
+
+ log_program 1 "$expecterror" $tmpin "-n $program_args"
+ log_program 0 "" $tmpin "$program_args"
+
+ rm $tmpin
+}
+
+#
+# Program should complete successfully
+# when run in syncing context but fail
+# when attempted to run in open context.
+#
+function log_must_program_sync
+{
+ log_mustnot_checkerror_program_open "requires passing sync=TRUE" $@
+}
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/Makefile.am b/tests/zfs-tests/tests/functional/channel_program/lua_core/Makefile.am
new file mode 100644
index 000000000000..fb352081190c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/Makefile.am
@@ -0,0 +1,46 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/channel_program/lua_core
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ tst.args_to_lua.ksh \
+ tst.divide_by_zero.ksh \
+ tst.exists.ksh \
+ tst.integer_illegal.ksh \
+ tst.integer_overflow.ksh \
+ tst.language_functions_neg.ksh \
+ tst.language_functions_pos.ksh \
+ tst.large_prog.ksh \
+ tst.libraries.ksh \
+ tst.memory_limit.ksh \
+ tst.nested_neg.ksh \
+ tst.nested_pos.ksh \
+ tst.nvlist_to_lua.ksh \
+ tst.recursive_neg.ksh \
+ tst.recursive_pos.ksh \
+ tst.return_large.ksh \
+ tst.return_nvlist_neg.ksh \
+ tst.return_nvlist_pos.ksh \
+ tst.return_recursive_table.ksh \
+ tst.stack_gsub.ksh \
+ tst.timeout.ksh
+
+dist_pkgdata_DATA = \
+ tst.args_to_lua.out \
+ tst.args_to_lua.zcp \
+ tst.divide_by_zero.err \
+ tst.divide_by_zero.zcp \
+ tst.exists.zcp \
+ tst.large_prog.out \
+ tst.large_prog.zcp \
+ tst.lib_base.lua \
+ tst.lib_coroutine.lua \
+ tst.lib_strings.lua \
+ tst.lib_table.lua \
+ tst.nested_neg.zcp \
+ tst.nested_pos.zcp \
+ tst.recursive.zcp \
+ tst.return_large.zcp \
+ tst.return_recursive_table.zcp \
+ tst.stack_gsub.err \
+ tst.stack_gsub.zcp \
+ tst.timeout.zcp
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/cleanup.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/cleanup.ksh
new file mode 100755
index 000000000000..281f639a4276
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/setup.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/setup.ksh
new file mode 100755
index 000000000000..2516b6b8ad9e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup ${DISK}
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.ksh
new file mode 100755
index 000000000000..6ec5610639de
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Passing arguments to lua programs should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Passing arguments to lua programs should work correctly."
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.args_to_lua.zcp foo bar
+
+log_pass "Passing arguments to lua programs should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.out b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.out
new file mode 100644
index 000000000000..84191f8f803c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.out
@@ -0,0 +1 @@
+Channel program fully executed with no return value.
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.zcp
new file mode 100644
index 000000000000..f6f14e5222f9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.args_to_lua.zcp
@@ -0,0 +1,25 @@
+--
+-- 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.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> foo bar"
+
+arg = ...
+argv = arg["argv"]
+
+assert(#argv == 2)
+assert(argv[1] == "foo")
+assert(argv[2] == "bar")
+
+return
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.err b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.err
new file mode 100644
index 000000000000..fd67d09f7309
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.err
@@ -0,0 +1,4 @@
+Channel program execution failed:
+[string "channel program"]:16: attempt to divide by zero
+stack traceback:
+ [string "channel program"]:16: in main chunk
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.ksh
new file mode 100755
index 000000000000..2587c594da0d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Divide by zero should fail gracefully.
+#
+
+verify_runnable "global"
+
+log_assert "Divide by zero should fail gracefully."
+
+log_mustnot_program $TESTPOOL $ZCP_ROOT/lua_core/tst.divide_by_zero.zcp
+
+log_pass "Divide by zero should fail gracefully."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.zcp
new file mode 100644
index 000000000000..bd882d493b63
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.divide_by_zero.zcp
@@ -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 (c) 2016 by Delphix. All rights reserved.
+--
+
+return 1 / 0
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.exists.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.exists.ksh
new file mode 100755
index 000000000000..d486c25f4487
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.exists.ksh
@@ -0,0 +1,45 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs.exists should accurately report whether a dataset exists, and
+# report an error if a dataset is in another pool.
+
+verify_runnable "global"
+
+# create $TESTSNAP and $TESTCLONE
+create_snapshot
+create_clone
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS@$TESTSNAP && \
+ log_must zfs destroy -R $TESTPOOL/$TESTFS@$TESTSNAP
+}
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.exists.zcp \
+ $TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTFS@$TESTSNAP \
+ $TESTPOOL/$TESTCLONE
+
+log_mustnot_checkerror_program "not in the target pool" \
+ $TESTPOOL - <<-EOF
+ return zfs.exists('rpool')
+EOF
+
+log_pass "zfs.exists() gives correct results"
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.exists.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.exists.zcp
new file mode 100644
index 000000000000..e44cf4560502
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.exists.zcp
@@ -0,0 +1,26 @@
+--
+-- 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.
+--
+
+-- ensure zfs.exists works as expected.
+
+args = ...
+argv = args['argv']
+pool = argv[1]
+
+for i = 1,4 do
+ assert(zfs.exists(argv[i]))
+end
+
+assert(not zfs.exists(pool .. '/notadataset'))
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_illegal.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_illegal.ksh
new file mode 100755
index 000000000000..c34f2afd9e18
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_illegal.ksh
@@ -0,0 +1,41 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Constructing integers that are doubles, too large, or too
+# small should fail gracefully.
+#
+
+verify_runnable "global"
+
+log_assert "constructing illegal integer values should fail gracefully"
+
+set -A args "1.0" \
+ "1.5" \
+ "-1.5"
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot_checkerror_program "malformed number" $TESTPOOL - <<-EOF
+ return ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "constructing illegal integer values should fail gracefully"
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_overflow.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_overflow.ksh
new file mode 100755
index 000000000000..c129bae51b04
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.integer_overflow.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Overflowing a 64-bit integer should wrap around.
+#
+
+verify_runnable "global"
+
+log_assert "overflowing a 64-bit integer should wrap around"
+
+log_must_program $TESTPOOL - <<-EOF
+ assert(18446744073709551615 + 1 == (-18446744073709551616))
+EOF
+
+log_pass "overflowing a 64-bit integer should wrap around"
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_neg.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_neg.ksh
new file mode 100755
index 000000000000..0125d76c7036
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_neg.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try channel programs with various lua runtime issues.
+# the program should fail, but the system should not crash.
+# Issues include:
+# * syntax errors
+# * misuse of language constructs (e.g. indexing non-tables)
+# * the error() function
+# * the assert() function
+#
+
+verify_runnable "global"
+
+set -A args "{]" \
+ "retrn 1" \
+ "abc = nil; abc.deref" \
+ "abc = nil; abc()" \
+ "error(0)" \
+ "error(\"string\")" \
+ "error(true)" \
+ "error({})" \
+ "assert(false)"
+
+log_assert "Runtime errors in lua scripts fail as expected."
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_mustnot_checkerror_program "execution failed" $TESTPOOL - <<-EOF
+ ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Runtime errors in lua scripts fail as expected."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_pos.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_pos.ksh
new file mode 100755
index 000000000000..924d8e2c6944
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.language_functions_pos.ksh
@@ -0,0 +1,42 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try very simple programs that interact with the core lua
+# runtime rather than ZFS functions, just to make sure the
+# runtime is hooked up correctly.
+#
+
+verify_runnable "global"
+
+set -A args "" \
+ "assert(true)" \
+ "x = 1 + 1"
+
+log_assert "Simple lua scripts pass."
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_must_program $TESTPOOL - <<-EOF
+ ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Simple lua scripts pass."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.ksh
new file mode 100755
index 000000000000..21ab69adb1c7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Running a large program file should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Running a large program file should work correctly."
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.large_prog.zcp
+
+log_pass "Running a large program file should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.out b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.out
new file mode 100644
index 000000000000..84191f8f803c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.out
@@ -0,0 +1 @@
+Channel program fully executed with no return value.
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.zcp
new file mode 100644
index 000000000000..add68973349e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.large_prog.zcp
@@ -0,0 +1,280 @@
+--
+-- 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.
+--
+
+-- /sbin/zfs initially allocates 1KB for the channel program file. This
+-- program file is larger than that, to test the reallocation and
+-- passing of a large channel string to the kernel.
+-- This file is at least 16KB long.
+
+--[[
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+1234567890123456789012345678901234567890123456789012345678901234
+]]
+
+return
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_base.lua b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_base.lua
new file mode 100644
index 000000000000..c39144959a3f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_base.lua
@@ -0,0 +1,469 @@
+--[[
+--*****************************************************************************
+--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
+--*
+--* Permission is hereby granted, free of charge, to any person obtaining
+--* a copy of this software and associated documentation files (the
+--* "Software"), to deal in the Software without restriction, including
+--* without limitation the rights to use, copy, modify, merge, publish,
+--* distribute, sublicense, and/or sell copies of the Software, and to
+--* permit persons to whom the Software is furnished to do so, subject to
+--* the following conditions:
+--*
+--* The above copyright notice and this permission notice shall be
+--* included in all copies or substantial portions of the Software.
+--*
+--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--*****************************************************************************
+--]]
+
+-- testing metatables
+
+X = 20; B = 30
+
+_ENV = setmetatable({}, {__index=_G})
+
+collectgarbage()
+
+X = X+10
+assert(X == 30 and _G.X == 20)
+B = false
+assert(B == false)
+B = nil
+assert(B == 30)
+
+assert(getmetatable{} == nil)
+assert(getmetatable(4) == nil)
+assert(getmetatable(nil) == nil)
+a={name = "NAME"}; setmetatable(a, {__metatable = "xuxu",
+ __tostring=function(x) return x.name end})
+assert(getmetatable(a) == "xuxu")
+assert(tostring(a) == "NAME")
+
+local a, t = {10,20,30; x="10", y="20"}, {}
+assert(setmetatable(a,t) == a)
+assert(getmetatable(a) == t)
+assert(setmetatable(a,nil) == a)
+assert(getmetatable(a) == nil)
+assert(setmetatable(a,t) == a)
+
+
+function f (t, i, e)
+ assert(not e)
+ local p = rawget(t, "parent")
+ return (p and p[i]+3), "dummy return"
+end
+
+t.__index = f
+
+a.parent = {z=25, x=12, [4] = 24}
+assert(a[1] == 10 and a.z == 28 and a[4] == 27 and a.x == "10")
+
+collectgarbage()
+
+a = setmetatable({}, t)
+function f(t, i, v) rawset(t, i, v-3) end
+setmetatable(t, t) -- causes a bug in 5.1 !
+t.__newindex = f
+a[1] = 30; a.x = "101"; a[5] = 200
+assert(a[1] == 27 and a.x == 98 and a[5] == 197)
+
+
+local c = {}
+a = setmetatable({}, t)
+t.__newindex = c
+a[1] = 10; a[2] = 20; a[3] = 90
+assert(c[1] == 10 and c[2] == 20 and c[3] == 90)
+
+
+do
+ local a;
+ a = setmetatable({}, {__index = setmetatable({},
+ {__index = setmetatable({},
+ {__index = function (_,n) return a[n-3]+4, "lixo" end})})})
+ a[0] = 20
+ for i=0,10 do
+ assert(a[i*3] == 20 + i*4)
+ end
+end
+
+
+do -- newindex
+ local foi
+ local a = {}
+ for i=1,10 do a[i] = 0; a['a'..i] = 0; end
+ setmetatable(a, {__newindex = function (t,k,v) foi=true; rawset(t,k,v) end})
+ foi = false; a[1]=0; assert(not foi)
+ foi = false; a['a1']=0; assert(not foi)
+ foi = false; a['a11']=0; assert(foi)
+ foi = false; a[11]=0; assert(foi)
+ foi = false; a[1]=nil; assert(not foi)
+ foi = false; a[1]=nil; assert(foi)
+end
+
+
+setmetatable(t, nil)
+function f (t, ...) return t, {...} end
+t.__call = f
+
+do
+ local x,y = a(table.unpack{'a', 1})
+ assert(x==a and y[1]=='a' and y[2]==1 and y[3]==nil)
+ x,y = a()
+ assert(x==a and y[1]==nil)
+end
+
+
+local b = setmetatable({}, t)
+setmetatable(b,t)
+
+function f(op)
+ return function (...) cap = {[0] = op, ...} ; return (...) end
+end
+t.__add = f("add")
+t.__sub = f("sub")
+t.__mul = f("mul")
+t.__div = f("div")
+t.__mod = f("mod")
+t.__unm = f("unm")
+t.__pow = f("pow")
+t.__len = f("len")
+
+assert(b+5 == b)
+assert(cap[0] == "add" and cap[1] == b and cap[2] == 5 and cap[3]==nil)
+assert(b+'5' == b)
+assert(cap[0] == "add" and cap[1] == b and cap[2] == '5' and cap[3]==nil)
+assert(5+b == 5)
+assert(cap[0] == "add" and cap[1] == 5 and cap[2] == b and cap[3]==nil)
+assert('5'+b == '5')
+assert(cap[0] == "add" and cap[1] == '5' and cap[2] == b and cap[3]==nil)
+b=b-3; assert(getmetatable(b) == t)
+assert(5-a == 5)
+assert(cap[0] == "sub" and cap[1] == 5 and cap[2] == a and cap[3]==nil)
+assert('5'-a == '5')
+assert(cap[0] == "sub" and cap[1] == '5' and cap[2] == a and cap[3]==nil)
+assert(a*a == a)
+assert(cap[0] == "mul" and cap[1] == a and cap[2] == a and cap[3]==nil)
+assert(a/0 == a)
+assert(cap[0] == "div" and cap[1] == a and cap[2] == 0 and cap[3]==nil)
+assert(a%2 == a)
+assert(cap[0] == "mod" and cap[1] == a and cap[2] == 2 and cap[3]==nil)
+assert(-a == a)
+assert(cap[0] == "unm" and cap[1] == a)
+assert(a^4 == a)
+assert(cap[0] == "pow" and cap[1] == a and cap[2] == 4 and cap[3]==nil)
+assert(a^'4' == a)
+assert(cap[0] == "pow" and cap[1] == a and cap[2] == '4' and cap[3]==nil)
+assert(4^a == 4)
+assert(cap[0] == "pow" and cap[1] == 4 and cap[2] == a and cap[3]==nil)
+assert('4'^a == '4')
+assert(cap[0] == "pow" and cap[1] == '4' and cap[2] == a and cap[3]==nil)
+assert(#a == a)
+assert(cap[0] == "len" and cap[1] == a)
+
+
+-- test for rawlen
+t = setmetatable({1,2,3}, {__len = function () return 10 end})
+assert(#t == 10 and rawlen(t) == 3)
+assert(rawlen"abc" == 3)
+assert(rawlen(string.rep('a', 1000)) == 1000)
+
+t = {}
+t.__lt = function (a,b,c)
+ collectgarbage()
+ assert(c == nil)
+ if type(a) == 'table' then a = a.x end
+ if type(b) == 'table' then b = b.x end
+ return a<b, "dummy"
+end
+
+function Op(x) return setmetatable({x=x}, t) end
+
+local function test ()
+ assert(not(Op(1)<Op(1)) and (Op(1)<Op(2)) and not(Op(2)<Op(1)))
+ assert(not(1 < Op(1)) and (Op(1) < 2) and not(2 < Op(1)))
+ assert(not(Op('a')<Op('a')) and (Op('a')<Op('b')) and not(Op('b')<Op('a')))
+ assert(not('a' < Op('a')) and (Op('a') < 'b') and not(Op('b') < Op('a')))
+ assert((Op(1)<=Op(1)) and (Op(1)<=Op(2)) and not(Op(2)<=Op(1)))
+ assert((Op('a')<=Op('a')) and (Op('a')<=Op('b')) and not(Op('b')<=Op('a')))
+ assert(not(Op(1)>Op(1)) and not(Op(1)>Op(2)) and (Op(2)>Op(1)))
+ assert(not(Op('a')>Op('a')) and not(Op('a')>Op('b')) and (Op('b')>Op('a')))
+ assert((Op(1)>=Op(1)) and not(Op(1)>=Op(2)) and (Op(2)>=Op(1)))
+ assert((1 >= Op(1)) and not(1 >= Op(2)) and (Op(2) >= 1))
+ assert((Op('a')>=Op('a')) and not(Op('a')>=Op('b')) and (Op('b')>=Op('a')))
+ assert(('a' >= Op('a')) and not(Op('a') >= 'b') and (Op('b') >= Op('a')))
+end
+
+test()
+
+t.__le = function (a,b,c)
+ assert(c == nil)
+ if type(a) == 'table' then a = a.x end
+ if type(b) == 'table' then b = b.x end
+ return a<=b, "dummy"
+end
+
+test() -- retest comparisons, now using both `lt' and `le'
+
+
+-- test `partial order'
+
+local function Set(x)
+ local y = {}
+ for _,k in pairs(x) do y[k] = 1 end
+ return setmetatable(y, t)
+end
+
+t.__lt = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ b[k] = nil
+ end
+ return next(b) ~= nil
+end
+
+t.__le = nil
+
+assert(Set{1,2,3} < Set{1,2,3,4})
+assert(not(Set{1,2,3,4} < Set{1,2,3,4}))
+assert((Set{1,2,3,4} <= Set{1,2,3,4}))
+assert((Set{1,2,3,4} >= Set{1,2,3,4}))
+assert((Set{1,3} <= Set{3,5})) -- wrong!! model needs a `le' method ;-)
+
+t.__le = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ end
+ return true
+end
+
+assert(not (Set{1,3} <= Set{3,5})) -- now its OK!
+assert(not(Set{1,3} <= Set{3,5}))
+assert(not(Set{1,3} >= Set{3,5}))
+
+t.__eq = function (a,b)
+ for k in pairs(a) do
+ if not b[k] then return false end
+ b[k] = nil
+ end
+ return next(b) == nil
+end
+
+local s = Set{1,3,5}
+assert(s == Set{3,5,1})
+assert(not rawequal(s, Set{3,5,1}))
+assert(rawequal(s, s))
+assert(Set{1,3,5,1} == Set{3,5,1})
+assert(Set{1,3,5} ~= Set{3,5,1,6})
+t[Set{1,3,5}] = 1
+assert(t[Set{1,3,5}] == nil) -- `__eq' is not valid for table accesses
+
+
+t.__concat = function (a,b,c)
+ assert(c == nil)
+ if type(a) == 'table' then a = a.val end
+ if type(b) == 'table' then b = b.val end
+ if A then return a..b
+ else
+ return setmetatable({val=a..b}, t)
+ end
+end
+
+c = {val="c"}; setmetatable(c, t)
+d = {val="d"}; setmetatable(d, t)
+
+A = true
+assert(c..d == 'cd')
+assert(0 .."a".."b"..c..d.."e".."f"..(5+3).."g" == "0abcdef8g")
+
+A = false
+assert((c..d..c..d).val == 'cdcd')
+x = c..d
+assert(getmetatable(x) == t and x.val == 'cd')
+x = 0 .."a".."b"..c..d.."e".."f".."g"
+assert(x.val == "0abcdefg")
+
+
+-- concat metamethod x numbers (bug in 5.1.1)
+c = {}
+local x
+setmetatable(c, {__concat = function (a,b)
+ assert(type(a) == "number" and b == c or type(b) == "number" and a == c)
+ return c
+end})
+assert(c..5 == c and 5 .. c == c)
+assert(4 .. c .. 5 == c and 4 .. 5 .. 6 .. 7 .. c == c)
+
+
+-- test comparison compatibilities
+local t1, t2, c, d
+t1 = {}; c = {}; setmetatable(c, t1)
+d = {}
+t1.__eq = function () return true end
+t1.__lt = function () return true end
+setmetatable(d, t1)
+assert(c == d and c < d and not(d <= c))
+t2 = {}
+t2.__eq = t1.__eq
+t2.__lt = t1.__lt
+setmetatable(d, t2)
+assert(c == d and c < d and not(d <= c))
+
+
+
+-- test for several levels of calls
+local i
+local tt = {
+ __call = function (t, ...)
+ i = i+1
+ if t.f then return t.f(...)
+ else return {...}
+ end
+ end
+}
+
+local a = setmetatable({}, tt)
+local b = setmetatable({f=a}, tt)
+local c = setmetatable({f=b}, tt)
+
+i = 0
+x = c(3,4,5)
+assert(i == 3 and x[1] == 3 and x[3] == 5)
+
+
+assert(_G.X == 20)
+
+
+local _g = _G
+_ENV = setmetatable({}, {__index=function (_,k) return _g[k] end})
+
+
+a = {}
+rawset(a, "x", 1, 2, 3)
+assert(a.x == 1 and rawget(a, "x", 3) == 1)
+
+
+-- bug in 5.1
+T, K, V = nil
+grandparent = {}
+grandparent.__newindex = function(t,k,v) T=t; K=k; V=v end
+
+parent = {}
+parent.__newindex = parent
+setmetatable(parent, grandparent)
+
+child = setmetatable({}, parent)
+child.foo = 10 --> CRASH (on some machines)
+assert(T == parent and K == "foo" and V == 10)
+
+
+-- testing 'tonumber'
+assert(tonumber{} == nil)
+assert(tonumber('-012') == -010-2)
+assert(tonumber("0xffffffffffff") == 2^(4*12) - 1)
+assert(tonumber("0x"..string.rep("f", 150)) == 2^(4*150) - 1)
+
+-- testing 'tonumber' with base
+assert(tonumber(' 001010 ', 2) == 10)
+assert(tonumber(' 001010 ', 10) == 1010)
+assert(tonumber(' -1010 ', 2) == -10)
+assert(tonumber('10', 36) == 36)
+assert(tonumber(' -10 ', 36) == -36)
+assert(tonumber(' +1Z ', 36) == 36 + 35)
+assert(tonumber(' -1z ', 36) == -36 + -35)
+assert(tonumber('-fFfa', 16) == -(10+(16*(15+(16*(15+(16*15)))))))
+assert(tonumber(string.rep('1', 42), 2) + 1 == 2^42)
+assert(tonumber(string.rep('1', 34), 2) + 1 == 2^34)
+assert(tonumber('ffffFFFF', 16)+1 == 2^32)
+assert(tonumber('0ffffFFFF', 16)+1 == 2^32)
+assert(tonumber('-0ffffffFFFF', 16) - 1 == -2^40)
+for i = 2,36 do
+ assert(tonumber('\t10000000000\t', i) == i^10)
+end
+
+-- testing 'tonumber' for invalid formats
+function f(...)
+ if select('#', ...) == 1 then
+ return (...)
+ else
+ return "***"
+ end
+end
+
+assert(f(tonumber('fFfa', 15)) == nil)
+assert(f(tonumber('099', 8)) == nil)
+assert(f(tonumber('1\0', 2)) == nil)
+assert(f(tonumber('', 8)) == nil)
+assert(f(tonumber(' ', 9)) == nil)
+assert(f(tonumber('0xf', 10)) == nil)
+
+assert(f(tonumber('inf')) == nil)
+assert(f(tonumber(' INF ')) == nil)
+assert(f(tonumber('Nan')) == nil)
+assert(f(tonumber('nan')) == nil)
+
+assert(f(tonumber('')) == nil)
+assert(f(tonumber('1 a')) == nil)
+assert(f(tonumber('1\0')) == nil)
+assert(f(tonumber('1 \0')) == nil)
+assert(f(tonumber('1\0 ')) == nil)
+assert(f(tonumber('e1')) == nil)
+assert(f(tonumber('e 1')) == nil)
+
+
+-- testing 'tonumber' for invalid hexadecimal formats
+assert(tonumber('0x') == nil)
+assert(tonumber('x') == nil)
+assert(tonumber('x3') == nil)
+assert(tonumber('00x2') == nil)
+assert(tonumber('0x 2') == nil)
+assert(tonumber('0 x2') == nil)
+assert(tonumber('23x') == nil)
+assert(tonumber('- 0xaa') == nil)
+
+
+-- testing hexadecimal numerals
+assert(tonumber('+0x2') == 2)
+assert(tonumber('-0xaA') == -170)
+assert(tonumber('-0xffFFFfff') == -2^32 + 1)
+
+
+-- testing 'tostring'
+assert(tostring("alo") == "alo")
+assert(tostring(12) == "12")
+assert(tostring(1234567890123) == '1234567890123')
+assert(type(tostring("hello")) == "string")
+assert(tostring(true) == "true")
+assert(tostring(false) == "false")
+assert(string.find(tostring{}, 'table:'))
+assert(string.find(tostring(select), 'function:'))
+assert(#tostring('\0') == 1)
+
+
+-- testing ipairs
+local x = 0
+for k,v in ipairs{10,20,30;x=12} do
+ x = x + 1
+ assert(k == x and v == x * 10)
+end
+
+for _ in ipairs{x=12, y=24} do assert(nil) end
+
+-- test for 'false' x ipair
+x = false
+local i = 0
+for k,v in ipairs{true,false,true,false} do
+ i = i + 1
+ x = not x
+ assert(x == v)
+end
+assert(i == 4)
+
+
+return "OK"
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_coroutine.lua b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_coroutine.lua
new file mode 100644
index 000000000000..e0e9e2a64fbc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_coroutine.lua
@@ -0,0 +1,362 @@
+--[[
+--*****************************************************************************
+--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
+--*
+--* Permission is hereby granted, free of charge, to any person obtaining
+--* a copy of this software and associated documentation files (the
+--* "Software"), to deal in the Software without restriction, including
+--* without limitation the rights to use, copy, modify, merge, publish,
+--* distribute, sublicense, and/or sell copies of the Software, and to
+--* permit persons to whom the Software is furnished to do so, subject to
+--* the following conditions:
+--*
+--* The above copyright notice and this permission notice shall be
+--* included in all copies or substantial portions of the Software.
+--*
+--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--*****************************************************************************
+--]]
+
+local f
+
+local main, ismain = coroutine.running()
+assert(type(main) == "thread" and ismain)
+assert(not coroutine.resume(main))
+
+
+-- tests for multiple yield/resume arguments
+
+local function eqtab (t1, t2)
+ assert(#t1 == #t2)
+ for i = 1, #t1 do
+ local v = t1[i]
+ assert(t2[i] == v)
+ end
+end
+
+_G.x = nil -- declare x
+function foo (a, ...)
+ local x, y = coroutine.running()
+ assert(x == f and y == false)
+ -- next call should not corrupt coroutine (but must fail,
+ -- as it attempts to resume the running coroutine)
+ assert(coroutine.resume(f) == false)
+ assert(coroutine.status(f) == "running")
+ local arg = {...}
+ for i=1,#arg do
+ _G.x = {coroutine.yield(table.unpack(arg[i]))}
+ end
+ return table.unpack(a)
+end
+
+f = coroutine.create(foo)
+assert(type(f) == "thread" and coroutine.status(f) == "suspended")
+assert(string.find(tostring(f), "thread"))
+local s,a,b,c,d
+s,a,b,c,d = coroutine.resume(f, {1,2,3}, {}, {1}, {'a', 'b', 'c'})
+assert(s and a == nil and coroutine.status(f) == "suspended")
+s,a,b,c,d = coroutine.resume(f)
+eqtab(_G.x, {})
+assert(s and a == 1 and b == nil)
+s,a,b,c,d = coroutine.resume(f, 1, 2, 3)
+eqtab(_G.x, {1, 2, 3})
+assert(s and a == 'a' and b == 'b' and c == 'c' and d == nil)
+s,a,b,c,d = coroutine.resume(f, "xuxu")
+eqtab(_G.x, {"xuxu"})
+assert(s and a == 1 and b == 2 and c == 3 and d == nil)
+assert(coroutine.status(f) == "dead")
+s, a = coroutine.resume(f, "xuxu")
+assert(not s and string.find(a, "dead") and coroutine.status(f) == "dead")
+
+
+-- yields in tail calls
+local function foo (i) return coroutine.yield(i) end
+f = coroutine.wrap(function ()
+ for i=1,10 do
+ assert(foo(i) == _G.x)
+ end
+ return 'a'
+end)
+for i=1,10 do _G.x = i; assert(f(i) == i) end
+_G.x = 'xuxu'; assert(f('xuxu') == 'a')
+
+-- recursive
+function pf (n, i)
+ coroutine.yield(n)
+ pf(n*i, i+1)
+end
+
+f = coroutine.wrap(pf)
+local s=1
+for i=1,10 do
+ assert(f(1, 1) == s)
+ s = s*i
+end
+
+-- sieve implemented with co-routines
+
+-- generate all the numbers from 2 to n
+function gen (n)
+ return coroutine.wrap(function ()
+ for i=2,n do coroutine.yield(i) end
+ end)
+end
+
+-- filter the numbers generated by 'g', removing multiples of 'p'
+function filter (p, g)
+ return coroutine.wrap(function ()
+ for n in g do
+ if n%p ~= 0 then coroutine.yield(n) end
+ end
+ end)
+end
+
+-- generate primes up to 20
+local x = gen(20)
+local a = {}
+while 1 do
+ local n = x()
+ if n == nil then break end
+ table.insert(a, n)
+ x = filter(n, x)
+end
+
+-- expect 8 primes and last one is 19
+assert(#a == 8 and a[#a] == 19)
+x, a = nil
+
+
+-- yielding across C boundaries
+
+co = coroutine.wrap(function()
+ coroutine.yield(20)
+ return 30
+ end)
+
+assert(co() == 20)
+assert(co() == 30)
+
+
+local f = function (s, i) return coroutine.yield(i) end
+function f (a, b) a = coroutine.yield(a); error{a + b} end
+function g(x) return x[1]*2 end
+
+
+-- unyieldable C call
+do
+ local function f (c)
+ return c .. c
+ end
+
+ local co = coroutine.wrap(function (c)
+ local s = string.gsub("a", ".", f)
+ return s
+ end)
+ assert(co() == "aa")
+end
+
+
+-- errors in coroutines
+function foo ()
+ coroutine.yield(3)
+ error(foo)
+end
+
+function goo() foo() end
+x = coroutine.wrap(goo)
+assert(x() == 3)
+x = coroutine.create(goo)
+a,b = coroutine.resume(x)
+assert(a and b == 3)
+a,b = coroutine.resume(x)
+assert(not a and b == foo and coroutine.status(x) == "dead")
+a,b = coroutine.resume(x)
+assert(not a and string.find(b, "dead") and coroutine.status(x) == "dead")
+
+
+-- co-routines x for loop
+function all (a, n, k)
+ if k == 0 then coroutine.yield(a)
+ else
+ for i=1,n do
+ a[k] = i
+ all(a, n, k-1)
+ end
+ end
+end
+
+local a = 0
+for t in coroutine.wrap(function () all({}, 5, 4) end) do
+ a = a+1
+end
+assert(a == 5^4)
+
+
+-- access to locals of collected corroutines
+local C = {}; setmetatable(C, {__mode = "kv"})
+local x = coroutine.wrap (function ()
+ local a = 10
+ local function f () a = a+10; return a end
+ while true do
+ a = a+1
+ coroutine.yield(f)
+ end
+ end)
+
+C[1] = x;
+
+local f = x()
+assert(f() == 21 and x()() == 32 and x() == f)
+x = nil
+collectgarbage()
+assert(C[1] == nil)
+assert(f() == 43 and f() == 53)
+
+
+-- old bug: attempt to resume itself
+
+function co_func (current_co)
+ assert(coroutine.running() == current_co)
+ assert(coroutine.resume(current_co) == false)
+ coroutine.yield(10, 20)
+ assert(coroutine.resume(current_co) == false)
+ coroutine.yield(23)
+ return 10
+end
+
+local co = coroutine.create(co_func)
+local a,b,c = coroutine.resume(co, co)
+assert(a == true and b == 10 and c == 20)
+a,b = coroutine.resume(co, co)
+assert(a == true and b == 23)
+a,b = coroutine.resume(co, co)
+assert(a == true and b == 10)
+assert(coroutine.resume(co, co) == false)
+assert(coroutine.resume(co, co) == false)
+
+
+-- attempt to resume 'normal' coroutine
+local co1, co2
+co1 = coroutine.create(function () return co2() end)
+co2 = coroutine.wrap(function ()
+ assert(coroutine.status(co1) == 'normal')
+ assert(not coroutine.resume(co1))
+ coroutine.yield(3)
+ end)
+
+a,b = coroutine.resume(co1)
+assert(a and b == 3)
+assert(coroutine.status(co1) == 'dead')
+
+
+-- access to locals of erroneous coroutines
+local x = coroutine.create (function ()
+ local a = 10
+ _G.f = function () a=a+1; return a end
+ error('x')
+ end)
+
+assert(not coroutine.resume(x))
+-- overwrite previous position of local `a'
+assert(not coroutine.resume(x, 1, 1, 1, 1, 1, 1, 1))
+assert(_G.f() == 11)
+assert(_G.f() == 12)
+
+
+-- leaving a pending coroutine open
+_X = coroutine.wrap(function ()
+ local a = 10
+ local x = function () a = a+1 end
+ coroutine.yield()
+ end)
+
+_X()
+
+assert(coroutine.running() == main)
+
+
+
+-- testing yields inside metamethods
+
+local mt = {
+ __eq = function(a,b) coroutine.yield(nil, "eq"); return a.x == b.x end,
+ __lt = function(a,b) coroutine.yield(nil, "lt"); return a.x < b.x end,
+ __le = function(a,b) coroutine.yield(nil, "le"); return a - b <= 0 end,
+ __add = function(a,b) coroutine.yield(nil, "add"); return a.x + b.x end,
+ __sub = function(a,b) coroutine.yield(nil, "sub"); return a.x - b.x end,
+ __mod = function(a,b) coroutine.yield(nil, "mod"); return a.x % b.x end,
+ __unm = function(a,b) coroutine.yield(nil, "unm"); return -a.x end,
+
+ __concat = function(a,b)
+ coroutine.yield(nil, "concat");
+ a = type(a) == "table" and a.x or a
+ b = type(b) == "table" and b.x or b
+ return a .. b
+ end,
+ __index = function (t,k) coroutine.yield(nil, "idx"); return t.k[k] end,
+ __newindex = function (t,k,v) coroutine.yield(nil, "nidx"); t.k[k] = v end,
+}
+
+
+local function new (x)
+ return setmetatable({x = x, k = {}}, mt)
+end
+
+
+local a = new(10)
+local b = new(12)
+local c = new"hello"
+
+local function run (f, t)
+ local i = 1
+ local c = coroutine.wrap(f)
+ while true do
+ local res, stat = c()
+ if res then assert(t[i] == nil); return res, t end
+ assert(stat == t[i])
+ i = i + 1
+ end
+end
+
+
+assert(run(function () if (a>=b) then return '>=' else return '<' end end,
+ {"le", "sub"}) == "<")
+-- '<=' using '<'
+mt.__le = nil
+assert(run(function () if (a<=b) then return '<=' else return '>' end end,
+ {"lt"}) == "<=")
+assert(run(function () if (a==b) then return '==' else return '~=' end end,
+ {"eq"}) == "~=")
+
+assert(run(function () return a % b end, {"mod"}) == 10)
+
+assert(run(function () return a..b end, {"concat"}) == "1012")
+
+assert(run(function() return a .. b .. c .. a end,
+ {"concat", "concat", "concat"}) == "1012hello10")
+
+assert(run(function() return "a" .. "b" .. a .. "c" .. c .. b .. "x" end,
+ {"concat", "concat", "concat"}) == "ab10chello12x")
+
+
+-- testing yields inside 'for' iterators
+
+local f = function (s, i)
+ if i%2 == 0 then coroutine.yield(nil, "for") end
+ if i < s then return i + 1 end
+ end
+
+assert(run(function ()
+ local s = 0
+ for i in f, 4, 0 do s = s + i end
+ return s
+ end, {"for", "for", "for"}) == 10)
+
+
+return "OK"
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_strings.lua b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_strings.lua
new file mode 100644
index 000000000000..1725fd123796
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_strings.lua
@@ -0,0 +1,241 @@
+--[[
+--*****************************************************************************
+--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
+--*
+--* Permission is hereby granted, free of charge, to any person obtaining
+--* a copy of this software and associated documentation files (the
+--* "Software"), to deal in the Software without restriction, including
+--* without limitation the rights to use, copy, modify, merge, publish,
+--* distribute, sublicense, and/or sell copies of the Software, and to
+--* permit persons to whom the Software is furnished to do so, subject to
+--* the following conditions:
+--*
+--* The above copyright notice and this permission notice shall be
+--* included in all copies or substantial portions of the Software.
+--*
+--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--*****************************************************************************
+--]]
+
+-- testing string library
+
+local maxi, mini = 0x7fffffffffffffff, 0x8000000000000000
+
+-- testing string.sub
+assert(string.sub("123456789",2,4) == "234")
+assert(string.sub("123456789",7) == "789")
+assert(string.sub("123456789",7,6) == "")
+assert(string.sub("123456789",7,7) == "7")
+assert(string.sub("123456789",0,0) == "")
+assert(string.sub("123456789",-10,10) == "123456789")
+assert(string.sub("123456789",1,9) == "123456789")
+assert(string.sub("123456789",-10,-20) == "")
+assert(string.sub("123456789",-1) == "9")
+assert(string.sub("123456789",-4) == "6789")
+assert(string.sub("123456789",-6, -4) == "456")
+assert(string.sub("123456789", mini, -4) == "123456")
+assert(string.sub("123456789", mini, maxi) == "123456789")
+assert(string.sub("123456789", mini, mini) == "")
+assert(string.sub("\000123456789",3,5) == "234")
+assert(("\000123456789"):sub(8) == "789")
+
+-- testing string.find
+assert(string.find("123456789", "345") == 3)
+a,b = string.find("123456789", "345")
+assert(string.sub("123456789", a, b) == "345")
+assert(string.find("1234567890123456789", "345", 3) == 3)
+assert(string.find("1234567890123456789", "345", 4) == 13)
+assert(string.find("1234567890123456789", "346", 4) == nil)
+assert(string.find("1234567890123456789", ".45", -9) == 13)
+assert(string.find("abcdefg", "\0", 5, 1) == nil)
+assert(string.find("", "") == 1)
+assert(string.find("", "", 1) == 1)
+assert(not string.find("", "", 2))
+assert(string.find('', 'aaa', 1) == nil)
+assert(('alo(.)alo'):find('(.)', 1, 1) == 4)
+
+assert(string.len("") == 0)
+assert(string.len("\0\0\0") == 3)
+assert(string.len("1234567890") == 10)
+
+assert(#"" == 0)
+assert(#"\0\0\0" == 3)
+assert(#"1234567890" == 10)
+
+-- testing string.byte/string.char
+assert(string.byte("a") == 97)
+assert(string.byte("\xe4") > 127)
+assert(string.byte(string.char(255)) == 255)
+assert(string.byte(string.char(0)) == 0)
+assert(string.byte("\0") == 0)
+assert(string.byte("\0\0alo\0x", -1) == string.byte('x'))
+assert(string.byte("ba", 2) == 97)
+assert(string.byte("\n\n", 2, -1) == 10)
+assert(string.byte("\n\n", 2, 2) == 10)
+assert(string.byte("") == nil)
+assert(string.byte("hi", -3) == nil)
+assert(string.byte("hi", 3) == nil)
+assert(string.byte("hi", 9, 10) == nil)
+assert(string.byte("hi", 2, 1) == nil)
+assert(string.char() == "")
+assert(string.char(0, 255, 0) == "\0\255\0")
+assert(string.char(0, string.byte("\xe4"), 0) == "\0\xe4\0")
+assert(string.char(string.byte("\xe4l\0\195\179u", 1, -1)) == "\xe4l\0\195\179u")
+assert(string.char(string.byte("\xe4l\0\195\179u", 1, 0)) == "")
+assert(string.char(string.byte("\xe4l\0\195\179u", -10, 100)) == "\xe4l\0\195\179u")
+
+assert(string.upper("ab\0c") == "AB\0C")
+assert(string.lower("\0ABCc%$") == "\0abcc%$")
+assert(string.rep('teste', 0) == '')
+assert(string.rep('t\195\169s\00t\195\170', 2) == 't\195\169s\0t\195\170t\195\169s\000t\195\170')
+assert(string.rep('', 10) == '')
+
+-- repetitions with separator
+assert(string.rep('teste', 0, 'xuxu') == '')
+assert(string.rep('teste', 1, 'xuxu') == 'teste')
+assert(string.rep('\1\0\1', 2, '\0\0') == '\1\0\1\0\0\1\0\1')
+assert(string.rep('', 10, '.') == string.rep('.', 9))
+
+assert(string.reverse"" == "")
+assert(string.reverse"\0\1\2\3" == "\3\2\1\0")
+assert(string.reverse"\0001234" == "4321\0")
+
+for i=0,30 do assert(string.len(string.rep('a', i)) == i) end
+
+
+x = '"\195\174lo"\n\\'
+assert(string.format('%q%s', x, x) == '"\\"\195\174lo\\"\\\n\\\\""\195\174lo"\n\\')
+assert(string.format('%q', "\0") == [["\0"]])
+x = "\0\1\0023\5\0009"
+assert(string.format("\0%c\0%c%x\0", string.byte("\xe4"), string.byte("b"), 140) ==
+ "\0\xe4\0b8c\0")
+assert(string.format('') == "")
+assert(string.format("%c",34)..string.format("%c",48)..string.format("%c",90)..string.format("%c",100) ==
+ string.format("%c%c%c%c", 34, 48, 90, 100))
+assert(string.format("%s\0 is not \0%s", 'not be', 'be') == 'not be\0 is not \0be')
+assert(string.format("%%%d %010d", 10, 23) == "%10 0000000023")
+x = string.format('"%-50s"', 'a')
+assert(#x == 52)
+assert(string.sub(x, 1, 4) == '"a ')
+
+assert(string.format("-%.20s.20s", string.rep("%", 2000)) ==
+ "-"..string.rep("%", 20)..".20s")
+assert(string.format('"-%20s.20s"', string.rep("%", 2000)) ==
+ string.format("%q", "-"..string.rep("%", 2000)..".20s"))
+
+-- format x tostring
+assert(string.format("%s %s", nil, true) == "nil true")
+assert(string.format("%s %.4s", false, true) == "false true")
+assert(string.format("%.3s %.3s", false, true) == "fal tru")
+
+
+-- testing large numbers for format
+do
+ local max, min = 0x7fffffff, -0x80000000 -- "large" for 32 bits
+ assert(string.sub(string.format("%8x", -1), -8) == "ffffffff")
+ assert(string.format("%x", max) == "7fffffff")
+ assert(string.sub(string.format("%x", min), -8) == "80000000")
+ assert(string.format("%d", max) == "2147483647")
+ assert(string.format("%d", min) == "-2147483648")
+ assert(string.format("%u", 0xffffffff) == "4294967295")
+ assert(string.format("%o", 0xABCD) == "125715")
+
+ max, min = 0x7fffffffffffffff, -0x8000000000000000
+ assert(string.format("0x%8X", 0x8f000003) == "0x8F000003")
+ assert(string.format("%d", 2^53) == "9007199254740992")
+ assert(string.format("%x", max) == "7fffffffffffffff")
+ assert(string.format("%x", min) == "8000000000000000")
+ assert(string.format("%d", max) == "9223372036854775807")
+ assert(string.format("%d", min) == "-9223372036854775808")
+end
+
+
+assert(table.concat{} == "")
+assert(table.concat({}, 'x') == "")
+assert(table.concat({'\0', '\0\1', '\0\1\2'}, '.\0.') == "\0.\0.\0\1.\0.\0\1\2")
+local a = {}; for i=1,300 do a[i] = "xuxu" end
+assert(table.concat(a, "123").."123" == string.rep("xuxu123", 300))
+assert(table.concat(a, "b", 20, 20) == "xuxu")
+assert(table.concat(a, "", 20, 21) == "xuxuxuxu")
+assert(table.concat(a, "x", 22, 21) == "")
+assert(table.concat(a, "3", 299) == "xuxu3xuxu")
+assert(table.concat({}, "x", 2^31-1, 2^31-2) == "")
+assert(table.concat({}, "x", -2^31+1, -2^31) == "")
+assert(table.concat({}, "x", 2^31-1, -2^31) == "")
+assert(table.concat({[2^31-1] = "alo"}, "x", 2^31-1, 2^31-1) == "alo")
+
+a = {"a","b","c"}
+assert(table.concat(a, ",", 1, 0) == "")
+assert(table.concat(a, ",", 1, 1) == "a")
+assert(table.concat(a, ",", 1, 2) == "a,b")
+assert(table.concat(a, ",", 2) == "b,c")
+assert(table.concat(a, ",", 3) == "c")
+assert(table.concat(a, ",", 4) == "")
+
+
+-- tests for gmatch
+local a = 0
+for i in string.gmatch('abcde', '()') do assert(i == a+1); a=i end
+assert(a==6)
+
+t = {n=0}
+for w in string.gmatch("first second word", "%w+") do
+ t.n=t.n+1; t[t.n] = w
+end
+assert(t[1] == "first" and t[2] == "second" and t[3] == "word")
+
+t = {3, 6, 9}
+for i in string.gmatch ("xuxx uu ppar r", "()(.)%2") do
+ assert(i == table.remove(t, 1))
+end
+assert(#t == 0)
+
+t = {}
+for i,j in string.gmatch("13 14 10 = 11, 15= 16, 22=23", "(%d+)%s*=%s*(%d+)") do
+ t[i] = j
+end
+a = 0
+for k,v in pairs(t) do assert(k+1 == v+0); a=a+1 end
+assert(a == 3)
+
+
+-- tests for gsub
+function f1(s, p)
+ p = string.gsub(p, "%%([0-9])", function (s) return "%" .. (s+1) end)
+ p = string.gsub(p, "^(^?)", "%1()", 1)
+ p = string.gsub(p, "($?)$", "()%1", 1)
+ local t = {string.match(s, p)}
+ return string.sub(s, t[1], t[#t] - 1)
+end
+
+assert(f1('alo alx 123 b\0o b\0o', '(..*) %1') == "b\0o b\0o")
+assert(f1('axz123= 4= 4 34', '(.+)=(.*)=%2 %1') == '3= 4= 4 3')
+assert(f1('=======', '^(=*)=%1$') == '=======')
+
+-- gsub with tables
+assert(string.gsub("alo alo", ".", {}) == "alo alo")
+assert(string.gsub("alo alo", "(.)", {a="AA", l=""}) == "AAo AAo")
+assert(string.gsub("alo alo", "(.).", {a="AA", l="K"}) == "AAo AAo")
+assert(string.gsub("alo alo", "((.)(.?))", {al="AA", o=false}) == "AAo AAo")
+
+assert(string.gsub("alo alo", "().", {2,5,6}) == "256 alo")
+
+t = {}; setmetatable(t, {__index = function (t,s) return string.upper(s) end})
+assert(string.gsub("a alo b hi", "%w%w+", t) == "a ALO b HI")
+
+
+-- tests for match
+assert(string.match('==========', '^([=]*)=%1$') == nil)
+assert(string.match("alo xyzK", "(%w+)K") == "xyz")
+assert(string.match("254 K", "(%d*)K") == "")
+assert(string.match("alo ", "(%w*)$") == "")
+assert(string.match("alo ", "(%w+)$") == nil)
+assert(string.match("ab\0\1\2c", "[\0-\2]+") == "\0\1\2")
+
+return "OK"
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_table.lua b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_table.lua
new file mode 100644
index 000000000000..500117b19d90
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.lib_table.lua
@@ -0,0 +1,252 @@
+--[[
+--*****************************************************************************
+--* Copyright (C) 1994-2016 Lua.org, PUC-Rio.
+--*
+--* Permission is hereby granted, free of charge, to any person obtaining
+--* a copy of this software and associated documentation files (the
+--* "Software"), to deal in the Software without restriction, including
+--* without limitation the rights to use, copy, modify, merge, publish,
+--* distribute, sublicense, and/or sell copies of the Software, and to
+--* permit persons to whom the Software is furnished to do so, subject to
+--* the following conditions:
+--*
+--* The above copyright notice and this permission notice shall be
+--* included in all copies or substantial portions of the Software.
+--*
+--* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+--* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+--* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+--* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+--* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+--* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+--* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--*****************************************************************************
+--]]
+
+-- testing table library
+
+-- workaround missing pcall in zfs lua implementation
+local function tuple(...)
+ return {n=select('#', ...), ...}
+end
+
+function pcall(f, ...)
+ local co = coroutine.create(f)
+ local res = tuple(coroutine.resume(co, ...))
+ if res[1] and coroutine.status(co) == "suspended" then
+ res[1] = false
+ end
+ return table.unpack(res, 1, res.n)
+end
+
+
+-- workaround missing math lib in zfs lua implementation
+local A1, A2 = 727595, 798405 -- 5^17=D20*A1+A2
+local D20, D40 = 1048576, 1099511627776 -- 2^20, 2^40
+local X1, X2 = 0, 1
+function rand()
+ local U = X2*A2
+ local V = (X1*A2 + X2*A1) % D20
+ V = (V*D20 + U) % D40
+ X1 = V/D20
+ X2 = V - X1*D20
+ return V*100/D40
+end
+
+
+-- testing unpack
+
+local unpack = table.unpack
+
+local x,y,z,a,n
+a = {}; lim = 2000
+for i=1, lim do a[i]=i end
+assert(select(lim, unpack(a)) == lim and select('#', unpack(a)) == lim)
+x = unpack(a)
+assert(x == 1)
+x = {unpack(a)}
+assert(#x == lim and x[1] == 1 and x[lim] == lim)
+x = {unpack(a, lim-2)}
+assert(#x == 3 and x[1] == lim-2 and x[3] == lim)
+x = {unpack(a, 10, 6)}
+assert(next(x) == nil) -- no elements
+x = {unpack(a, 11, 10)}
+assert(next(x) == nil) -- no elements
+x,y = unpack(a, 10, 10)
+assert(x == 10 and y == nil)
+x,y,z = unpack(a, 10, 11)
+assert(x == 10 and y == 11 and z == nil)
+a,x = unpack{1}
+assert(a==1 and x==nil)
+a,x = unpack({1,2}, 1, 1)
+assert(a==1 and x==nil)
+
+if not _no32 then
+ assert(not pcall(unpack, {}, 0, 2^31-1))
+ assert(not pcall(unpack, {}, 1, 2^31-1))
+ assert(not pcall(unpack, {}, -(2^31), 2^31-1))
+ assert(not pcall(unpack, {}, -(2^31 - 1), 2^31-1))
+ assert(pcall(unpack, {}, 2^31-1, 0))
+ assert(pcall(unpack, {}, 2^31-1, 1))
+ pcall(unpack, {}, 1, 2^31)
+ a, b = unpack({[2^31-1] = 20}, 2^31-1, 2^31-1)
+ assert(a == 20 and b == nil)
+ a, b = unpack({[2^31-1] = 20}, 2^31-2, 2^31-1)
+ assert(a == nil and b == 20)
+end
+
+-- testing pack
+
+a = table.pack()
+assert(a[1] == nil and a.n == 0)
+
+a = table.pack(table)
+assert(a[1] == table and a.n == 1)
+
+a = table.pack(nil, nil, nil, nil)
+assert(a[1] == nil and a.n == 4)
+
+
+-- testing sort
+
+
+-- test checks for invalid order functions
+local function check (t)
+ local function f(a, b) assert(a and b); return true end
+ local s, e = pcall(table.sort, t, f)
+ assert(not s and e:find("invalid order function"))
+end
+
+check{1,2,3,4}
+check{1,2,3,4,5}
+check{1,2,3,4,5,6}
+
+
+function check (a, f)
+ f = f or function (x,y) return x<y end;
+ for n = #a, 2, -1 do
+ assert(not f(a[n], a[n-1]))
+ end
+end
+
+a = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
+ "Oct", "Nov", "Dec"}
+
+table.sort(a)
+check(a)
+
+function perm (s, n)
+ n = n or #s
+ if n == 1 then
+ local t = {unpack(s)}
+ table.sort(t)
+ check(t)
+ else
+ for i = 1, n do
+ s[i], s[n] = s[n], s[i]
+ perm(s, n - 1)
+ s[i], s[n] = s[n], s[i]
+ end
+ end
+end
+
+perm{}
+perm{1}
+perm{1,2}
+perm{1,2,3}
+perm{1,2,3,4}
+perm{2,2,3,4}
+perm{1,2,3,4,5}
+perm{1,2,3,3,5}
+perm{1,2,3,4,5,6}
+perm{2,2,3,3,5,6}
+
+limit = 5000
+
+a = {}
+for i=1,limit do
+ a[i] = rand()
+end
+
+table.sort(a)
+check(a)
+
+table.sort(a)
+check(a)
+
+a = {}
+for i=1,limit do
+ a[i] = rand()
+end
+
+i=0
+table.sort(a, function(x,y) i=i+1; return y<x end)
+check(a, function(x,y) return y<x end)
+
+
+table.sort{} -- empty array
+
+for i=1,limit do a[i] = false end
+table.sort(a, function(x,y) return nil end)
+check(a, function(x,y) return nil end)
+for i,v in pairs(a) do assert(not v or i=='n' and v==limit) end
+
+A = {"álo", "\0first :-)", "alo", "then this one", "45", "and a new"}
+table.sort(A)
+check(A)
+
+tt = {__lt = function (a,b) return a.val < b.val end}
+a = {}
+for i=1,10 do a[i] = {val=rand(100)}; setmetatable(a[i], tt); end
+table.sort(a)
+check(a, tt.__lt)
+check(a)
+
+
+-- test remove
+local function test (a)
+ table.insert(a, 10); table.insert(a, 2, 20);
+ table.insert(a, 1, -1); table.insert(a, 40);
+ table.insert(a, #a+1, 50)
+ table.insert(a, 2, -2)
+ assert(table.remove(a,1) == -1)
+ assert(table.remove(a,1) == -2)
+ assert(table.remove(a,1) == 10)
+ assert(table.remove(a,1) == 20)
+ assert(table.remove(a,1) == 40)
+ assert(table.remove(a,1) == 50)
+ assert(table.remove(a,1) == nil)
+end
+
+a = {n=0, [-7] = "ban"}
+test(a)
+assert(a.n == 0 and a[-7] == "ban")
+
+a = {[-7] = "ban"};
+test(a)
+assert(a.n == nil and #a == 0 and a[-7] == "ban")
+
+
+table.insert(a, 1, 10); table.insert(a, 1, 20); table.insert(a, 1, -1)
+assert(table.remove(a) == 10)
+assert(table.remove(a) == 20)
+assert(table.remove(a) == -1)
+
+a = {'c', 'd'}
+table.insert(a, 3, 'a')
+table.insert(a, 'b')
+assert(table.remove(a, 1) == 'c')
+assert(table.remove(a, 1) == 'd')
+assert(table.remove(a, 1) == 'a')
+assert(table.remove(a, 1) == 'b')
+assert(#a == 0 and a.n == nil)
+
+a = {10,20,30,40}
+assert(a[#a] == 40)
+assert(table.remove(a, #a) == 40)
+assert(a[#a] == 30)
+assert(table.remove(a, 2) == 20)
+assert(a[#a] == 30 and #a == 2)
+
+
+return "OK"
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.libraries.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.libraries.ksh
new file mode 100755
index 000000000000..71afabdbe2d3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.libraries.ksh
@@ -0,0 +1,31 @@
+#!/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/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+arch=$(uname -m)
+
+if [[ "$arch" == "sparc64" ]]; then
+ log_note "Skipping lib_base and lib_coroutine on sparc64 to avoid stack overflow"
+else
+ log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_base.lua
+ log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_coroutine.lua
+fi
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_strings.lua
+log_must_program -m 40000000 $TESTPOOL $ZCP_ROOT/lua_core/tst.lib_table.lua
+
+log_pass "lua libraries work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.memory_limit.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.memory_limit.ksh
new file mode 100755
index 000000000000..0533b8fa306f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.memory_limit.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+
+#
+# DESCRIPTION:
+# Passing memory limit options to channel programs should work correctly.
+# Programs that exceed these limits should fail gracefully.
+
+
+verify_runnable "global"
+
+log_mustnot_checkerror_program "Memory limit exhausted" \
+ -t 100000000 $TESTPOOL - <<-EOF
+ a = {};
+ i = 0;
+ while true do
+ i = i + 1
+ a[i] = "Here is the " .. i .. "th entry of a"
+ end;
+ return a
+EOF
+
+log_assert "memory limit options work"
+log_mustnot_checkerror_program "Memory limit exhausted" \
+ -m 100000 -t 100000000 $TESTPOOL - <<-EOF
+ a = {};
+ i = 0;
+ while true do
+ i = i + 1
+ a[i] = "Here is the " .. i .. "th entry of a"
+ end;
+ return a
+EOF
+
+log_must_program -m 100000 $TESTPOOL - <<-EOF
+ s = "teststring"
+ s = s .. s .. s .. s
+ return s
+EOF
+
+log_assert "very small memory limits fail correctly"
+log_mustnot_checkerror_program "Memory limit exhausted" -m 1 $TESTPOOL - <<-EOF
+ s = "teststring"
+ s = s .. s .. s .. s
+ return s
+EOF
+
+# Set the memlimit, in case it is a non-default value
+log_must set_tunable32 LUA_MAX_MEMLIMIT 100000000
+
+log_mustnot_checkerror_program "Invalid instruction or memory limit" \
+ -m 200000000 $TESTPOOL - <<-EOF
+ return 1;
+EOF
+
+log_mustnot_checkerror_program "Return value too large" \
+ -m 9223372036854775808 $TESTPOOL - <<-EOF
+ return 1;
+EOF
+
+log_pass "Memory limits work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.ksh
new file mode 100755
index 000000000000..2be9150c34fa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+arch=$(uname -m)
+
+if [[ "$arch" == "sparc64" ]]; then
+ log_unsupported "May cause stack overflow on sparc64 due to recursion"
+else
+ log_mustnot_checkerror_program "too many C levels" \
+ $TESTPOOL $ZCP_ROOT/lua_core/tst.nested_neg.zcp
+
+ log_pass "Too many nested lua statements fail cleanly."
+fi
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.zcp
new file mode 100644
index 000000000000..afe3aa8f4f58
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_neg.zcp
@@ -0,0 +1,770 @@
+--
+-- 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.
+--
+
+-- This program contains deeply nested LUA statements, such that the LUA
+-- parser can not process it, given the limited size of the C stack.
+-- This program contains 243 levels, well beyond the LUAI_MAXCCALLS limit
+
+i = 0
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+return i
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.ksh
new file mode 100755
index 000000000000..0c8b8dd8d0ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.nested_pos.zcp
+
+log_pass "Nested lua statements work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.zcp
new file mode 100644
index 000000000000..02af95d99d18
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nested_pos.zcp
@@ -0,0 +1,71 @@
+--
+-- 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.
+--
+
+-- This program should work with LUAI_MAXCCALLS=20
+
+i = 0
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+if true then
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+i = i + 1
+end
+
+return i
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nvlist_to_lua.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nvlist_to_lua.ksh
new file mode 100755
index 000000000000..eaba6427c96c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.nvlist_to_lua.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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# run C program which tests passing different nvlists to lua
+#
+
+verify_runnable "global"
+
+log_assert "nvlist arguments can be passed to LUA."
+
+log_must nvlist_to_lua $TESTPOOL
+
+log_pass "nvlist arguments can be passed to LUA."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive.zcp
new file mode 100644
index 000000000000..9a13c1e7dc29
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive.zcp
@@ -0,0 +1,31 @@
+--
+-- 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.
+--
+
+-- Test recursion in LUA. Deep recursion should work because it does
+-- not use the C stack. The LUA stack is is allocated from the kernel's
+-- heap, up to the specified memory limit.
+
+arg = ...
+argv = arg["argv"]
+
+function f (x)
+ if (x == 0) then
+ return x
+ end
+ return f(x-1) + 1
+end
+
+r = f(argv[1])
+return r
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_neg.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_neg.ksh
new file mode 100755
index 000000000000..c75048ae7d66
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_neg.ksh
@@ -0,0 +1,24 @@
+#!/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/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+log_mustnot_checkerror_program "Memory limit exhausted" \
+ $TESTPOOL $ZCP_ROOT/lua_core/tst.recursive.zcp 10000000
+
+log_pass "Nearly-infinite recursive LUA calls fail cleanly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_pos.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_pos.ksh
new file mode 100755
index 000000000000..18d5d0f1ee47
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.recursive_pos.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+log_must_program $TESTPOOL $ZCP_ROOT/lua_core/tst.recursive.zcp 10000
+
+log_pass "Deeply recursive LUA calls succeed."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_large.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_large.ksh
new file mode 100755
index 000000000000..ba9c40739471
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_large.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) 2016, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Returning very large (up to the memory limit) lists should
+# function correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+
+function cleanup
+{
+ datasetexists $fs && log_must zfs destroy -R $fs
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+#
+# Actually checking in the ~500kb expected result of this program would be
+# awful, so we just make sure it was as long as we expected.
+#
+output_lines=$(log_must zfs program $TESTPOOL \
+ $ZCP_ROOT/lua_core/tst.return_large.zcp | wc -l)
+
+[[ $output_lines -lt 5000 ]] &&
+ log_fail "Expected return of full list but only got $output_lines lines"
+
+#
+# Make sure we fail if the return is over the memory limit
+#
+log_mustnot_program -m 10000 $TESTPOOL \
+ $ZCP_ROOT/lua_core/tst.return_large.zcp
+
+log_pass "Large return values work properly"
+
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_large.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_large.zcp
new file mode 100644
index 000000000000..0ea9f8930eac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_large.zcp
@@ -0,0 +1,24 @@
+--
+-- 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 Delphix. All rights reserved.
+--
+
+basestring = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" ..
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
+
+ret = {}
+for i=1,5000 do
+ table.insert(ret, basestring)
+end
+
+return ret
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_neg.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_neg.ksh
new file mode 100755
index 000000000000..10afa6727847
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_neg.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try returning various values that lua allows you to construct,
+# but that cannot be represented as nvlists and therefore should
+# cause the script to fail (but not panic). Try sending the values
+# back to userland from both "return" and "error()".
+#
+
+verify_runnable "both"
+
+set -A args 'function() return 1 end' \
+ '{[{}]=true}' \
+ '{[function() return 1 end]=0}' \
+ 'assert' \
+ '0, assert' \
+ 'true, {[{}]=0}' \
+ '{val=true}, {val=false}' \
+ '{1, 2, 3}, {[4]=5}' \
+ 'nil, true, 1, "test", {}, {val=true}' \
+ '{[false]=true, ["false"]=false}' \
+ '{[true]=false, ["true"]=true}' \
+ '{[0]=true, ["0"]=false}' \
+ '{0,0,0,["1"]=0}' \
+ '{0,0,0,["2"]=0}' \
+ '{0,0,0,["3"]=0}'
+
+typeset -i last_index=$((${#args[*]} - 1))
+for i in $(seq 0 $last_index); do
+ log_note "running program: ${args[i]}"
+ log_mustnot_checkerror_program "execution failed" $TESTPOOL - <<-EOF
+ return ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+for i in $(seq 0 $last_index); do
+ log_note "running program: ${args[i]}"
+ log_mustnot_checkerror_program "execution failed" $TESTPOOL - <<-EOF
+ error(${args[i]})
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Returning lua constructs that cannot be converted to " \
+ "nvlists fails as expected."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_pos.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_pos.ksh
new file mode 100755
index 000000000000..8b4ef6e760b0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_nvlist_pos.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try returning various lua values that should be converted
+# to nvlists. Also, try to pass them to error().
+#
+
+verify_runnable "global"
+
+set -A args "" \
+ "nil" \
+ "true" \
+ "1" \
+ "\"test\"" \
+ "{}" \
+ "{val=0}" \
+ "{{1, {2, 3}, {val1={val2=true}}}, {test=\"yes\"}}" \
+ "EINVAL"
+
+log_assert "Returning valid lua constructs works."
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_note "running program: return ${args[i]}"
+ log_must_program $TESTPOOL - <<-EOF
+ return ${args[i]}
+ EOF
+ ((i = i + 1))
+done
+
+typeset -i i=0
+while (( i < ${#args[*]} )); do
+ log_note "running program: error(${args[i]})"
+ log_mustnot_checkerror_program "in function 'error'" $TESTPOOL - <<-EOF
+ error(${args[i]})
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Returning valid lua constructs works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.ksh
new file mode 100755
index 000000000000..18c035e0464b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.ksh
@@ -0,0 +1,31 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Returning a recursive table should fail gracefully
+#
+
+verify_runnable "both"
+
+log_assert "Returning a recursive table should fail gracefully."
+
+log_mustnot_checkerror_program "Maximum table depth" \
+ $TESTPOOL $ZCP_ROOT/lua_core/tst.return_recursive_table.zcp
+
+log_pass "Returning a recursive table should fail gracefully."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.zcp
new file mode 100644
index 000000000000..21e6c60d8e26
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.return_recursive_table.zcp
@@ -0,0 +1,21 @@
+--
+-- 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.
+--
+
+-- This program returns a self-referential data structure.
+
+a = {}
+a["key"] = "val"
+a["self"] = a
+return a
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.err b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.err
new file mode 100644
index 000000000000..45f2d9ef0ea6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.err
@@ -0,0 +1,18 @@
+Channel program execution failed:
+C stack overflow
+stack traceback:
+ [C]: in function 'gsub'
+ [string "channel program"]:17: in function <[string "channel program"]:16>
+ [C]: in function 'gsub'
+ [string "channel program"]:17: in function <[string "channel program"]:16>
+ [C]: in function 'gsub'
+ [string "channel program"]:17: in function <[string "channel program"]:16>
+ [C]: in function 'gsub'
+ [string "channel program"]:17: in function <[string "channel program"]:16>
+ [C]: in function 'gsub'
+ [string "channel program"]:17: in function <[string "channel program"]:16>
+ [C]: in function 'gsub'
+ [string "channel program"]:17: in function <[string "channel program"]:16>
+ [C]: in function 'gsub'
+ [string "channel program"]:17: in function <[string "channel program"]:16>
+ (...tail calls...) \ No newline at end of file
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.ksh
new file mode 100755
index 000000000000..ecabf3a3fec7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.ksh
@@ -0,0 +1,33 @@
+#!/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/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Overflowing the C stack using recursive gsub() should be handled
+# gracefully. gsub() uses more stack space than typical, so it relies
+# on LUAI_MINCSTACK to ensure that we don't overflow the Linux kernel's
+# stack.
+#
+
+verify_runnable "global"
+
+log_assert "recursive gsub() should be handled gracefully"
+
+log_mustnot_program $TESTPOOL $ZCP_ROOT/lua_core/tst.stack_gsub.zcp
+
+log_pass "recursive gsub() should be handled gracefully"
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.zcp
new file mode 100644
index 000000000000..a493363ca68d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.stack_gsub.zcp
@@ -0,0 +1,20 @@
+--
+-- 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.
+--
+
+function f(s)
+ return string.gsub(s, ".", f)
+end
+
+return f("foo")
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.ksh b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.ksh
new file mode 100755
index 000000000000..22ea37548173
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.ksh
@@ -0,0 +1,55 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Passing the instruction limit option to channel programs should work
+# correctly. Programs that exceed these instruction limits should fail
+# gracefully.
+#
+
+verify_runnable "both"
+
+log_assert "Timeouts work correctly."
+
+log_mustnot_checkerror_program "Channel program timed out" \
+ $TESTPOOL $ZCP_ROOT/lua_core/tst.timeout.zcp
+
+function test_instr_limit
+{
+ typeset lim=$1
+
+ error=$(zfs program -t $lim $TESTPOOL $ZCP_ROOT/lua_core/tst.timeout.zcp 2>&1)
+ [[ $? -ne 0 ]] || log_fail "Channel program with limit $lim exited 0: $error"
+
+ instrs_run=$(echo $error | awk -F "chunk" '{print $2}' | awk '{print $1}')
+ if [[ $instrs_run -lt $(( $lim - 100 )) ]]; then
+ log_fail "Runtime (${instrs_run} instr) < limit (${lim} - 100 instr)"
+ elif [[ $instrs_run -gt $(( $lim + 100 )) ]]; then
+ log_fail "Runtime (${instrs_run} instr) > limit (${lim} + 100 instr)"
+ fi
+ log_note "With limit $lim the program ended after $instrs_run instructions"
+}
+
+test_instr_limit 1000
+test_instr_limit 10000
+test_instr_limit 100000
+test_instr_limit 1000000
+test_instr_limit 2000000
+
+log_pass "Timeouts work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.zcp b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.zcp
new file mode 100644
index 000000000000..d74b1a73c2e5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/lua_core/tst.timeout.zcp
@@ -0,0 +1,22 @@
+--
+-- 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.
+--
+
+-- This program runs forever (until timed out).
+
+i = 1;
+while true do
+ i = i + 1
+end;
+return i
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am b/tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am
new file mode 100644
index 000000000000..4d9aa9cebbfc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/Makefile.am
@@ -0,0 +1,53 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/channel_program/synctask_core
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ tst.destroy_fs.ksh \
+ tst.destroy_snap.ksh \
+ tst.get_count_and_limit.ksh \
+ tst.get_index_props.ksh \
+ tst.get_mountpoint.ksh \
+ tst.get_neg.ksh \
+ tst.get_number_props.ksh \
+ tst.get_string_props.ksh \
+ tst.get_type.ksh \
+ tst.get_userquota.ksh \
+ tst.get_written.ksh \
+ tst.inherit.ksh \
+ tst.list_bookmarks.ksh \
+ tst.list_children.ksh \
+ tst.list_clones.ksh \
+ tst.list_holds.ksh \
+ tst.list_snapshots.ksh \
+ tst.list_system_props.ksh \
+ tst.list_user_props.ksh \
+ tst.parse_args_neg.ksh \
+ tst.promote_conflict.ksh \
+ tst.promote_multiple.ksh \
+ tst.promote_simple.ksh \
+ tst.rollback_mult.ksh \
+ tst.rollback_one.ksh \
+ tst.set_props.ksh \
+ tst.snapshot_destroy.ksh \
+ tst.snapshot_neg.ksh \
+ tst.snapshot_recursive.ksh \
+ tst.bookmark.create.ksh \
+ tst.bookmark.copy.ksh \
+ tst.snapshot_simple.ksh \
+ tst.terminate_by_signal.ksh
+
+dist_pkgdata_DATA = \
+ tst.get_index_props.out \
+ tst.get_index_props.zcp \
+ tst.get_number_props.out \
+ tst.get_number_props.zcp \
+ tst.get_string_props.out \
+ tst.get_string_props.zcp \
+ tst.promote_conflict.zcp \
+ tst.set_props.zcp \
+ tst.snapshot_destroy.zcp \
+ tst.snapshot_neg.zcp \
+ tst.snapshot_recursive.zcp \
+ tst.snapshot_simple.zcp \
+ tst.bookmark.create.zcp \
+ tst.bookmark.copy.zcp
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/cleanup.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/cleanup.ksh
new file mode 100755
index 000000000000..3ddcb4d2759c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/cleanup.ksh
@@ -0,0 +1,22 @@
+#!/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/include/libtest.shlib
+
+default_cleanup_noexit
+destroy_pool testpool2
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/setup.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/setup.ksh
new file mode 100755
index 000000000000..5837bf1a14c7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/setup.ksh
@@ -0,0 +1,25 @@
+#!/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/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+TESTPOOLDISK=${DISKS%% *}
+TESTPOOL2DISK=${DISKS##* }
+
+default_setup ${TESTPOOLDISK}
+create_pool testpool2 ${TESTPOOL2DISK}
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh
new file mode 100755
index 000000000000..81f570d9e1e2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.ksh
@@ -0,0 +1,45 @@
+#!/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) 2019, 2020 by Christian Schwarz. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Make sure bookmark copying works in channel programs
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snapname=testsnap
+bookname=testbookmark
+bookcopyname=testbookmark_copy
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_must zfs snapshot $fs@$snapname
+log_must zfs bookmark $fs@$snapname "$fs#$bookname"
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.bookmark.copy.zcp $fs $bookname $bookcopyname
+
+log_pass "Simple bookmark copying works"
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp
new file mode 100644
index 000000000000..9473035f025b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.copy.zcp
@@ -0,0 +1,32 @@
+--
+-- 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, 2020 by Christian Schwarz. All rights reserved.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> <fs> <source_book> <new_book>"
+
+args = ...
+argv = args["argv"]
+fs = argv[1]
+source = fs .. "#" .. argv[2]
+new = fs .. "#" .. argv[3]
+assert(zfs.sync.bookmark(source, new) == 0)
+books = {}
+count = 0
+for s in zfs.list.bookmarks(fs) do
+ count = count + 1
+ books[s] = 1
+end
+assert(count == 2)
+assert(books[source] == 1)
+assert(books[new] == 1)
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.ksh
new file mode 100755
index 000000000000..05ec9cc67602
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.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) 2019, 2020 by Christian Schwarz. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Make sure basic bookmark functionality works in channel programs
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snapname=testsnap
+bookname=testbookmark
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_must zfs snapshot $fs@$snapname
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.bookmark.create.zcp $fs $snapname $bookname
+
+log_pass "Simple bookmark creation works"
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp
new file mode 100644
index 000000000000..eb53fd16ce16
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.bookmark.create.zcp
@@ -0,0 +1,26 @@
+--
+-- 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, 2020 by Christian Schwarz. All rights reserved.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> <fs> <snap> <book>"
+
+args = ...
+argv = args["argv"]
+assert(zfs.sync.bookmark(argv[1] .. "@" .. argv[2], argv[1] .. "#" .. argv[3]) == 0)
+books = {}
+for s in zfs.list.bookmarks(argv[1]) do
+ table.insert(books, s)
+end
+assert(#books == 1)
+assert(books[1] == (argv[1] .. "#" .. argv[3]))
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_fs.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_fs.ksh
new file mode 100755
index 000000000000..45a3fdb66a6f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_fs.ksh
@@ -0,0 +1,45 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+
+function cleanup
+{
+ destroy_dataset $fs
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+log_must zfs unmount $fs
+
+log_must datasetexists $fs
+
+log_must_program_sync $TESTPOOL - $fs <<-EOF
+ arg = ...
+ fs = arg["argv"][1]
+ err = zfs.sync.destroy(fs)
+ msg = "destroying " .. fs .. " err=" .. err
+ return msg
+EOF
+
+log_mustnot datasetexists $fs
+
+log_pass "Destroying filesystem with channel program works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_snap.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_snap.ksh
new file mode 100755
index 000000000000..571d7f87c1b5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.destroy_snap.ksh
@@ -0,0 +1,44 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+snap=$TESTPOOL/$TESTFS@$TESTSNAP
+
+function cleanup
+{
+ destroy_dataset $snap
+}
+
+log_onexit cleanup
+
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+
+log_must snapexists $snap
+
+log_must_program_sync $TESTPOOL - $snap <<-EOF
+ arg = ...
+ snap = arg["argv"][1]
+ err = zfs.sync.destroy(snap)
+ msg = "destroying " .. snap .. " err=" .. err
+ return msg
+EOF
+
+log_mustnot snapexists $snap
+
+log_pass "Destroying snapshot with channel program works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_count_and_limit.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_count_and_limit.ksh
new file mode 100755
index 000000000000..70330c91a0e7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_count_and_limit.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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Getting filesystem and snapshot count/limit props should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/testchild
+snap=$fs@$TESTSNAP
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+ log_must rm -rf $fs/foo
+ log_must rm -rf $fs/bar
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+log_must zfs create $fs/foo
+create_snapshot $fs $TESTSNAP
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "snapshot_limit")
+ assert(ans == -1)
+ assert(src == 'default')
+
+ ans, src = zfs.get_prop("$fs", "snapshot_count")
+ assert(ans == nil)
+ assert(src == nil)
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "filesystem_limit")
+ assert(ans == -1)
+ assert(src == 'default')
+
+ ans, src = zfs.get_prop("$fs", "filesystem_count")
+ assert(ans == nil)
+ assert(src == nil)
+EOF
+
+log_must zfs set snapshot_limit=10 $fs
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "snapshot_limit")
+ assert(ans == 10)
+ assert(src == '$fs')
+
+ ans, src = zfs.get_prop("$fs", "snapshot_count")
+ assert(ans == 1)
+ assert(src == nil)
+EOF
+
+log_must zfs set filesystem_limit=8 $fs
+
+log_must zfs create $fs/bar
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "filesystem_limit")
+ assert(ans == 8)
+ assert(src == '$fs')
+
+ ans, src = zfs.get_prop("$fs", "filesystem_count")
+ assert(ans == 2)
+ assert(src == nil)
+EOF
+
+log_pass "Getting filesystem and snapshot count/limit props should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.ksh
new file mode 100755
index 000000000000..eed3e0bce5fc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.ksh
@@ -0,0 +1,41 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting index props should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snap=$fs@$TESTSNAP
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create -o version=5 $fs
+create_snapshot $fs $TESTSNAP
+
+os=$(uname)
+log_must_program $TESTPOOL $ZCP_ROOT/synctask_core/tst.get_index_props.zcp $fs $snap $os
+
+log_pass "Getting index props should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.out b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.out
new file mode 100644
index 000000000000..40c58b4b3aea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.out
@@ -0,0 +1,4 @@
+Channel program fully executed with return value:
+ return:
+ 1:
+ 2:
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.zcp
new file mode 100644
index 000000000000..10ef8e7f839a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_index_props.zcp
@@ -0,0 +1,77 @@
+--
+-- 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.
+--
+
+arg = ...
+fs = arg["argv"][1]
+snap = arg["argv"][2]
+os = arg["argv"][3]
+
+props = {}
+
+-- prop filesystem snapshot
+props['redundant_metadata'] = {{'all', 'default'}, {nil, nil}}
+props['sync'] = {{'standard', 'default'}, {nil, nil}}
+props['checksum'] = {{'on', 'default'}, {nil, nil}}
+props['dedup'] = {{'off', 'default'}, {nil, nil}}
+props['compression'] = {{'off', 'default'}, {nil, nil}}
+props['snapdir'] = {{'hidden', 'default'}, {nil, nil}}
+if os == "Linux" then
+ props['acltype'] = {{'off', 'default'}, {'off', 'default'}}
+elseif os == "FreeBSD" then
+ props['aclmode'] = {{'discard', 'default'}, {'discard', 'default'}}
+end
+props['aclinherit'] = {{'restricted','default'}, {nil, nil}}
+props['copies'] = {{'1', 'default'}, {nil, nil}}
+props['primarycache'] = {{'all', 'default'}, {'all', 'default'}}
+props['secondarycache'] = {{'all', 'default'}, {'all', 'default'}}
+props['logbias'] = {{'latency', 'default'}, {nil, nil}}
+props['atime'] = {{'on', 'default'}, {nil, nil}}
+props['devices'] = {{'on', 'default'}, {'on', 'default'}}
+props['exec'] = {{'on', 'default'}, {'on', 'default'}}
+props['setuid'] = {{'on', 'default'}, {'on', 'default'}}
+props['readonly'] = {{'off', 'default'}, {nil, nil}}
+if os == "FreeBSD" then
+ props['jailed'] = {{'off', 'default'}, {nil, nil}}
+else
+ props['zoned'] = {{'off', 'default'}, {nil, nil}}
+end
+props['vscan'] = {{'off', 'default'}, {nil, nil}}
+props['nbmand'] = {{'off', 'default'}, {'off', 'default'}}
+props['version'] = {{'5', nil}, {'5', nil}}
+props['canmount'] = {{'on', 'default'}, {nil, nil}}
+props['mounted'] = {{nil, nil}, {nil, nil}}
+props['defer_destroy'] = {{nil, nil}, {'off', nil}}
+props['normalization'] = {{'none', nil}, {'none', nil}}
+props['casesensitivity'] = {{'sensitive', nil}, {'sensitive', nil}}
+props['utf8only'] = {{'off', nil}, {'off', nil}}
+props['dnodesize'] = {{'legacy', 'default'}, {nil, nil}}
+props['relatime'] = {{'off', 'default'}, {nil, nil}}
+props['overlay'] = {{'off', 'default'}, {nil, nil}}
+
+fs_fails = {}
+snap_fails = {}
+for prop, expected in pairs(props) do
+ ans, src = zfs.get_prop(fs, prop)
+ if ((ans ~= expected[1][1]) or (src ~= expected[1][2])) then
+ fs_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(snap, prop)
+ if ((ans ~= expected[2][1]) or (src ~= expected[2][2])) then
+ snap_fails[prop] = {ans, src}
+ end
+end
+
+return {fs_fails, snap_fails}
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_mountpoint.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_mountpoint.ksh
new file mode 100755
index 000000000000..f3cf396aa1f2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_mountpoint.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting dataset mountpoint should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/testmount
+snap=$fs@$TESTSNAP
+clone=$TESTPOOL/$TESTCLONE
+mnt1=/$fs/mnt1
+mnt2=/$fs/mnt2
+
+function cleanup
+{
+ destroy_dataset $clone
+ destroy_dataset $fs "-R"
+ log_must rm -rf $mnt1
+ log_must rm -rf $mnt2
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+create_clone $snap $clone
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "mountpoint")
+ assert(ans == '/$fs')
+ assert(src == 'default')
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$snap", "mountpoint")
+ assert(ans == nil)
+ assert(src == nil)
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$clone", "mountpoint")
+ assert(ans == '/$clone')
+ assert(src == 'default')
+EOF
+
+log_must mkdir $mnt1
+log_must mkdir $mnt2
+
+log_must zfs set mountpoint=$mnt1 $fs
+log_must zfs set mountpoint=$mnt2 $clone
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$fs", "mountpoint")
+ assert(ans == '$mnt1')
+ assert(src == '$fs')
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$snap", "mountpoint")
+ assert(ans == nil)
+ assert(src == nil)
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, src = zfs.get_prop("$clone", "mountpoint")
+ assert(ans == '$mnt2')
+ assert(src == '$clone')
+EOF
+
+log_pass "Getting dataset mountpoint should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_neg.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_neg.ksh
new file mode 100755
index 000000000000..17f7a8fd9749
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting failures should work correctly.
+#
+
+verify_runnable "global"
+fs=$TESTPOOL/$TESTFS/testchild
+function cleanup
+{
+ destroy_dataset $fs
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "notaprop")
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("notadataset", "type")
+EOF
+
+log_pass "Getting failures should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.ksh
new file mode 100755
index 000000000000..942930fa6923
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting number props should work correctly on filesystems,
+# snapshots and volumes.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snap=$fs@$TESTSNAP
+vol=$TESTPOOL/$TESTVOL
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+ destroy_dataset $vol
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+log_must zfs create -V $VOLSIZE $TESTPOOL/$TESTVOL
+
+#
+# Set snapshot_limit and filesystem_limit for the filesystem so that the
+# snapshot_count and filesystem_count properties return a value.
+#
+log_must zfs set snapshot_limit=10 filesystem_limit=10 $fs
+log_must zfs set snapshot_limit=10 $vol
+
+log_must_program $TESTPOOL $ZCP_ROOT/synctask_core/tst.get_number_props.zcp $fs $snap $vol
+
+log_pass "Getting number props should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.out b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.out
new file mode 100644
index 000000000000..be68500097ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.out
@@ -0,0 +1,5 @@
+Channel program fully executed with return value:
+ return:
+ 1:
+ 2:
+ 3:
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.zcp
new file mode 100644
index 000000000000..79969509be89
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_number_props.zcp
@@ -0,0 +1,101 @@
+--
+-- 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.
+--
+
+arg = ...
+fs = arg["argv"][1]
+snap = arg["argv"][2]
+vol = arg["argv"][3]
+
+props = {}
+
+-- The values indicate whether or not a property should be returned,
+-- not the value of the property. A better approach might be to compare
+-- their values to the output of 'zfs get <prop>'
+
+-- prop filesystem snapshot volume
+props['used'] = {{true, nil}, {true, nil}, {true, nil}}
+props['available'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['referenced'] = {{true, nil}, {true, nil}, {true, nil}}
+props['compressratio'] = {{true, nil}, {true, nil}, {true, nil}}
+props['refcompressratio'] = {{true, nil}, {true, nil}, {true, nil}}
+props['volblocksize'] = {{nil, nil}, {nil, nil}, {true, nil}}
+props['usedbysnapshots'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['usedbydataset'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['usedbychildren'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['usedbyrefreservation'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['userrefs'] = {{nil, nil}, {true, nil}, {nil, nil}}
+props['written'] = {{true, nil}, {true, nil}, {true, nil}}
+props['logicalused'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['logicalreferenced'] = {{true, nil}, {true, nil}, {true, nil}}
+props['quota'] = {{true, 'default'}, {nil, nil}, {nil, nil}}
+props['reservation'] = {{true, 'default'}, {nil, nil}, {true, 'default'}}
+-- Note that zfsonlinux allows volsize for snapshot which differs from openzfs
+-- props['volsize'] = {{nil, nil}, {nil, nil}, {true, vol}}
+props['refquota'] = {{true, 'default'}, {nil, nil}, {nil, nil}}
+props['refreservation'] = {{true, 'default'}, {nil, nil}, {true, vol}}
+props['filesystem_limit'] = {{true, fs}, {nil, nil}, {nil, nil}}
+props['snapshot_limit'] = {{true, fs}, {nil, nil}, {true, vol}}
+props['filesystem_count'] = {{true, nil}, {nil, nil}, {nil, nil}}
+props['snapshot_count'] = {{true, nil}, {nil, nil}, {true, nil}}
+props['recordsize'] = {{true, 'default'}, {nil, nil}, {nil, nil}}
+props['creation'] = {{true, nil}, {true, nil}, {true, nil}}
+-- hidden props
+props['createtxg'] = {{true, nil}, {true, nil}, {true, nil}}
+props['numclones'] = {{nil, nil}, {true, nil}, {nil, nil}}
+props['guid'] = {{true, nil}, {true, nil}, {true, nil}}
+props['useraccounting'] = {{true, nil}, {true, nil}, {true, nil}}
+props['unique'] = {{true, nil}, {true, nil}, {true, nil}}
+props['objsetid'] = {{true, nil}, {true, nil}, {true, nil}}
+props['inconsistent'] = {{true, nil}, {true, nil}, {true, nil}}
+
+
+fs_fails = {}
+snap_fails = {}
+vol_fails = {}
+
+function match(n, ans, src, expected)
+ if ((expected[n][1] == nil) and (ans ~= nil)) then
+ return false
+ end
+
+ if ((expected[n][1] == true) and (ans == nil)) then
+ return false
+ end
+
+ if (expected[n][2] ~= src) then
+ return false
+ end
+
+ return true
+end
+
+for prop, expected in pairs(props) do
+ ans, src = zfs.get_prop(fs, prop)
+ if not (match(1, ans, src, expected)) then
+ fs_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(snap, prop)
+ if not (match(2, ans, src, expected)) then
+ snap_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(vol, prop)
+ if not (match(3, ans, src, expected)) then
+ vol_fails[prop] = {ans, src}
+ end
+end
+
+return {fs_fails, snap_fails, vol_fails}
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.ksh
new file mode 100755
index 000000000000..b7d784489ac8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.ksh
@@ -0,0 +1,45 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Getting string props should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/testchild
+snap=$fs@$TESTSNAP
+clone=$TESTPOOL/$TESTCLONE
+
+
+function cleanup
+{
+ datasetexists $clone && log_must zfs destroy $clone
+ datasetexists $fs && log_must zfs destroy -R $fs
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+create_clone $snap $clone
+
+log_must_program $TESTPOOL $ZCP_ROOT/synctask_core/tst.get_string_props.zcp $fs $snap $clone
+
+log_pass "Getting string props should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.out b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.out
new file mode 100644
index 000000000000..be68500097ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.out
@@ -0,0 +1,5 @@
+Channel program fully executed with return value:
+ return:
+ 1:
+ 2:
+ 3:
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.zcp
new file mode 100644
index 000000000000..899bdc0336c0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_string_props.zcp
@@ -0,0 +1,73 @@
+--
+-- 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.
+--
+
+arg = ...
+fs = arg["argv"][1]
+snap = arg["argv"][2]
+clone = arg["argv"][3]
+
+props = {}
+
+-- prop filesystem snapshot clone
+props['origin'] = {{nil, nil}, {nil, nil}, {snap, nil}}
+props['clones'] = {{nil, nil}, {{clone}, nil}, {nil, nil}}
+props['mountpoint'] = {{'/' .. fs, 'default'}, {nil, nil}, {'/' .. clone, 'default'}}
+props['sharenfs'] = {{'off', 'default'}, {nil, nil}, {'off', 'default'}}
+props['type'] = {{'filesystem', nil}, {'snapshot', nil}, {'filesystem', nil}}
+props['sharesmb'] = {{'off', 'default'}, {nil, nil}, {'off', 'default'}}
+props['mlslabel'] = {{'none', 'default'}, {'none', 'default'}, {'none', 'default'}}
+props['receive_resume_token'] = {{nil, nil}, {nil, nil}, {nil, nil}}
+-- hidden props
+props['name'] = {{fs, nil}, {snap, nil}, {clone, nil}}
+props['iscsioptions'] = {{nil, nil}, {nil, nil}, {nil, nil}}
+props['prevsnap'] = {{snap, nil}, {nil, nil}, {snap, nil}}
+
+
+fs_fails = {}
+snap_fails = {}
+clone_fails = {}
+
+
+function list_match(t1, t2)
+ if t1 == t2 then return true end
+ return (t1[1] == t2[1])
+end
+
+function match(n, prop, ans, src, expected)
+ if ((prop == 'clones') or (prop == 'redact_snaps')) then
+ return (list_match(ans, expected[n][1]) and (src == expected[n][2]))
+ else
+ return ((ans == expected[n][1]) and (src == expected[n][2]))
+ end
+end
+
+for prop, expected in pairs(props) do
+ ans, src = zfs.get_prop(fs, prop)
+ if not (match(1, prop, ans, src, expected)) then
+ fs_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(snap, prop)
+ if not (match(2, prop, ans, src, expected)) then
+ snap_fails[prop] = {ans, src}
+ end
+
+ ans, src = zfs.get_prop(clone, prop)
+ if not (match(3, prop, ans, src, expected)) then
+ clone_fails[prop] = {ans, src}
+ end
+end
+
+return {fs_fails, snap_fails, clone_fails}
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_type.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_type.ksh
new file mode 100755
index 000000000000..d040e8962e06
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_type.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Getting type should work correctly.
+#
+
+verify_runnable "global"
+fs=$TESTPOOL/$TESTFS/testchild
+snap=$fs@$TESTSNAP
+vol=$TESTPOOL/$TESTVOL
+function cleanup
+{
+ destroy_dataset $snap
+ destroy_dataset $fs
+ destroy_dataset $vol
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+log_must zfs create -V $VOLSIZE $vol
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "type")
+ assert(ans == "filesystem")
+
+ ans, setpoint = zfs.get_prop("$snap", "type")
+ assert(ans == "snapshot")
+
+ ans, setpoint = zfs.get_prop("$vol", "type")
+ assert(ans == "volume")
+EOF
+
+
+log_pass "Getting type should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_userquota.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_userquota.ksh
new file mode 100755
index 000000000000..80cc4ad418cc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_userquota.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 (c) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# "Getting {user,group}{quota,used}, should work correctly."
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+fs1=$TESTPOOL/$TESTFS/nextchild
+userid='123'
+groupid='456'
+
+function cleanup
+{
+ destroy_dataset $fs
+ destroy_dataset $fs1
+}
+
+log_onexit cleanup
+
+log_must zfs create -o userquota@$userid=$UQUOTA_SIZE \
+ -o groupquota@$groupid=$GQUOTA_SIZE $fs
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "userquota@$userid")
+ assert(ans == $UQUOTA_SIZE)
+ assert(setpoint == "$fs")
+
+ ans, setpoint = zfs.get_prop("$fs", "userused@$userid")
+ assert(ans == 0)
+ assert(setpoint == "$fs")
+
+ ans, setpoint = zfs.get_prop("$fs", "groupquota@$groupid")
+ assert(ans == $GQUOTA_SIZE)
+ assert(setpoint == "$fs")
+
+ ans, setpoint = zfs.get_prop("$fs", "groupused@$groupid")
+ assert(ans == 0)
+ assert(setpoint == "$fs")
+EOF
+
+log_must zfs create $fs1
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs1", "userquota@$userid")
+ assert(ans == nil)
+ assert(setpoint == nil)
+
+ ans, setpoint = zfs.get_prop("$fs1", "userused@$userid")
+ assert(ans == 0)
+ assert(setpoint == "$fs1")
+
+ ans, setpoint = zfs.get_prop("$fs1", "groupquota@$groupid")
+ assert(ans == nil)
+ assert(setpoint == nil)
+
+ ans, setpoint = zfs.get_prop("$fs1", "groupused@$groupid")
+ assert(ans == 0)
+ assert(setpoint == "$fs1")
+EOF
+
+log_pass "Getting {user,group}{quota,used}, should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written.ksh
new file mode 100755
index 000000000000..9755e6f82e58
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.get_written.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Getting written@ props should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/testchild
+snap=$fs@$TESTSNAP
+dir=/$fs/dir
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+ log_must rm -rf $dir
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "written@$TESTSNAP")
+ assert(ans == 0)
+
+EOF
+
+log_must mkdir $dir
+sync
+
+log_must_program $TESTPOOL - <<-EOF
+ ans, setpoint = zfs.get_prop("$fs", "written@$TESTSNAP")
+ assert(ans > 0)
+
+EOF
+
+log_pass "Getting written@ props should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh
new file mode 100755
index 000000000000..e199b4c8b07d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.inherit.ksh
@@ -0,0 +1,39 @@
+#!/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 2020 Joyent, Inc.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS
+testprop="com.joyent:testprop"
+testval="testval"
+
+log_must dataset_setprop $fs $testprop $testval
+log_must_program_sync $TESTPOOL - $fs $testprop <<-EOF
+ arg = ...
+ fs = arg["argv"][1]
+ prop = arg["argv"][2]
+ err = zfs.sync.inherit(fs, prop)
+ msg = "resetting " .. prop .. " on " .. fs .. " err=" .. err
+ return msg
+EOF
+
+
+prop=$(get_prop $testprop $fs)
+[[ "$prop" == "-" ]] || log_fail "Property still set after inheriting"
+
+log_pass "Inherit/clear property with channel program works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_bookmarks.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_bookmarks.ksh
new file mode 100755
index 000000000000..7456177f725b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_bookmarks.ksh
@@ -0,0 +1,120 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs bookmarks should work correctly.
+#
+
+verify_runnable "global"
+
+TESTBOOK=$TESTPOOL/$TESTFS#testbook
+TESTBOOK1=$TESTBOOK-1
+TESTBOOK2=$TESTBOOK-2
+TESTBOOK3=$TESTBOOK-3
+
+function cleanup
+{
+ bkmarkexists $TESTBOOK && log_must zfs destroy $TESTBOOK
+ bkmarkexists $TESTBOOK1 && log_must zfs destroy $TESTBOOK1
+ bkmarkexists $TESTBOOK2 && log_must zfs destroy $TESTBOOK2
+ bkmarkexists $TESTBOOK3 && log_must zfs destroy $TESTBOOK3
+ destroy_snapshot
+}
+
+log_onexit cleanup
+
+create_snapshot
+
+# 0 bookmarks handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.bookmarks("$TESTPOOL/$TESTFS") do
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+# Create a bookmark
+log_must zfs bookmark $TESTPOOL/$TESTFS@$TESTSNAP $TESTBOOK
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.bookmarks("$TESTPOOL/$TESTFS") do
+ assert(s == "$TESTBOOK")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+log_must zfs bookmark $TESTPOOL/$TESTFS@$TESTSNAP $TESTBOOK1
+log_must zfs bookmark $TESTPOOL/$TESTFS@$TESTSNAP $TESTBOOK2
+log_must zfs bookmark $TESTPOOL/$TESTFS@$TESTSNAP $TESTBOOK3
+
+# All bookmarks appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTBOOK"] = false
+ a["$TESTBOOK1"] = false
+ a["$TESTBOOK2"] = false
+ a["$TESTBOOK3"] = false
+ n = 0
+ for s in zfs.list.bookmarks("$TESTPOOL/$TESTFS") do
+ assert(not a[s])
+ a[s] = true
+ n = n + 1
+ end
+ assert(n == 4)
+ assert(a["$TESTBOOK"] and
+ a["$TESTBOOK1"] and
+ a["$TESTBOOK2"] and
+ a["$TESTBOOK3"])
+ return 0
+EOF
+
+# Nonexistent input
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.bookmarks("$TESTPOOL/nonexistent-fs")
+ return 0
+EOF
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.bookmarks("nonexistent-pool/$TESTFS")
+ return 0
+EOF
+
+# Can't look in a different pool than the one specified on command line
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.bookmarks("testpool2")
+ return 0
+EOF
+
+# Can't have bookmarks on snapshots, only on filesystems
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.bookmarks("$TESTPOOL/$TESTFS@$TESTSNAP")
+ return 0
+EOF
+
+# Can't have bookmarks on bookmarks, only on filesystems
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.bookmarks("$TESTBOOK")
+ return 0
+EOF
+
+log_pass "Listing zfs bookmarks should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children.ksh
new file mode 100755
index 000000000000..06b82cab4f34
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_children.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs children should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Listing zfs children should work correctly."
+
+TESTCHILD=$TESTPOOL/$TESTFS/testchild
+TESTCHILD1=$TESTCHILD-1
+TESTCHILD2=$TESTCHILD-2
+TESTCHILD3=$TESTCHILD-3
+
+function cleanup
+{
+ destroy_dataset $TESTCHILD
+ destroy_dataset $TESTCHILD1
+ destroy_dataset $TESTCHILD2
+ destroy_dataset $TESTCHILD3
+}
+
+log_onexit cleanup
+
+# 0 children handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.children("$TESTPOOL/$TESTFS") do
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.children("$TESTPOOL") do
+ assert(s == "$TESTPOOL/$TESTFS")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+# Create a child fs
+log_must zfs create $TESTCHILD
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.children("$TESTPOOL/$TESTFS") do
+ assert(s == "$TESTCHILD")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+log_must zfs create $TESTCHILD1
+log_must zfs create $TESTCHILD2
+log_must zfs create $TESTCHILD3
+
+# All children appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTCHILD"] = false
+ a["$TESTCHILD1"] = false
+ a["$TESTCHILD2"] = false
+ a["$TESTCHILD3"] = false
+ n = 0
+ for s in zfs.list.children("$TESTPOOL/$TESTFS") do
+ assert(not a[s])
+ a[s] = true
+ n = n + 1
+ end
+ assert(n == 4)
+ assert(a["$TESTCHILD"] and
+ a["$TESTCHILD1"] and
+ a["$TESTCHILD2"] and
+ a["$TESTCHILD3"])
+ return 0
+EOF
+
+# Bad input
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.children("$TESTPOOL/not-a-fs")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.children("not-a-pool/$TESTFS")
+ return 0
+EOF
+
+# Can't look in a different pool than the one specified on command line
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.children("rpool")
+ return 0
+EOF
+
+create_snapshot
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.children("$TESTPOOL/$TESTFS@$TESTSNAP")
+ return 0
+EOF
+destroy_snapshot
+
+log_pass "Listing zfs children should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_clones.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_clones.ksh
new file mode 100755
index 000000000000..68d053283d31
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_clones.ksh
@@ -0,0 +1,116 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs clones should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Listing zfs clones should work correctly."
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/$TESTFS@$TESTSNAP "-R"
+}
+
+log_onexit cleanup
+
+# Take snapshot to test with ($TESTSNAP)
+create_snapshot
+
+# 0 clones handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.clones("$TESTPOOL/$TESTFS@$TESTSNAP") do
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+# Create a clone ($TESTCLONE)
+create_clone
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.clones("$TESTPOOL/$TESTFS@$TESTSNAP") do
+ assert(s == "$TESTPOOL/$TESTCLONE")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+TESTCLONE1=${TESTCLONE}-1
+TESTCLONE2=${TESTCLONE}-2
+TESTCLONE3=${TESTCLONE}-3
+create_clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE1
+create_clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE2
+create_clone $TESTPOOL/$TESTFS@$TESTSNAP $TESTPOOL/$TESTCLONE3
+
+# All clones appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTPOOL/$TESTCLONE"] = false
+ a["$TESTPOOL/$TESTCLONE1"] = false
+ a["$TESTPOOL/$TESTCLONE2"] = false
+ a["$TESTPOOL/$TESTCLONE3"] = false
+ n = 0
+ for s in zfs.list.clones("$TESTPOOL/$TESTFS@$TESTSNAP") do
+ assert(not a[s])
+ a[s] = true
+ n = n + 1
+ end
+ assert(n == 4)
+ assert(a["$TESTPOOL/$TESTCLONE"] and
+ a["$TESTPOOL/$TESTCLONE1"] and
+ a["$TESTPOOL/$TESTCLONE2"] and
+ a["$TESTPOOL/$TESTCLONE3"])
+ return 0
+EOF
+
+# Bad input
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("$TESTPOOL/not-a-fs@$TESTSNAP")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("$TESTPOOL/$TESTFS@not-a-snap")
+ return 0
+EOF
+
+# Can't look in a different pool than the one specified on command line
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("rpool")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("not-a-pool/$TESTFS@$TESTSNAP")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.clones("$TESTPOOL/$TESTFS")
+ return 0
+EOF
+
+log_pass "Listing zfs clones should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_holds.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_holds.ksh
new file mode 100755
index 000000000000..2a471bdecbfc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_holds.ksh
@@ -0,0 +1,121 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs holds should work correctly.
+#
+
+verify_runnable "global"
+
+TESTHOLD=testhold-tag
+TESTHOLD1=$TESTHOLD-1
+TESTHOLD2=$TESTHOLD-2
+TESTHOLD3=$TESTHOLD-3
+SNAP=$TESTPOOL/$TESTFS@$TESTSNAP
+
+function cleanup
+{
+ holdexists $TESTHOLD $SNAP && log_must zfs release $TESTHOLD $SNAP
+ holdexists $TESTHOLD1 $SNAP && log_must zfs release $TESTHOLD1 $SNAP
+ holdexists $TESTHOLD2 $SNAP && log_must zfs release $TESTHOLD2 $SNAP
+ holdexists $TESTHOLD3 $SNAP && log_must zfs release $TESTHOLD3 $SNAP
+ destroy_snapshot
+}
+
+log_onexit cleanup
+
+create_snapshot
+
+# 0 holds handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.holds("$SNAP") do
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+# Create a hold
+log_must zfs hold $TESTHOLD $SNAP
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.holds("$SNAP") do
+ assert(s == "$TESTHOLD")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+log_must zfs hold $TESTHOLD1 $SNAP
+log_must zfs hold $TESTHOLD2 $SNAP
+log_must zfs hold $TESTHOLD3 $SNAP
+
+# All holds appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTHOLD"] = false
+ a["$TESTHOLD1"] = false
+ a["$TESTHOLD2"] = false
+ a["$TESTHOLD3"] = false
+ n = 0
+ for s in zfs.list.holds("$SNAP") do
+ assert(not a[s])
+ a[s] = true
+ n = n + 1
+ end
+ assert(n == 4)
+ assert(a["$TESTHOLD"] and
+ a["$TESTHOLD1"] and
+ a["$TESTHOLD2"] and
+ a["$TESTHOLD3"])
+ return 0
+EOF
+
+# Nonexistent input
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.holds("$TESTPOOL/nonexistent-fs@nonexistent-snap")
+ return 0
+EOF
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.holds("nonexistent-pool/$TESTFS")
+ return 0
+EOF
+
+# Can't look in a different pool than the one specified on command line
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.holds("testpool2")
+ return 0
+EOF
+
+# Can't have holds on filesystems
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.holds("$TESTPOOL/$TESTFS")
+ return 0
+EOF
+
+# Can't have holds on bookmarks
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.holds("$TESTPOOL/$TESTFS#bookmark")
+ return 0
+EOF
+
+log_pass "Listing zfs holds should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_snapshots.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_snapshots.ksh
new file mode 100755
index 000000000000..7bc36606c957
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_snapshots.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs snapshots should work correctly.
+#
+
+verify_runnable "global"
+
+log_assert "Listing zfs snapshots should work correctly."
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/$TESTFS@$TESTSNAP
+ destroy_dataset $TESTPOOL/$TESTFS@$TESTSNAP1
+ destroy_dataset $TESTPOOL/$TESTFS@$TESTSNAP2
+ destroy_dataset $TESTPOOL/$TESTFS@$TESTSNAP3
+}
+
+log_onexit cleanup
+
+# 0 snapshots handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.snapshots("$TESTPOOL/$TESTFS") do
+ zfs.debug("ERROR: found snapshot " .. s)
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+# Take a snapshot, make sure it appears
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for s in zfs.list.snapshots("$TESTPOOL/$TESTFS") do
+ assert(s == "$TESTPOOL/$TESTFS@$TESTSNAP")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+TESTSNAP1=${TESTSNAP}-1
+TESTSNAP2=${TESTSNAP}-2
+TESTSNAP3=${TESTSNAP}-3
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP1
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP2
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP3
+
+# All snapshots appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTPOOL/$TESTFS@$TESTSNAP"] = false
+ a["$TESTPOOL/$TESTFS@$TESTSNAP1"] = false
+ a["$TESTPOOL/$TESTFS@$TESTSNAP2"] = false
+ a["$TESTPOOL/$TESTFS@$TESTSNAP3"] = false
+ n = 0
+ for s in zfs.list.snapshots("$TESTPOOL/$TESTFS") do
+ assert(not a[s])
+ a[s] = true
+ n = n + 1
+ end
+ assert(n == 4)
+ assert(a["$TESTPOOL/$TESTFS@$TESTSNAP"] and
+ a["$TESTPOOL/$TESTFS@$TESTSNAP1"] and
+ a["$TESTPOOL/$TESTFS@$TESTSNAP2"] and
+ a["$TESTPOOL/$TESTFS@$TESTSNAP3"])
+ return 0
+EOF
+
+# Bad input
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.snapshots("$TESTPOOL/not-a-fs")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.snapshots("not-a-pool/$TESTFS")
+ return 0
+EOF
+
+# Can't look in a different pool than the one specified on command line
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.snapshots("rpool")
+ return 0
+EOF
+
+log_mustnot_program $TESTPOOL - <<-EOF
+ zfs.list.snapshots("$TESTPOOL/${TESTFS}@$TESTSNAP")
+ return 0
+EOF
+
+log_pass "Listing zfs snapshots should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_system_props.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_system_props.ksh
new file mode 100755
index 000000000000..24ab65a195b9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_system_props.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) 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Listing system properties should succeed
+#
+
+verify_runnable "global"
+fs=$TESTPOOL/$TESTFS/testchild
+snap=$fs@$TESTSNAP
+vol=$TESTPOOL/$TESTVOL
+function cleanup
+{
+ destroy_dataset $snap
+ destroy_dataset $fs
+ destroy_dataset $vol
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+create_snapshot $fs $TESTSNAP
+log_must zfs create -V $VOLSIZE $vol
+
+log_must_program $TESTPOOL - <<-EOF
+ zfs.list.system_properties("$fs")
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ zfs.list.system_properties("$snap")
+EOF
+
+log_must_program $TESTPOOL - <<-EOF
+ zfs.list.system_properties("$vol")
+EOF
+
+log_pass "Listing system properties should succeed."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_user_props.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_user_props.ksh
new file mode 100755
index 000000000000..a454a2753302
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.list_user_props.ksh
@@ -0,0 +1,147 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Listing zfs user properties should work correctly.
+#
+# Note, that this file tests both zfs.list.user_properties
+# and it's alias zfs.list.properties.
+#
+
+verify_runnable "global"
+
+TESTPROP="org.openzfs:test_property"
+TESTPROP1=$TESTPROP-1
+TESTPROP2=$TESTPROP-2
+TESTPROP3=$TESTPROP-3
+TESTPROP4=$TESTPROP-4
+
+TESTVAL="true"
+TESTVAL1="busy"
+TESTVAL2="9223372036854775808"
+TESTVAL3="801f2266-3715-41f4-9080-3d5e913b0f15"
+TESTVAL4="TOZwOfACvQtmDyiq68elB3a3g9YYyxBjSnLtN3ZyQYNOAKykzIE2khKKOBncJiDx"
+
+
+# 0 properties handled correctly
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for p in zfs.list.user_properties("$TESTPOOL/$TESTFS") do
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for p in zfs.list.properties("$TESTPOOL/$TESTFS") do
+ n = n + 1
+ end
+ assert(n == 0)
+ return 0
+EOF
+
+# Add a single user property
+log_must zfs set $TESTPROP="$TESTVAL" $TESTPOOL/$TESTFS
+
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for p,v in zfs.list.user_properties("$TESTPOOL/$TESTFS") do
+ assert(p == "$TESTPROP")
+ assert(v == "$TESTVAL")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+log_must_program $TESTPOOL - <<-EOF
+ n = 0
+ for p,v in zfs.list.properties("$TESTPOOL/$TESTFS") do
+ assert(p == "$TESTPROP")
+ assert(v == "$TESTVAL")
+ n = n + 1
+ end
+ assert(n == 1)
+ return 0
+EOF
+
+log_must zfs set $TESTPROP1="$TESTVAL1" $TESTPOOL/$TESTFS
+log_must zfs set $TESTPROP2="$TESTVAL2" $TESTPOOL/$TESTFS
+log_must zfs set $TESTPROP3="$TESTVAL3" $TESTPOOL/$TESTFS
+log_must zfs set $TESTPROP4="$TESTVAL4" $TESTPOOL/$TESTFS
+
+# All user properties have correct value and appear exactly once
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTPROP"] = false
+ a["$TESTPROP1"] = false
+ a["$TESTPROP2"] = false
+ a["$TESTPROP3"] = false
+ a["$TESTPROP4"] = false
+ m = {}
+ m["$TESTPROP"] = "$TESTVAL"
+ m["$TESTPROP1"] = "$TESTVAL1"
+ m["$TESTPROP2"] = "$TESTVAL2"
+ m["$TESTPROP3"] = "$TESTVAL3"
+ m["$TESTPROP4"] = "$TESTVAL4"
+ n = 0
+ for p,v in zfs.list.user_properties("$TESTPOOL/$TESTFS") do
+ assert(not a[p])
+ a[p] = true
+ assert(v == m[p])
+ n = n + 1
+ end
+ assert(n == 5)
+ assert(a["$TESTPROP"] and
+ a["$TESTPROP1"] and
+ a["$TESTPROP2"] and
+ a["$TESTPROP3"] and
+ a["$TESTPROP4"])
+ return 0
+EOF
+log_must_program $TESTPOOL - <<-EOF
+ a = {}
+ a["$TESTPROP"] = false
+ a["$TESTPROP1"] = false
+ a["$TESTPROP2"] = false
+ a["$TESTPROP3"] = false
+ a["$TESTPROP4"] = false
+ m = {}
+ m["$TESTPROP"] = "$TESTVAL"
+ m["$TESTPROP1"] = "$TESTVAL1"
+ m["$TESTPROP2"] = "$TESTVAL2"
+ m["$TESTPROP3"] = "$TESTVAL3"
+ m["$TESTPROP4"] = "$TESTVAL4"
+ n = 0
+ for p,v in zfs.list.properties("$TESTPOOL/$TESTFS") do
+ assert(not a[p])
+ a[p] = true
+ assert(v == m[p])
+ n = n + 1
+ end
+ assert(n == 5)
+ assert(a["$TESTPROP"] and
+ a["$TESTPROP1"] and
+ a["$TESTPROP2"] and
+ a["$TESTPROP3"] and
+ a["$TESTPROP4"])
+ return 0
+EOF
+
+log_pass "Listing zfs user properties should work correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.parse_args_neg.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.parse_args_neg.ksh
new file mode 100755
index 000000000000..01bdb63eb678
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.parse_args_neg.ksh
@@ -0,0 +1,50 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Try calling zfs.sync.destroy with various arguments that are not
+# valid. The script should fail.
+#
+
+verify_runnable "global"
+
+set -A progs "zfs.sync.destroy(\"foo\", \"bar\")" \
+ "zfs.sync.destroy(\"foo\", 12345)" \
+ "zfs.sync.destroy(12345)" \
+ "zfs.sync.destroy()" \
+ "zfs.sync.destroy{\"foo\", bar=true}" \
+ "zfs.sync.destroy{\"foo\", defer=12345}" \
+ "zfs.sync.destroy{\"foo\", defer=true, 12345}" \
+ "zfs.sync.destroy{\"foo\", defer=true, bar=12345}" \
+ "zfs.sync.destroy{\"foo\", bar=true, defer=true}" \
+ "zfs.sync.destroy{defer=true}" \
+ "zfs.sync.destroy{12345, defer=true}"
+
+
+typeset -i i=0
+while (( i < ${#progs[*]} )); do
+ log_note "running program: ${progs[i]}"
+ # output should contain the usage message, which contains "destroy{"
+ log_mustnot_checkerror_program "destroy{" $TESTPOOL - <<-EOF
+ ${progs[i]}
+ EOF
+ ((i = i + 1))
+done
+
+log_pass "Invalid arguments to zfs.sync.destroy generate errors."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.ksh
new file mode 100755
index 000000000000..b2840377b559
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.ksh
@@ -0,0 +1,55 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Attempting to promote a clone when it shares a snapshot name with
+# its parent filesystem should fail and return the name of the
+# conflicting snapshot.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+clone=$TESTPOOL/$TESTFS/testchild_clone
+snap=promote_conflict_snap
+
+function cleanup
+{
+ for to_destroy in $fs $clone; do
+ destroy_dataset $to_destroy "-R"
+ done
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+log_must zfs snapshot $fs@$snap
+log_must zfs clone $fs@$snap $clone
+log_must zfs snapshot $clone@$snap
+
+#
+# This channel program is expected to return successfully, but fail to execute
+# the promote command since the snapshot names collide. It returns the error
+# code and description, which should be EEXIST (17) and the name of the
+# conflicting snapshot.
+#
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.promote_conflict.zcp $clone
+
+log_pass "Promoting a clone with a conflicting snapshot fails."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.zcp
new file mode 100644
index 000000000000..287328a40d31
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_conflict.zcp
@@ -0,0 +1,23 @@
+--
+-- 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.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> <clone>"
+
+args = ...
+argv = args["argv"]
+err, desc = zfs.sync.promote(argv[1])
+assert(err == EEXIST)
+assert(#desc == 1)
+assert(desc[1] == "promote_conflict_snap")
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_multiple.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_multiple.ksh
new file mode 100755
index 000000000000..7618a34bc8e1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_multiple.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) 2016, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Multiple interacting promotions in a single txg should succeed.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+clone1=$TESTPOOL/$TESTFS/testchild_clone1
+clone2=$TESTPOOL/$TESTFS/testchild_clone2
+snap1=$fs@testchild_snap1
+snap2=$clone1@testchild_snap2
+
+function cleanup
+{
+ for to_destroy in $fs $clone1 $clone2; do
+ destroy_dataset $to_destroy "-R"
+ done
+}
+
+log_onexit cleanup
+
+#
+# Create a chain of clones and snapshots:
+#
+# snap1 -----------> fs
+# \--> snap2 --> clone1
+# \---> clone2
+#
+# Then promote clone2 twice, resulting in:
+#
+# snap1 --> snap2 --> clone2
+# \ \---> clone1
+# \------------> fs
+#
+# We then attempt to destroy clone1, which should succeed since it no
+# longer has any dependents.
+#
+log_must zfs create $fs
+log_must zfs snapshot $snap1
+log_must zfs clone $snap1 $clone1
+log_must zfs snapshot $snap2
+log_must zfs clone $snap2 $clone2
+
+log_must zfs unmount -f $clone1
+
+log_must_program_sync $TESTPOOL - <<-EOF
+ assert(zfs.sync.promote("$clone2") == 0)
+ assert(zfs.sync.promote("$clone2") == 0)
+ assert(zfs.sync.destroy("$clone1") == 0)
+EOF
+
+log_pass "Multiple promotes and destroying a demoted fs in one txg works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple.ksh
new file mode 100755
index 000000000000..541c6840e0c0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.promote_simple.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) 2016, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Promoting a clone should work correctly.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+clone=$TESTPOOL/$TESTFS/testchild_clone
+snap=$fs@$TESTSNAP
+
+function cleanup
+{
+ for to_destroy in $fs $clone; do
+ destroy_dataset $to_destroy "-R"
+ done
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+log_must zfs snapshot $snap
+log_must zfs clone $snap $clone
+
+log_must_program_sync $TESTPOOL - <<-EOF
+ assert(zfs.sync.promote("$clone") == 0)
+EOF
+
+log_pass "Promoting a clone with a channel program works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh
new file mode 100755
index 000000000000..2fbbc73d5fe8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_mult.ksh
@@ -0,0 +1,60 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+snap1=$TESTPOOL/$TESTFS@$TESTSNAP1
+snap2=$TESTPOOL/$TESTFS@$TESTSNAP2
+fs=$TESTPOOL/$TESTFS
+file=$TESTDIR/$TESTFILE0
+
+function cleanup
+{
+ destroy_dataset $snap1 && log_must rm $file
+}
+
+log_onexit cleanup
+
+log_must mkfile 128b $file
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP1
+log_must rm $file
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP2
+
+log_must snapexists $snap1
+log_must snapexists $snap2
+log_must zfs unmount $fs
+
+log_must_program_sync $TESTPOOL - $fs $snap2 <<-EOF
+ arg = ...
+ fs = arg["argv"][1]
+ snap = arg["argv"][2]
+ err = zfs.sync.rollback(fs)
+ if err == 0 then
+ err = zfs.sync.destroy(snap)
+ end
+ if err == 0 then
+ err = zfs.sync.rollback(fs)
+ end
+ msg = "rolling back " .. fs .. " err=" .. err
+ return msg
+EOF
+
+log_must zfs mount $fs
+log_must [ -f $file ]
+log_mustnot snapexists $snap2
+
+log_pass "Rolling back snapshot with channel program works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.ksh
new file mode 100755
index 000000000000..12834430163c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.rollback_one.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) 2016, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+verify_runnable "global"
+snap=$TESTPOOL/$TESTFS@$TESTSNAP
+fs=$TESTPOOL/$TESTFS
+file=$TESTDIR/$TESTFILE0
+
+function cleanup
+{
+ destroy_dataset $snap && log_must rm $file
+}
+
+log_onexit cleanup
+
+log_must mkfile 128b $file
+create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+log_must rm $file
+
+log_must snapexists $snap
+log_must zfs unmount $fs
+
+log_must_program_sync $TESTPOOL - $fs <<-EOF
+ arg = ...
+ fs = arg["argv"][1]
+ err = zfs.sync.rollback(fs)
+ msg = "rolling back " .. fs .. " err=" .. err
+ return msg
+EOF
+
+log_must zfs mount $fs
+log_must [ -f $file ]
+
+log_pass "Rolling back snapshot with channel program works."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.set_props.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.set_props.ksh
new file mode 100755
index 000000000000..6ac1c2b205cd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.set_props.ksh
@@ -0,0 +1,39 @@
+#!/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/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION:
+# Setting user props should work correctly on datasets.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_must_program_sync $TESTPOOL $ZCP_ROOT/synctask_core/tst.set_props.zcp $fs
+
+log_pass "Setting props from channel program works correctly."
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.set_props.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.set_props.zcp
new file mode 100644
index 000000000000..756263a9d082
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.set_props.zcp
@@ -0,0 +1,109 @@
+--
+-- 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 2020 Joyent, Inc.
+--
+
+arg = ...
+fs = arg["argv"][1]
+
+-- values from zfs.h
+maxname = 256 -- ZAP_MAXNAMELEN
+maxvalue = 8192 -- ZAP_MAXVALUELEN
+
+pos_props = {}
+neg_props = {}
+
+-- In lua, strings are immutable, so to avoid a bunch of copies, we
+-- build the value in a table and use concat (which appears to be the
+-- recommend method for such things).
+largeprop = {}
+for i = 0,maxvalue,8
+do
+ table.insert(largeprop, "aaaaaaaa")
+end
+-- add an extra character so we spill over the limit
+table.insert(largeprop, "b")
+
+largepropv = table.concat(largeprop)
+
+largepropname = { "b:" }
+for i = 0,maxname,8
+do
+ table.insert(largepropname, "aaaaaaaa")
+end
+largepropnamev = table.concat(largepropname)
+
+pos_props["a:prop"] = {"hello"}
+
+-- For neg_props, an optional expected error value can be added after the
+-- property value as seen below.
+neg_props["notaproperty"] = {"hello", EINVAL}
+neg_props["a:very.long.property.value"] = { largepropv, E2BIG }
+neg_props[largepropnamev] = {"greetings", ENAMETOOLONG }
+
+-- non-user properties aren't currently supported
+-- Even if they were, the argument must be a string due to requirements of
+-- the ZCP api.
+neg_props["mountpoint"] = {"/foo/bar"}
+neg_props["copies"] = { "2" }
+
+-- read-only properties should never succeed
+neg_props["guid"] = { "12345" }
+
+set_fail = {}
+val_fail = {}
+
+-- Test properties that should work
+for prop, values in pairs(pos_props) do
+ for i, val in ipairs(values) do
+ old_val, src = zfs.get_prop(fs, prop)
+
+ -- Attempt to set the property to the specified value
+ err = zfs.sync.set_prop(fs, prop, val)
+
+ if (err ~= 0) then
+ set_fail[prop] = err -- tuple of prop, val that resulted in error
+ else
+ -- use get_prop to check that the set took affect
+ new_val, src = zfs.get_prop(fs, prop)
+ if (tostring(new_val) ~= tostring(val)) then
+ val_fail[prop] = new_val
+ end
+
+ -- We modified the prop, restore old value (if one existed)
+ if (old_val ~= nil) then
+ err = zfs.sync.set_prop(fs, prop, old_val)
+ if (err ~= 0) then return err end
+ else
+ -- Didn't have an old value, delete (inherit) instead
+ err = zfs.sync.inherit(fs, prop)
+ if (err ~= 0) then return err end
+ end
+ end
+ end
+end
+
+-- Test properties that should fail
+for prop, expected in pairs(neg_props) do
+ exp_val = expected[1]
+ exp_err = expected[2]
+
+ -- Attempt to set the property to the specified value
+ err = zfs.sync.set_prop(fs, prop, exp_val)
+ if (err == 0 or (exp_err ~= nil and err ~= exp_err)) then
+ set_fail[prop] = err -- tuple of prop, val that resulted in error
+ end
+end
+
+return {set_fail, val_fail}
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_destroy.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_destroy.ksh
new file mode 100755
index 000000000000..b0cdfb84f4ea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_destroy.ksh
@@ -0,0 +1,39 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Creating and destroying snapshots in the same txg should work.
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.snapshot_destroy.zcp $fs
+
+log_pass "Creating/destroying snapshots in one channel program works"
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_destroy.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_destroy.zcp
new file mode 100644
index 000000000000..6fbfb06ad433
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_destroy.zcp
@@ -0,0 +1,24 @@
+--
+-- 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 Delphix. All rights reserved.
+--
+
+args = ...
+argv = args["argv"]
+
+assert(zfs.sync.snapshot(argv[1] .. "@snap1") == 0)
+assert(zfs.sync.destroy(argv[1] .. "@snap1") == 0)
+
+for s in zfs.list.snapshots(argv[1]) do
+ assert(false)
+end
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_neg.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_neg.ksh
new file mode 100755
index 000000000000..8d6cd38310e6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_neg.ksh
@@ -0,0 +1,45 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Check various invalid snapshot error cases
+#
+
+verify_runnable "global"
+
+fs1=$TESTPOOL/$TESTFS/testchild1
+fs2=$TESTPOOL/$TESTFS/testchild2
+
+function cleanup
+{
+ for fs in $fs1 $fs2; do
+ destroy_dataset $fs "-R"
+ done
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs1
+log_must zfs create $fs2
+log_must zfs snapshot $fs1@snap1
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.snapshot_neg.zcp $fs1 $fs2
+
+log_pass "zfs.sync.snapshot returns correct errors on invalid input"
+
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_neg.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_neg.zcp
new file mode 100644
index 000000000000..5cae324bc90e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_neg.zcp
@@ -0,0 +1,35 @@
+--
+-- 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 Delphix. All rights reserved.
+--
+
+args = ...
+argv = args["argv"]
+fs1 = argv[1]
+fs2 = argv[2]
+
+longstring = "a"
+for i=1,9 do
+ longstring = longstring .. longstring
+end
+
+-- invalid snapshot names
+assert(zfs.sync.snapshot("ceci_nest_pas_une_dataset") == EINVAL);
+assert(zfs.sync.snapshot(fs1) == EINVAL)
+assert(zfs.sync.snapshot(fs1 .. "@" .. longstring) == ENAMETOOLONG)
+
+assert(zfs.sync.snapshot(fs2 .. "@snap1") == 0)
+-- only one snapshot of a filesystem is allowed per TXG.
+assert(zfs.sync.snapshot(fs2 .. "@snap2") == EAGAIN)
+-- snapshot already exists
+assert(zfs.sync.snapshot(fs1 .. "@snap1") == EEXIST)
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_recursive.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_recursive.ksh
new file mode 100755
index 000000000000..e3bf10b69168
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_recursive.ksh
@@ -0,0 +1,61 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Construct a set of nested filesystems, then recursively snapshot
+# all of them.
+#
+
+verify_runnable "global"
+
+rootfs=$TESTPOOL/$TESTFS/root
+snapname=snap
+
+function cleanup
+{
+ destroy_dataset $rootfs "-R"
+}
+
+log_onexit cleanup
+
+filesystems="$rootfs \
+$rootfs/child1 \
+$rootfs/child1/subchild1 \
+$rootfs/child1/subchild2 \
+$rootfs/child1/subchild3 \
+$rootfs/child2 \
+$rootfs/child2/subchild4 \
+$rootfs/child2/subchild5"
+
+for fs in $filesystems; do
+ log_must zfs create $fs
+done
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.snapshot_recursive.zcp $rootfs $snapname
+
+#
+# Make sure all of the snapshots we expect were created.
+#
+for fs in $filesystems; do
+ log_must snapexists $fs@$snapname
+done
+
+log_pass "Recursively snapshotting multiple filesystems works."
+
+
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_recursive.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_recursive.zcp
new file mode 100644
index 000000000000..097940d71198
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_recursive.zcp
@@ -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 (c) 2016, 2017 by Delphix. All rights reserved.
+--
+
+args = ...
+argv = args["argv"]
+fs = argv[1]
+snap = argv[2]
+
+function snapshot_recursive(root)
+ assert(zfs.sync.snapshot(root .. "@" .. snap) == 0)
+ for child in zfs.list.children(root) do
+ snapshot_recursive(child)
+ end
+end
+
+snapshot_recursive(fs)
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_simple.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_simple.ksh
new file mode 100755
index 000000000000..4a7acaddaf8f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_simple.ksh
@@ -0,0 +1,40 @@
+#!/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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Make sure basic snapshot functionality works in channel programs
+#
+
+verify_runnable "global"
+
+fs=$TESTPOOL/$TESTFS/testchild
+snapname=testsnap
+
+function cleanup
+{
+ destroy_dataset $fs "-R"
+}
+
+log_onexit cleanup
+
+log_must zfs create $fs
+
+log_must_program_sync $TESTPOOL \
+ $ZCP_ROOT/synctask_core/tst.snapshot_simple.zcp $fs $snapname
+
+log_pass "Simple snapshotting works"
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_simple.zcp b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_simple.zcp
new file mode 100644
index 000000000000..215e013df1d2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.snapshot_simple.zcp
@@ -0,0 +1,26 @@
+--
+-- 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 Delphix. All rights reserved.
+--
+
+-- This program should be invoked as "zfs program <pool> <prog> <fs> <snap>"
+
+args = ...
+argv = args["argv"]
+assert(zfs.sync.snapshot(argv[1] .. "@" .. argv[2]) == 0)
+snaps = {}
+for s in zfs.list.snapshots(argv[1]) do
+ table.insert(snaps, s)
+end
+assert(#snaps == 1)
+assert(snaps[1] == (argv[1] .. "@" .. argv[2]))
diff --git a/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.terminate_by_signal.ksh b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.terminate_by_signal.ksh
new file mode 100755
index 000000000000..0a5fb804ac39
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/channel_program/synctask_core/tst.terminate_by_signal.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) 2017 by Delphix. All rights reserved.
+#
+. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
+
+#
+# DESCRIPTION: Execute a long-running zfs channel program and attempt to
+# cancel it by sending a signal.
+#
+
+verify_runnable "global"
+
+rootfs=$TESTPOOL/$TESTFS
+snapname=snap
+limit=50000000
+
+function cleanup
+{
+ datasetexists $rootfs && log_must zfs destroy -R $rootfs
+}
+
+log_onexit cleanup
+
+#
+# Create a working set of 100 file systems
+#
+for i in {1..100}; do
+ log_must zfs create "$rootfs/child$i"
+done
+
+#
+# Attempt to create 100 snapshots with zfs.sync.snapshot() along with some
+# time consuming efforts. We use loops of zfs.check.* (dry run operations)
+# to consume instructions before the next zfs.sync.snapshot() occurs.
+#
+# Without a signal interruption this ZCP would take several minutes and
+# generate over 30 million Lua instructions.
+#
+function chan_prog
+{
+zfs program -t $limit $TESTPOOL - $rootfs $snapname <<-EOF
+ arg = ...
+ fs = arg["argv"][1]
+ snap = arg["argv"][2]
+ for child in zfs.list.children(fs) do
+ local snapname = child .. "@" .. snap
+ zfs.check.snapshot(snapname)
+ zfs.sync.snapshot(snapname)
+ for i=1,20000,1 do
+ zfs.check.snapshot(snapname)
+ zfs.check.destroy(snapname)
+ zfs.check.destroy(fs)
+ end
+ end
+ return "should not have reached here"
+EOF
+}
+
+log_note "Executing a long-running zfs program in the background"
+chan_prog &
+CHILD=$!
+
+#
+# After waiting, send a kill signal to the channel program process.
+# This should stop the ZCP near a million instructions but still have
+# created some of the snapshots. Note that since the above zfs program
+# command might get wrapped, we also issue a kill to the group.
+#
+sleep 10
+log_pos pkill -P $CHILD
+log_pos kill $CHILD
+
+#
+# Make sure the channel program did not fully complete by enforcing
+# that not all of the snapshots were created.
+#
+snap_count=$(zfs list -t snapshot | grep $TESTPOOL | wc -l)
+log_note "$snap_count snapshots created by ZCP"
+
+if [ "$snap_count" -eq 0 ]; then
+ log_fail "Channel program failed to run."
+elif [ "$snap_count" -gt 90 ]; then
+ log_fail "Too many snapshots after a cancel ($snap_count)."
+else
+ log_pass "Canceling a long-running channel program works."
+fi
diff --git a/tests/zfs-tests/tests/functional/chattr/Makefile.am b/tests/zfs-tests/tests/functional/chattr/Makefile.am
new file mode 100644
index 000000000000..431208e587ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/chattr/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/chattr
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ chattr_001_pos.ksh \
+ chattr_002_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/chattr/chattr_001_pos.ksh b/tests/zfs-tests/tests/functional/chattr/chattr_001_pos.ksh
new file mode 100755
index 000000000000..cb8c2ead593a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/chattr/chattr_001_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check whether chattr works as expected
+#
+#
+# STRATEGY:
+# 1. Create 3 files
+# 2. Use chattr to make them writable, immutable and appendonly
+# 3. Try to write and append to each file
+#
+
+set -A files writable immutable append
+
+function cleanup
+{
+ for i in ${files[*]}; do
+ if is_freebsd ; then
+ log_must chflags noschg $TESTDIR/$i
+ log_must rm -f $TESTDIR/$i
+ else
+ log_must chattr -ia $TESTDIR/$i
+ log_must rm -f $TESTDIR/$i
+ fi
+ done
+}
+
+log_onexit cleanup
+
+if is_freebsd ; then
+ log_assert "Check whether chflags works as expected"
+else
+ log_assert "Check whether chattr works as expected"
+fi
+
+log_must touch $TESTDIR/writable
+log_must touch $TESTDIR/immutable
+log_must touch $TESTDIR/append
+
+if is_freebsd ; then
+ log_must chflags noschg $TESTDIR/writable
+ log_must chflags schg $TESTDIR/immutable
+ log_must chflags sappnd $TESTDIR/append
+else
+ log_must chattr -i $TESTDIR/writable
+ log_must chattr +i $TESTDIR/immutable
+ log_must chattr +a $TESTDIR/append
+fi
+
+log_must eval "echo test > $TESTDIR/writable"
+log_must eval "echo test >> $TESTDIR/writable"
+log_mustnot eval "echo test > $TESTDIR/immutable"
+log_mustnot eval "echo test >> $TESTDIR/immutable"
+log_mustnot eval "echo test > $TESTDIR/append"
+log_must eval "echo test >> $TESTDIR/append"
+
+if is_freebsd ; then
+ log_pass "chflags works as expected"
+else
+ log_pass "chattr works as expected"
+fi
diff --git a/tests/zfs-tests/tests/functional/chattr/chattr_002_neg.ksh b/tests/zfs-tests/tests/functional/chattr/chattr_002_neg.ksh
new file mode 100755
index 000000000000..cad1b0a38a4d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/chattr/chattr_002_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check whether unprivileged user can chattr
+#
+#
+# STRATEGY:
+# 1. Create 3 files
+# 2. Use chattr to make them writable, immutable and appendonly
+# 3. Try to chattr with unprivileged user
+#
+
+set -A files writable immutable append
+
+function cleanup
+{
+ for i in ${files[*]}; do
+ log_must chattr -ia $TESTDIR/$i
+ log_must rm -f $TESTDIR/$i
+ done
+ log_must chmod 0755 $TESTDIR
+}
+
+log_onexit cleanup
+
+log_assert "Check whether unprivileged user can chattr"
+
+log_must chmod 0777 $TESTDIR
+
+log_must user_run $QUSER1 touch $TESTDIR/writable
+log_must user_run $QUSER1 touch $TESTDIR/immutable
+log_must user_run $QUSER1 touch $TESTDIR/append
+
+log_must chattr -i $TESTDIR/writable
+log_must chattr +i $TESTDIR/immutable
+log_must chattr +a $TESTDIR/append
+
+log_must user_run $QUSER1 chattr -i $TESTDIR/writable
+log_must user_run $QUSER1 chattr -a $TESTDIR/writable
+log_must user_run $QUSER1 chattr +i $TESTDIR/immutable
+log_must user_run $QUSER1 chattr +a $TESTDIR/append
+
+log_mustnot user_run $QUSER1 chattr +i $TESTDIR/writable
+log_mustnot user_run $QUSER1 chattr +a $TESTDIR/writable
+log_mustnot user_run $QUSER1 chattr -i $TESTDIR/immutable
+log_mustnot user_run $QUSER1 chattr -a $TESTDIR/append
+
+log_pass "Unprivileged user cannot chattr as expected"
diff --git a/tests/zfs-tests/tests/functional/chattr/cleanup.ksh b/tests/zfs-tests/tests/functional/chattr/cleanup.ksh
new file mode 100755
index 000000000000..59875d609ad9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/chattr/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+log_must clean_user_group
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/chattr/setup.ksh b/tests/zfs-tests/tests/functional/chattr/setup.ksh
new file mode 100755
index 000000000000..d4b3cdcaba92
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/chattr/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+verify_runnable "both"
+
+log_must clean_user_group
+
+log_must add_group $QGROUP
+log_must add_user $QGROUP $QUSER1
+log_must add_user $QGROUP $QUSER2
+
+#
+# Verify the test user can execute the zfs utilities. This may not
+# be possible due to default permissions on the user home directory.
+# This can be resolved granting group read access.
+#
+# chmod 0750 $HOME
+#
+user_run $QUSER1 zfs list
+if [ $? -ne 0 ]; then
+ log_unsupported "Test user $QUSER1 cannot execute zfs utilities"
+fi
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/checksum/.gitignore b/tests/zfs-tests/tests/functional/checksum/.gitignore
new file mode 100644
index 000000000000..0411d5aa47dc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/.gitignore
@@ -0,0 +1,4 @@
+skein_test
+edonr_test
+sha2_test
+
diff --git a/tests/zfs-tests/tests/functional/checksum/Makefile.am b/tests/zfs-tests/tests/functional/checksum/Makefile.am
new file mode 100644
index 000000000000..3ad48ccd4d96
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/Makefile.am
@@ -0,0 +1,32 @@
+include $(top_srcdir)/config/Rules.am
+
+LDADD = \
+ $(abs_top_builddir)/lib/libicp/libicp.la \
+ $(abs_top_builddir)/lib/libspl/libspl_assert.la
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/checksum
+
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ run_edonr_test.ksh \
+ run_sha2_test.ksh \
+ run_skein_test.ksh \
+ filetest_001_pos.ksh
+
+dist_pkgdata_DATA = \
+ default.cfg
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/checksum
+
+pkgexec_PROGRAMS = \
+ skein_test \
+ sha2_test
+
+skein_test_SOURCES = skein_test.c
+sha2_test_SOURCES = sha2_test.c
+
+if BUILD_LINUX
+pkgexec_PROGRAMS += edonr_test
+edonr_test_SOURCES = edonr_test.c
+endif
diff --git a/tests/zfs-tests/tests/functional/checksum/cleanup.ksh b/tests/zfs-tests/tests/functional/checksum/cleanup.ksh
new file mode 100755
index 000000000000..19b0f35cf768
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/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.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/scrub_mirror/default.cfg
+
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/checksum/default.cfg b/tests/zfs-tests/tests/functional/checksum/default.cfg
new file mode 100644
index 000000000000..bc2f6e261b73
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/default.cfg
@@ -0,0 +1,36 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+set -A CHECKSUM_TYPES "fletcher2" "fletcher4" "sha256" "sha512" "skein"
+if ! is_freebsd; then
+ CHECKSUM_TYPES+=("edonr")
+fi
diff --git a/tests/zfs-tests/tests/functional/checksum/edonr_test.c b/tests/zfs-tests/tests/functional/checksum/edonr_test.c
new file mode 100644
index 000000000000..a88756091e3d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/edonr_test.c
@@ -0,0 +1,218 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
+ */
+
+/*
+ * This is just to keep the compiler happy about sys/time.h not declaring
+ * gettimeofday due to -D_KERNEL (we can do this since we're actually
+ * running in userspace, but we need -D_KERNEL for the remaining Edon-R code).
+ */
+#ifdef _KERNEL
+#undef _KERNEL
+#endif
+
+#include <sys/edonr.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/note.h>
+#include <sys/time.h>
+#include <sys/stdtypes.h>
+
+/*
+ * Test messages from:
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
+ */
+const char *test_msg0 = "abc";
+const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn"
+ "lmnomnopnopq";
+const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi"
+ "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+
+/*
+ * Test digests computed by hand. There's no formal standard or spec for edonr.
+ */
+const uint8_t edonr_224_test_digests[][28] = {
+ {
+ /* for test_msg0 */
+ 0x56, 0x63, 0xc4, 0x93, 0x95, 0x20, 0xfa, 0xf6,
+ 0x12, 0x31, 0x65, 0xa4, 0x66, 0xf2, 0x56, 0x01,
+ 0x95, 0x2e, 0xa9, 0xe4, 0x24, 0xdd, 0xc9, 0x6b,
+ 0xef, 0xd0, 0x40, 0x94
+ },
+ {
+ /* for test_msg1 */
+ 0xd0, 0x13, 0xe4, 0x87, 0x4d, 0x06, 0x8d, 0xca,
+ 0x4e, 0x14, 0xb9, 0x37, 0x2f, 0xce, 0x12, 0x20,
+ 0x60, 0xf8, 0x5c, 0x0a, 0xfd, 0x7a, 0x7d, 0x97,
+ 0x88, 0x2b, 0x05, 0x75
+ }
+ /* no test vector for test_msg2 */
+};
+
+const uint8_t edonr_256_test_digests[][32] = {
+ {
+ /* for test_msg0 */
+ 0x54, 0xd7, 0x8b, 0x13, 0xc7, 0x4e, 0xda, 0x5a,
+ 0xed, 0xc2, 0x71, 0xcc, 0x88, 0x1f, 0xb2, 0x2f,
+ 0x83, 0x99, 0xaf, 0xd3, 0x04, 0x0b, 0x6a, 0x39,
+ 0x2d, 0x73, 0x94, 0x05, 0x50, 0x8d, 0xd8, 0x51
+ },
+ {
+ /* for test_msg1 */
+ 0x49, 0x2d, 0x0b, 0x19, 0xab, 0x1e, 0xde, 0x3a,
+ 0xea, 0x9b, 0xf2, 0x39, 0x3a, 0xb1, 0x21, 0xde,
+ 0x21, 0xf6, 0x80, 0x1f, 0xad, 0xbe, 0x8b, 0x07,
+ 0xc7, 0xfb, 0xe6, 0x99, 0x0e, 0x4d, 0x73, 0x63
+ }
+ /* no test vectorfor test_msg2 */
+};
+
+const uint8_t edonr_384_test_digests[][48] = {
+ {
+ /* for test_msg0 */
+ 0x0e, 0x7c, 0xd7, 0x85, 0x78, 0x77, 0xe0, 0x89,
+ 0x5b, 0x1c, 0xdf, 0x49, 0xf4, 0x1d, 0x20, 0x9c,
+ 0x72, 0x7d, 0x2e, 0x57, 0x9b, 0x9b, 0x9a, 0xdc,
+ 0x60, 0x27, 0x97, 0x82, 0xb9, 0x90, 0x72, 0xec,
+ 0x7e, 0xce, 0xd3, 0x16, 0x5f, 0x47, 0x75, 0x48,
+ 0xfa, 0x60, 0x72, 0x7e, 0x01, 0xc7, 0x7c, 0xc6
+ },
+ {
+ /* no test vector for test_msg1 */
+ 0
+ },
+ {
+ /* for test_msg2 */
+ 0xe2, 0x34, 0xa1, 0x02, 0x83, 0x76, 0xae, 0xe6,
+ 0x82, 0xd9, 0x38, 0x32, 0x0e, 0x00, 0x78, 0xd2,
+ 0x34, 0xdb, 0xb9, 0xbd, 0xf0, 0x08, 0xa8, 0x0f,
+ 0x63, 0x1c, 0x3d, 0x4a, 0xfd, 0x0a, 0xe9, 0x59,
+ 0xdc, 0xd4, 0xce, 0xcd, 0x8d, 0x67, 0x6c, 0xea,
+ 0xbb, 0x1a, 0x32, 0xed, 0x5c, 0x6b, 0xf1, 0x7f
+ }
+};
+
+const uint8_t edonr_512_test_digests[][64] = {
+ {
+ /* for test_msg0 */
+ 0x1b, 0x14, 0xdb, 0x15, 0x5f, 0x1d, 0x40, 0x65,
+ 0x94, 0xb8, 0xce, 0xf7, 0x0a, 0x43, 0x62, 0xec,
+ 0x6b, 0x5d, 0xe6, 0xa5, 0xda, 0xf5, 0x0e, 0xc9,
+ 0x99, 0xe9, 0x87, 0xc1, 0x9d, 0x30, 0x49, 0xe2,
+ 0xde, 0x59, 0x77, 0xbb, 0x05, 0xb1, 0xbb, 0x22,
+ 0x00, 0x50, 0xa1, 0xea, 0x5b, 0x46, 0xa9, 0xf1,
+ 0x74, 0x0a, 0xca, 0xfb, 0xf6, 0xb4, 0x50, 0x32,
+ 0xad, 0xc9, 0x0c, 0x62, 0x83, 0x72, 0xc2, 0x2b
+ },
+ {
+ /* no test vector for test_msg1 */
+ 0
+ },
+ {
+ /* for test_msg2 */
+ 0x53, 0x51, 0x07, 0x0d, 0xc5, 0x1c, 0x3b, 0x2b,
+ 0xac, 0xa5, 0xa6, 0x0d, 0x02, 0x52, 0xcc, 0xb4,
+ 0xe4, 0x92, 0x1a, 0x96, 0xfe, 0x5a, 0x69, 0xe7,
+ 0x6d, 0xad, 0x48, 0xfd, 0x21, 0xa0, 0x84, 0x5a,
+ 0xd5, 0x7f, 0x88, 0x0b, 0x3e, 0x4a, 0x90, 0x7b,
+ 0xc5, 0x03, 0x15, 0x18, 0x42, 0xbb, 0x94, 0x9e,
+ 0x1c, 0xba, 0x74, 0x39, 0xa6, 0x40, 0x9a, 0x34,
+ 0xb8, 0x43, 0x6c, 0xb4, 0x69, 0x21, 0x58, 0x3c
+ }
+};
+
+int
+main(int argc, char *argv[])
+{
+ boolean_t failed = B_FALSE;
+ uint64_t cpu_mhz = 0;
+
+ if (argc == 2)
+ cpu_mhz = atoi(argv[1]);
+
+#define EDONR_ALGO_TEST(_m, mode, testdigest) \
+ do { \
+ EdonRState ctx; \
+ uint8_t digest[mode / 8]; \
+ EdonRInit(&ctx, mode); \
+ EdonRUpdate(&ctx, (const uint8_t *) _m, strlen(_m) * 8);\
+ EdonRFinal(&ctx, digest); \
+ (void) printf("Edon-R-%-6sMessage: " #_m \
+ "\tResult: ", #mode); \
+ if (bcmp(digest, testdigest, mode / 8) == 0) { \
+ (void) printf("OK\n"); \
+ } else { \
+ (void) printf("FAILED!\n"); \
+ failed = B_TRUE; \
+ } \
+ NOTE(CONSTCOND) \
+ } while (0)
+
+#define EDONR_PERF_TEST(mode) \
+ do { \
+ EdonRState ctx; \
+ uint8_t digest[mode / 8]; \
+ uint8_t block[131072]; \
+ uint64_t delta; \
+ double cpb = 0; \
+ int i; \
+ struct timeval start, end; \
+ bzero(block, sizeof (block)); \
+ (void) gettimeofday(&start, NULL); \
+ EdonRInit(&ctx, mode); \
+ for (i = 0; i < 8192; i++) \
+ EdonRUpdate(&ctx, block, sizeof (block) * 8); \
+ EdonRFinal(&ctx, digest); \
+ (void) gettimeofday(&end, NULL); \
+ delta = (end.tv_sec * 1000000llu + end.tv_usec) - \
+ (start.tv_sec * 1000000llu + start.tv_usec); \
+ if (cpu_mhz != 0) { \
+ cpb = (cpu_mhz * 1e6 * ((double)delta / \
+ 1000000)) / (8192 * 128 * 1024); \
+ } \
+ (void) printf("Edon-R-%-6s%llu us (%.02f CPB)\n", #mode,\
+ (u_longlong_t)delta, cpb); \
+ NOTE(CONSTCOND) \
+ } while (0)
+
+ (void) printf("Running algorithm correctness tests:\n");
+ EDONR_ALGO_TEST(test_msg0, 224, edonr_224_test_digests[0]);
+ EDONR_ALGO_TEST(test_msg1, 224, edonr_224_test_digests[1]);
+ EDONR_ALGO_TEST(test_msg0, 256, edonr_256_test_digests[0]);
+ EDONR_ALGO_TEST(test_msg1, 256, edonr_256_test_digests[1]);
+ EDONR_ALGO_TEST(test_msg0, 384, edonr_384_test_digests[0]);
+ EDONR_ALGO_TEST(test_msg2, 384, edonr_384_test_digests[2]);
+ EDONR_ALGO_TEST(test_msg0, 512, edonr_512_test_digests[0]);
+ EDONR_ALGO_TEST(test_msg2, 512, edonr_512_test_digests[2]);
+ if (failed)
+ return (1);
+
+ (void) printf("Running performance tests (hashing 1024 MiB of "
+ "data):\n");
+ EDONR_PERF_TEST(256);
+ EDONR_PERF_TEST(512);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh b/tests/zfs-tests/tests/functional/checksum/filetest_001_pos.ksh
new file mode 100755
index 000000000000..0cad8047cdee
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/filetest_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 (c) 2018, 2019 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/checksum/default.cfg
+
+# DESCRIPTION:
+# Sanity test to make sure checksum algorithms work.
+# For each checksum, create a file in the pool using that checksum. Verify
+# that there are no checksum errors. Next, for each checksum, create a single
+# file in the pool using that checksum, corrupt the file, and verify that we
+# correctly catch the checksum errors.
+#
+# STRATEGY:
+# Test 1
+# 1. Create a mirrored pool
+# 2. Create a file using each checksum
+# 3. Export/import/scrub the pool
+# 4. Verify there's no checksum errors.
+# 5. Clear the pool
+#
+# Test 2
+# 6. For each checksum:
+# 7. Create a file using the checksum
+# 8. Corrupt all level 0 blocks in the file
+# 9. Scrub the pool
+# 10. Verify that there are checksum errors
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -fr $TESTDIR/*
+}
+
+log_assert "Create and read back files with using different checksum algorithms"
+
+log_onexit cleanup
+
+WRITESZ=1048576
+
+# Get a list of vdevs in our pool
+set -A array $(get_disklist_fullpath)
+
+# Get the first vdev, since we will corrupt it later
+firstvdev=${array[0]}
+
+# Test each checksum by writing a file using it, confirm there are no errors.
+typeset -i i=1
+while [[ $i -lt ${#CHECKSUM_TYPES[*]} ]]; do
+ type=${CHECKSUM_TYPES[i]}
+ log_must zfs set checksum=$type $TESTPOOL
+ log_must file_write -o overwrite -f $TESTDIR/test_$type \
+ -b $WRITESZ -c 5 -d R
+ (( i = i + 1 ))
+done
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+log_must zpool scrub $TESTPOOL
+log_must wait_scrubbed $TESTPOOL
+
+cksum=$(zpool status -P -v $TESTPOOL | grep "$firstvdev" | awk '{print $5}')
+log_assert "Normal file write test saw $cksum checksum errors"
+log_must [ $cksum -eq 0 ]
+
+rm -fr $TESTDIR/*
+
+log_assert "Test corrupting the files and seeing checksum errors"
+typeset -i j=1
+while [[ $j -lt ${#CHECKSUM_TYPES[*]} ]]; do
+ type=${CHECKSUM_TYPES[$j]}
+ log_must zfs set checksum=$type $TESTPOOL
+ log_must file_write -o overwrite -f $TESTDIR/test_$type \
+ -b $WRITESZ -c 5 -d R
+
+ # Corrupt the level 0 blocks of this file
+ corrupt_blocks_at_level $TESTDIR/test_$type
+
+ log_must zpool scrub $TESTPOOL
+ log_must wait_scrubbed $TESTPOOL
+
+ cksum=$(zpool status -P -v $TESTPOOL | grep "$firstvdev" | \
+ awk '{print $5}')
+
+ log_assert "Checksum '$type' caught $cksum checksum errors"
+ log_must [ $cksum -ne 0 ]
+
+ rm -f $TESTDIR/test_$type
+ log_must zpool clear $TESTPOOL
+
+ (( j = j + 1 ))
+done
diff --git a/tests/zfs-tests/tests/functional/checksum/run_edonr_test.ksh b/tests/zfs-tests/tests/functional/checksum/run_edonr_test.ksh
new file mode 100755
index 000000000000..42e88a8c8e3f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/run_edonr_test.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) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# Run the tests for the EdonR hash algorithm.
+#
+
+log_assert "Run the tests for the EdonR hash algorithm."
+
+freq=$(get_cpu_freq)
+log_must $STF_SUITE/tests/functional/checksum/edonr_test $freq
+
+log_pass "EdonR tests passed."
diff --git a/tests/zfs-tests/tests/functional/checksum/run_sha2_test.ksh b/tests/zfs-tests/tests/functional/checksum/run_sha2_test.ksh
new file mode 100755
index 000000000000..e238d7a53e6d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/run_sha2_test.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) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# Run the tests for the SHA-2 hash algorithm.
+#
+
+log_assert "Run the tests for the SHA-2 hash algorithm."
+
+freq=$(get_cpu_freq)
+log_must $STF_SUITE/tests/functional/checksum/sha2_test $freq
+
+log_pass "SHA-2 tests passed."
diff --git a/tests/zfs-tests/tests/functional/checksum/run_skein_test.ksh b/tests/zfs-tests/tests/functional/checksum/run_skein_test.ksh
new file mode 100755
index 000000000000..b3a33c3ca8bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/run_skein_test.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) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Description:
+# Run the tests for the Skein hash algorithm.
+#
+
+log_assert "Run the tests for the Skein hash algorithm."
+
+freq=$(get_cpu_freq)
+log_must $STF_SUITE/tests/functional/checksum/skein_test $freq
+
+log_pass "Skein tests passed."
diff --git a/tests/zfs-tests/tests/functional/checksum/setup.ksh b/tests/zfs-tests/tests/functional/checksum/setup.ksh
new file mode 100755
index 000000000000..204069de7383
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_mirror_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/checksum/sha2_test.c b/tests/zfs-tests/tests/functional/checksum/sha2_test.c
new file mode 100644
index 000000000000..5800002a6ef7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/sha2_test.c
@@ -0,0 +1,250 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
+ */
+
+/*
+ * This is just to keep the compiler happy about sys/time.h not declaring
+ * gettimeofday due to -D_KERNEL (we can do this since we're actually
+ * running in userspace, but we need -D_KERNEL for the remaining SHA2 code).
+ */
+#ifdef _KERNEL
+#undef _KERNEL
+#endif
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/time.h>
+#define _SHA2_IMPL
+#include <sys/sha2.h>
+#include <sys/stdtypes.h>
+#define NOTE(x)
+
+
+/*
+ * Test messages from:
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
+ */
+
+const char *test_msg0 = "abc";
+const char *test_msg1 = "abcdbcdecdefdefgefghfghighijhijkijkljklmklmn"
+ "lmnomnopnopq";
+const char *test_msg2 = "abcdefghbcdefghicdefghijdefghijkefghijklfghi"
+ "jklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+
+/*
+ * Test digests from:
+ * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/SHA_All.pdf
+ */
+const uint8_t sha256_test_digests[][32] = {
+ {
+ /* for test_msg0 */
+ 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
+ 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
+ 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
+ 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD
+ },
+ {
+ /* for test_msg1 */
+ 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
+ 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
+ 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
+ 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1
+ }
+ /* no test vector for test_msg2 */
+};
+
+const uint8_t sha384_test_digests[][48] = {
+ {
+ /* for test_msg0 */
+ 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
+ 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
+ 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
+ 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
+ 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
+ 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7
+ },
+ {
+ /* no test vector for test_msg1 */
+ 0
+ },
+ {
+ /* for test_msg2 */
+ 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
+ 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
+ 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
+ 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
+ 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
+ 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39
+ }
+};
+
+const uint8_t sha512_test_digests[][64] = {
+ {
+ /* for test_msg0 */
+ 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
+ 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
+ 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
+ 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
+ 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
+ 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
+ 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
+ 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F
+ },
+ {
+ /* no test vector for test_msg1 */
+ 0
+ },
+ {
+ /* for test_msg2 */
+ 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
+ 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
+ 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
+ 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
+ 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
+ 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
+ 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
+ 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09
+ }
+};
+
+const uint8_t sha512_224_test_digests[][28] = {
+ {
+ /* for test_msg0 */
+ 0x46, 0x34, 0x27, 0x0F, 0x70, 0x7B, 0x6A, 0x54,
+ 0xDA, 0xAE, 0x75, 0x30, 0x46, 0x08, 0x42, 0xE2,
+ 0x0E, 0x37, 0xED, 0x26, 0x5C, 0xEE, 0xE9, 0xA4,
+ 0x3E, 0x89, 0x24, 0xAA
+ },
+ {
+ /* no test vector for test_msg1 */
+ 0
+ },
+ {
+ /* for test_msg2 */
+ 0x23, 0xFE, 0xC5, 0xBB, 0x94, 0xD6, 0x0B, 0x23,
+ 0x30, 0x81, 0x92, 0x64, 0x0B, 0x0C, 0x45, 0x33,
+ 0x35, 0xD6, 0x64, 0x73, 0x4F, 0xE4, 0x0E, 0x72,
+ 0x68, 0x67, 0x4A, 0xF9
+ }
+};
+
+const uint8_t sha512_256_test_digests[][32] = {
+ {
+ /* for test_msg0 */
+ 0x53, 0x04, 0x8E, 0x26, 0x81, 0x94, 0x1E, 0xF9,
+ 0x9B, 0x2E, 0x29, 0xB7, 0x6B, 0x4C, 0x7D, 0xAB,
+ 0xE4, 0xC2, 0xD0, 0xC6, 0x34, 0xFC, 0x6D, 0x46,
+ 0xE0, 0xE2, 0xF1, 0x31, 0x07, 0xE7, 0xAF, 0x23
+ },
+ {
+ /* no test vector for test_msg1 */
+ 0
+ },
+ {
+ /* for test_msg2 */
+ 0x39, 0x28, 0xE1, 0x84, 0xFB, 0x86, 0x90, 0xF8,
+ 0x40, 0xDA, 0x39, 0x88, 0x12, 0x1D, 0x31, 0xBE,
+ 0x65, 0xCB, 0x9D, 0x3E, 0xF8, 0x3E, 0xE6, 0x14,
+ 0x6F, 0xEA, 0xC8, 0x61, 0xE1, 0x9B, 0x56, 0x3A
+ }
+};
+
+int
+main(int argc, char *argv[])
+{
+ boolean_t failed = B_FALSE;
+ uint64_t cpu_mhz = 0;
+
+ if (argc == 2)
+ cpu_mhz = atoi(argv[1]);
+
+#define SHA2_ALGO_TEST(_m, mode, diglen, testdigest) \
+ do { \
+ SHA2_CTX ctx; \
+ uint8_t digest[diglen / 8]; \
+ SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \
+ SHA2Update(&ctx, _m, strlen(_m)); \
+ SHA2Final(digest, &ctx); \
+ (void) printf("SHA%-9sMessage: " #_m \
+ "\tResult: ", #mode); \
+ if (bcmp(digest, testdigest, diglen / 8) == 0) { \
+ (void) printf("OK\n"); \
+ } else { \
+ (void) printf("FAILED!\n"); \
+ failed = B_TRUE; \
+ } \
+ NOTE(CONSTCOND) \
+ } while (0)
+
+#define SHA2_PERF_TEST(mode, diglen) \
+ do { \
+ SHA2_CTX ctx; \
+ uint8_t digest[diglen / 8]; \
+ uint8_t block[131072]; \
+ uint64_t delta; \
+ double cpb = 0; \
+ int i; \
+ struct timeval start, end; \
+ bzero(block, sizeof (block)); \
+ (void) gettimeofday(&start, NULL); \
+ SHA2Init(SHA ## mode ## _MECH_INFO_TYPE, &ctx); \
+ for (i = 0; i < 8192; i++) \
+ SHA2Update(&ctx, block, sizeof (block)); \
+ SHA2Final(digest, &ctx); \
+ (void) gettimeofday(&end, NULL); \
+ delta = (end.tv_sec * 1000000llu + end.tv_usec) - \
+ (start.tv_sec * 1000000llu + start.tv_usec); \
+ if (cpu_mhz != 0) { \
+ cpb = (cpu_mhz * 1e6 * ((double)delta / \
+ 1000000)) / (8192 * 128 * 1024); \
+ } \
+ (void) printf("SHA%-9s%llu us (%.02f CPB)\n", #mode, \
+ (u_longlong_t)delta, cpb); \
+ NOTE(CONSTCOND) \
+ } while (0)
+
+ (void) printf("Running algorithm correctness tests:\n");
+ SHA2_ALGO_TEST(test_msg0, 256, 256, sha256_test_digests[0]);
+ SHA2_ALGO_TEST(test_msg1, 256, 256, sha256_test_digests[1]);
+ SHA2_ALGO_TEST(test_msg0, 384, 384, sha384_test_digests[0]);
+ SHA2_ALGO_TEST(test_msg2, 384, 384, sha384_test_digests[2]);
+ SHA2_ALGO_TEST(test_msg0, 512, 512, sha512_test_digests[0]);
+ SHA2_ALGO_TEST(test_msg2, 512, 512, sha512_test_digests[2]);
+ SHA2_ALGO_TEST(test_msg0, 512_224, 224, sha512_224_test_digests[0]);
+ SHA2_ALGO_TEST(test_msg2, 512_224, 224, sha512_224_test_digests[2]);
+ SHA2_ALGO_TEST(test_msg0, 512_256, 256, sha512_256_test_digests[0]);
+ SHA2_ALGO_TEST(test_msg2, 512_256, 256, sha512_256_test_digests[2]);
+
+ if (failed)
+ return (1);
+
+ (void) printf("Running performance tests (hashing 1024 MiB of "
+ "data):\n");
+ SHA2_PERF_TEST(256, 256);
+ SHA2_PERF_TEST(512, 512);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/checksum/skein_test.c b/tests/zfs-tests/tests/functional/checksum/skein_test.c
new file mode 100644
index 000000000000..55df9075c66b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/checksum/skein_test.c
@@ -0,0 +1,340 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://opensource.org/licenses/CDDL-1.0.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2013 Saso Kiselkov. All rights reserved.
+ */
+
+/*
+ * This is just to keep the compiler happy about sys/time.h not declaring
+ * gettimeofday due to -D_KERNEL (we can do this since we're actually
+ * running in userspace, but we need -D_KERNEL for the remaining Skein code).
+ */
+#ifdef _KERNEL
+#undef _KERNEL
+#endif
+
+#include <sys/skein.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/stdtypes.h>
+#define NOTE(x)
+
+/*
+ * Skein test suite using values from the Skein V1.3 specification found at:
+ * http://www.skein-hash.info/sites/default/files/skein1.3.pdf
+ */
+
+/*
+ * Test messages from the Skein spec, Appendix C.
+ */
+const uint8_t test_msg0[] = {
+ 0xFF
+};
+
+const uint8_t test_msg1[] = {
+ 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
+ 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
+ 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
+ 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0
+};
+
+const uint8_t test_msg2[] = {
+ 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
+ 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
+ 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
+ 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
+ 0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
+ 0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
+ 0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
+ 0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0
+};
+
+const uint8_t test_msg3[] = {
+ 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
+ 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
+ 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
+ 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
+ 0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
+ 0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
+ 0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
+ 0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0,
+ 0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8,
+ 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0,
+ 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8,
+ 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0,
+ 0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98,
+ 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
+ 0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88,
+ 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80
+};
+
+const uint8_t test_msg4[] = {
+ 0xFF, 0xFE, 0xFD, 0xFC, 0xFB, 0xFA, 0xF9, 0xF8,
+ 0xF7, 0xF6, 0xF5, 0xF4, 0xF3, 0xF2, 0xF1, 0xF0,
+ 0xEF, 0xEE, 0xED, 0xEC, 0xEB, 0xEA, 0xE9, 0xE8,
+ 0xE7, 0xE6, 0xE5, 0xE4, 0xE3, 0xE2, 0xE1, 0xE0,
+ 0xDF, 0xDE, 0xDD, 0xDC, 0xDB, 0xDA, 0xD9, 0xD8,
+ 0xD7, 0xD6, 0xD5, 0xD4, 0xD3, 0xD2, 0xD1, 0xD0,
+ 0xCF, 0xCE, 0xCD, 0xCC, 0xCB, 0xCA, 0xC9, 0xC8,
+ 0xC7, 0xC6, 0xC5, 0xC4, 0xC3, 0xC2, 0xC1, 0xC0,
+ 0xBF, 0xBE, 0xBD, 0xBC, 0xBB, 0xBA, 0xB9, 0xB8,
+ 0xB7, 0xB6, 0xB5, 0xB4, 0xB3, 0xB2, 0xB1, 0xB0,
+ 0xAF, 0xAE, 0xAD, 0xAC, 0xAB, 0xAA, 0xA9, 0xA8,
+ 0xA7, 0xA6, 0xA5, 0xA4, 0xA3, 0xA2, 0xA1, 0xA0,
+ 0x9F, 0x9E, 0x9D, 0x9C, 0x9B, 0x9A, 0x99, 0x98,
+ 0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
+ 0x8F, 0x8E, 0x8D, 0x8C, 0x8B, 0x8A, 0x89, 0x88,
+ 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
+ 0x7F, 0x7E, 0x7D, 0x7C, 0x7B, 0x7A, 0x79, 0x78,
+ 0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
+ 0x6F, 0x6E, 0x6D, 0x6C, 0x6B, 0x6A, 0x69, 0x68,
+ 0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60,
+ 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58,
+ 0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
+ 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, 0x48,
+ 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
+ 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, 0x38,
+ 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
+ 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, 0x28,
+ 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
+ 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, 0x18,
+ 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
+ 0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08,
+ 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00
+};
+
+/*
+ * Test digests from the Skein spec, Appendix C.
+ */
+const uint8_t skein_256_test_digests[][32] = {
+ {
+ /* for test_msg0 */
+ 0x0B, 0x98, 0xDC, 0xD1, 0x98, 0xEA, 0x0E, 0x50,
+ 0xA7, 0xA2, 0x44, 0xC4, 0x44, 0xE2, 0x5C, 0x23,
+ 0xDA, 0x30, 0xC1, 0x0F, 0xC9, 0xA1, 0xF2, 0x70,
+ 0xA6, 0x63, 0x7F, 0x1F, 0x34, 0xE6, 0x7E, 0xD2
+ },
+ {
+ /* for test_msg1 */
+ 0x8D, 0x0F, 0xA4, 0xEF, 0x77, 0x7F, 0xD7, 0x59,
+ 0xDF, 0xD4, 0x04, 0x4E, 0x6F, 0x6A, 0x5A, 0xC3,
+ 0xC7, 0x74, 0xAE, 0xC9, 0x43, 0xDC, 0xFC, 0x07,
+ 0x92, 0x7B, 0x72, 0x3B, 0x5D, 0xBF, 0x40, 0x8B
+ },
+ {
+ /* for test_msg2 */
+ 0xDF, 0x28, 0xE9, 0x16, 0x63, 0x0D, 0x0B, 0x44,
+ 0xC4, 0xA8, 0x49, 0xDC, 0x9A, 0x02, 0xF0, 0x7A,
+ 0x07, 0xCB, 0x30, 0xF7, 0x32, 0x31, 0x82, 0x56,
+ 0xB1, 0x5D, 0x86, 0x5A, 0xC4, 0xAE, 0x16, 0x2F
+ }
+ /* no test digests for test_msg3 and test_msg4 */
+};
+
+const uint8_t skein_512_test_digests[][64] = {
+ {
+ /* for test_msg0 */
+ 0x71, 0xB7, 0xBC, 0xE6, 0xFE, 0x64, 0x52, 0x22,
+ 0x7B, 0x9C, 0xED, 0x60, 0x14, 0x24, 0x9E, 0x5B,
+ 0xF9, 0xA9, 0x75, 0x4C, 0x3A, 0xD6, 0x18, 0xCC,
+ 0xC4, 0xE0, 0xAA, 0xE1, 0x6B, 0x31, 0x6C, 0xC8,
+ 0xCA, 0x69, 0x8D, 0x86, 0x43, 0x07, 0xED, 0x3E,
+ 0x80, 0xB6, 0xEF, 0x15, 0x70, 0x81, 0x2A, 0xC5,
+ 0x27, 0x2D, 0xC4, 0x09, 0xB5, 0xA0, 0x12, 0xDF,
+ 0x2A, 0x57, 0x91, 0x02, 0xF3, 0x40, 0x61, 0x7A
+ },
+ {
+ /* no test vector for test_msg1 */
+ 0,
+ },
+ {
+ /* for test_msg2 */
+ 0x45, 0x86, 0x3B, 0xA3, 0xBE, 0x0C, 0x4D, 0xFC,
+ 0x27, 0xE7, 0x5D, 0x35, 0x84, 0x96, 0xF4, 0xAC,
+ 0x9A, 0x73, 0x6A, 0x50, 0x5D, 0x93, 0x13, 0xB4,
+ 0x2B, 0x2F, 0x5E, 0xAD, 0xA7, 0x9F, 0xC1, 0x7F,
+ 0x63, 0x86, 0x1E, 0x94, 0x7A, 0xFB, 0x1D, 0x05,
+ 0x6A, 0xA1, 0x99, 0x57, 0x5A, 0xD3, 0xF8, 0xC9,
+ 0xA3, 0xCC, 0x17, 0x80, 0xB5, 0xE5, 0xFA, 0x4C,
+ 0xAE, 0x05, 0x0E, 0x98, 0x98, 0x76, 0x62, 0x5B
+ },
+ {
+ /* for test_msg3 */
+ 0x91, 0xCC, 0xA5, 0x10, 0xC2, 0x63, 0xC4, 0xDD,
+ 0xD0, 0x10, 0x53, 0x0A, 0x33, 0x07, 0x33, 0x09,
+ 0x62, 0x86, 0x31, 0xF3, 0x08, 0x74, 0x7E, 0x1B,
+ 0xCB, 0xAA, 0x90, 0xE4, 0x51, 0xCA, 0xB9, 0x2E,
+ 0x51, 0x88, 0x08, 0x7A, 0xF4, 0x18, 0x87, 0x73,
+ 0xA3, 0x32, 0x30, 0x3E, 0x66, 0x67, 0xA7, 0xA2,
+ 0x10, 0x85, 0x6F, 0x74, 0x21, 0x39, 0x00, 0x00,
+ 0x71, 0xF4, 0x8E, 0x8B, 0xA2, 0xA5, 0xAD, 0xB7
+ }
+ /* no test digests for test_msg4 */
+};
+
+const uint8_t skein_1024_test_digests[][128] = {
+ {
+ /* for test_msg0 */
+ 0xE6, 0x2C, 0x05, 0x80, 0x2E, 0xA0, 0x15, 0x24,
+ 0x07, 0xCD, 0xD8, 0x78, 0x7F, 0xDA, 0x9E, 0x35,
+ 0x70, 0x3D, 0xE8, 0x62, 0xA4, 0xFB, 0xC1, 0x19,
+ 0xCF, 0xF8, 0x59, 0x0A, 0xFE, 0x79, 0x25, 0x0B,
+ 0xCC, 0xC8, 0xB3, 0xFA, 0xF1, 0xBD, 0x24, 0x22,
+ 0xAB, 0x5C, 0x0D, 0x26, 0x3F, 0xB2, 0xF8, 0xAF,
+ 0xB3, 0xF7, 0x96, 0xF0, 0x48, 0x00, 0x03, 0x81,
+ 0x53, 0x1B, 0x6F, 0x00, 0xD8, 0x51, 0x61, 0xBC,
+ 0x0F, 0xFF, 0x4B, 0xEF, 0x24, 0x86, 0xB1, 0xEB,
+ 0xCD, 0x37, 0x73, 0xFA, 0xBF, 0x50, 0xAD, 0x4A,
+ 0xD5, 0x63, 0x9A, 0xF9, 0x04, 0x0E, 0x3F, 0x29,
+ 0xC6, 0xC9, 0x31, 0x30, 0x1B, 0xF7, 0x98, 0x32,
+ 0xE9, 0xDA, 0x09, 0x85, 0x7E, 0x83, 0x1E, 0x82,
+ 0xEF, 0x8B, 0x46, 0x91, 0xC2, 0x35, 0x65, 0x65,
+ 0x15, 0xD4, 0x37, 0xD2, 0xBD, 0xA3, 0x3B, 0xCE,
+ 0xC0, 0x01, 0xC6, 0x7F, 0xFD, 0xE1, 0x5B, 0xA8
+ },
+ {
+ /* no test vector for test_msg1 */
+ 0
+ },
+ {
+ /* no test vector for test_msg2 */
+ 0
+ },
+ {
+ /* for test_msg3 */
+ 0x1F, 0x3E, 0x02, 0xC4, 0x6F, 0xB8, 0x0A, 0x3F,
+ 0xCD, 0x2D, 0xFB, 0xBC, 0x7C, 0x17, 0x38, 0x00,
+ 0xB4, 0x0C, 0x60, 0xC2, 0x35, 0x4A, 0xF5, 0x51,
+ 0x18, 0x9E, 0xBF, 0x43, 0x3C, 0x3D, 0x85, 0xF9,
+ 0xFF, 0x18, 0x03, 0xE6, 0xD9, 0x20, 0x49, 0x31,
+ 0x79, 0xED, 0x7A, 0xE7, 0xFC, 0xE6, 0x9C, 0x35,
+ 0x81, 0xA5, 0xA2, 0xF8, 0x2D, 0x3E, 0x0C, 0x7A,
+ 0x29, 0x55, 0x74, 0xD0, 0xCD, 0x7D, 0x21, 0x7C,
+ 0x48, 0x4D, 0x2F, 0x63, 0x13, 0xD5, 0x9A, 0x77,
+ 0x18, 0xEA, 0xD0, 0x7D, 0x07, 0x29, 0xC2, 0x48,
+ 0x51, 0xD7, 0xE7, 0xD2, 0x49, 0x1B, 0x90, 0x2D,
+ 0x48, 0x91, 0x94, 0xE6, 0xB7, 0xD3, 0x69, 0xDB,
+ 0x0A, 0xB7, 0xAA, 0x10, 0x6F, 0x0E, 0xE0, 0xA3,
+ 0x9A, 0x42, 0xEF, 0xC5, 0x4F, 0x18, 0xD9, 0x37,
+ 0x76, 0x08, 0x09, 0x85, 0xF9, 0x07, 0x57, 0x4F,
+ 0x99, 0x5E, 0xC6, 0xA3, 0x71, 0x53, 0xA5, 0x78
+ },
+ {
+ /* for test_msg4 */
+ 0x84, 0x2A, 0x53, 0xC9, 0x9C, 0x12, 0xB0, 0xCF,
+ 0x80, 0xCF, 0x69, 0x49, 0x1B, 0xE5, 0xE2, 0xF7,
+ 0x51, 0x5D, 0xE8, 0x73, 0x3B, 0x6E, 0xA9, 0x42,
+ 0x2D, 0xFD, 0x67, 0x66, 0x65, 0xB5, 0xFA, 0x42,
+ 0xFF, 0xB3, 0xA9, 0xC4, 0x8C, 0x21, 0x77, 0x77,
+ 0x95, 0x08, 0x48, 0xCE, 0xCD, 0xB4, 0x8F, 0x64,
+ 0x0F, 0x81, 0xFB, 0x92, 0xBE, 0xF6, 0xF8, 0x8F,
+ 0x7A, 0x85, 0xC1, 0xF7, 0xCD, 0x14, 0x46, 0xC9,
+ 0x16, 0x1C, 0x0A, 0xFE, 0x8F, 0x25, 0xAE, 0x44,
+ 0x4F, 0x40, 0xD3, 0x68, 0x00, 0x81, 0xC3, 0x5A,
+ 0xA4, 0x3F, 0x64, 0x0F, 0xD5, 0xFA, 0x3C, 0x3C,
+ 0x03, 0x0B, 0xCC, 0x06, 0xAB, 0xAC, 0x01, 0xD0,
+ 0x98, 0xBC, 0xC9, 0x84, 0xEB, 0xD8, 0x32, 0x27,
+ 0x12, 0x92, 0x1E, 0x00, 0xB1, 0xBA, 0x07, 0xD6,
+ 0xD0, 0x1F, 0x26, 0x90, 0x70, 0x50, 0x25, 0x5E,
+ 0xF2, 0xC8, 0xE2, 0x4F, 0x71, 0x6C, 0x52, 0xA5
+ }
+};
+
+int
+main(int argc, char *argv[])
+{
+ boolean_t failed = B_FALSE;
+ uint64_t cpu_mhz = 0;
+
+ if (argc == 2)
+ cpu_mhz = atoi(argv[1]);
+
+#define SKEIN_ALGO_TEST(_m, mode, diglen, testdigest) \
+ do { \
+ Skein ## mode ## _Ctxt_t ctx; \
+ uint8_t digest[diglen / 8]; \
+ (void) Skein ## mode ## _Init(&ctx, diglen); \
+ (void) Skein ## mode ## _Update(&ctx, _m, sizeof (_m)); \
+ (void) Skein ## mode ## _Final(&ctx, digest); \
+ (void) printf("Skein" #mode "/" #diglen \
+ "\tMessage: " #_m "\tResult: "); \
+ if (bcmp(digest, testdigest, diglen / 8) == 0) { \
+ (void) printf("OK\n"); \
+ } else { \
+ (void) printf("FAILED!\n"); \
+ failed = B_TRUE; \
+ } \
+ NOTE(CONSTCOND) \
+ } while (0)
+
+#define SKEIN_PERF_TEST(mode, diglen) \
+ do { \
+ Skein ## mode ## _Ctxt_t ctx; \
+ uint8_t digest[diglen / 8]; \
+ uint8_t block[131072]; \
+ uint64_t delta; \
+ double cpb = 0; \
+ int i; \
+ struct timeval start, end; \
+ bzero(block, sizeof (block)); \
+ (void) gettimeofday(&start, NULL); \
+ (void) Skein ## mode ## _Init(&ctx, diglen); \
+ for (i = 0; i < 8192; i++) { \
+ (void) Skein ## mode ## _Update(&ctx, block, \
+ sizeof (block)); \
+ } \
+ (void) Skein ## mode ## _Final(&ctx, digest); \
+ (void) gettimeofday(&end, NULL); \
+ delta = (end.tv_sec * 1000000llu + end.tv_usec) - \
+ (start.tv_sec * 1000000llu + start.tv_usec); \
+ if (cpu_mhz != 0) { \
+ cpb = (cpu_mhz * 1e6 * ((double)delta / \
+ 1000000)) / (8192 * 128 * 1024); \
+ } \
+ (void) printf("Skein" #mode "/" #diglen "\t%llu us " \
+ "(%.02f CPB)\n", (u_longlong_t)delta, cpb); \
+ NOTE(CONSTCOND) \
+ } while (0)
+
+ (void) printf("Running algorithm correctness tests:\n");
+ SKEIN_ALGO_TEST(test_msg0, _256, 256, skein_256_test_digests[0]);
+ SKEIN_ALGO_TEST(test_msg1, _256, 256, skein_256_test_digests[1]);
+ SKEIN_ALGO_TEST(test_msg2, _256, 256, skein_256_test_digests[2]);
+ SKEIN_ALGO_TEST(test_msg0, _512, 512, skein_512_test_digests[0]);
+ SKEIN_ALGO_TEST(test_msg2, _512, 512, skein_512_test_digests[2]);
+ SKEIN_ALGO_TEST(test_msg3, _512, 512, skein_512_test_digests[3]);
+ SKEIN_ALGO_TEST(test_msg0, 1024, 1024, skein_1024_test_digests[0]);
+ SKEIN_ALGO_TEST(test_msg3, 1024, 1024, skein_1024_test_digests[3]);
+ SKEIN_ALGO_TEST(test_msg4, 1024, 1024, skein_1024_test_digests[4]);
+ if (failed)
+ return (1);
+
+ (void) printf("Running performance tests (hashing 1024 MiB of "
+ "data):\n");
+ SKEIN_PERF_TEST(_256, 256);
+ SKEIN_PERF_TEST(_512, 512);
+ SKEIN_PERF_TEST(1024, 1024);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/Makefile.am b/tests/zfs-tests/tests/functional/clean_mirror/Makefile.am
new file mode 100644
index 000000000000..2bc67709fffb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/clean_mirror
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ clean_mirror_001_pos.ksh \
+ clean_mirror_002_pos.ksh \
+ clean_mirror_003_pos.ksh \
+ clean_mirror_004_pos.ksh
+
+dist_pkgdata_DATA = \
+ clean_mirror_common.kshlib \
+ default.cfg
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos.ksh b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_pos.ksh
new file mode 100755
index 000000000000..8dd337a6efb9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_001_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/clean_mirror/clean_mirror_common.kshlib
+
+#
+# DESCRIPTION:
+# The primary side of a zpool mirror can be zeroed without causing damage
+# to the data in the pool
+#
+# STRATEGY:
+# 1) Write several files to the ZFS filesystem mirror
+# 2) dd from /dev/zero over the primary side of the mirror
+# 3) verify that all the file contents are unchanged on the file system
+#
+
+verify_runnable "global"
+
+log_assert "The primary side of a zpool mirror may be completely wiped" \
+ "without affecting the content of the pool"
+
+overwrite_verify_mirror $SIDE_PRIMARY /dev/zero
+
+log_pass "The overwrite had no effect on the data"
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos.ksh b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_002_pos.ksh
new file mode 100755
index 000000000000..a156368d0c89
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/clean_mirror/clean_mirror_common.kshlib
+
+#
+# DESCRIPTION:
+# The secondary side of a zpool mirror can be zeroed without causing damage
+# to the data in the pool
+#
+# STRATEGY:
+# 1) Write several files to the ZFS filesystem in the mirrored pool
+# 2) dd from /dev/zero over the secondary side of the mirror
+# 3) verify that all the file contents are unchanged on the file system
+#
+
+verify_runnable "global"
+
+log_assert "The primary side of a zpool mirror may be completely wiped" \
+ "without affecting the content of the pool"
+
+overwrite_verify_mirror $SIDE_SECONDARY /dev/zero
+
+log_pass "The overwrite had no effect on the data"
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_pos.ksh b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_pos.ksh
new file mode 100755
index 000000000000..144dcf1c0b72
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_003_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/clean_mirror/clean_mirror_common.kshlib
+
+#
+# DESCRIPTION:
+# The primary side of a zpool mirror can be mangled without causing damage
+# to the data in the pool
+#
+# STRATEGY:
+# 1) Write several files to the ZFS filesystem mirror
+# 2) dd from /dev/urandom over the primary side of the mirror
+# 3) verify that all the file contents are unchanged on the file system
+#
+
+verify_runnable "global"
+
+log_assert "The primary side of a zpool mirror may be completely mangled" \
+ "without affecting the content of the pool"
+
+overwrite_verify_mirror $SIDE_PRIMARY /dev/urandom
+
+log_pass "The overwrite did not have any effect on the data"
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_pos.ksh b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_pos.ksh
new file mode 100755
index 000000000000..ce1aac56d85a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_004_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/clean_mirror/clean_mirror_common.kshlib
+
+#
+# DESCRIPTION:
+# The secondary side of a zpool mirror can be mangled without causing damage
+# to the data in the pool
+#
+# STRATEGY:
+# 1) Write several files to the ZFS filesystem in the mirrored pool
+# 2) dd from /dev/urandom over the secondary side of the mirror
+# 3) verify that all the file contents are unchanged on the file system
+#
+
+verify_runnable "global"
+
+log_assert "The primary side of a zpool mirror may be completely mangled" \
+ "without affecting the content of the pool"
+
+overwrite_verify_mirror $SIDE_SECONDARY /dev/urandom
+
+log_pass "The overwrite had no effect on the data"
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib
new file mode 100644
index 000000000000..cf1d77d9ccb5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/clean_mirror_common.kshlib
@@ -0,0 +1,83 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2017 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/clean_mirror/default.cfg
+
+function overwrite_verify_mirror
+{
+ typeset AFFECTED_DEVICE=$1
+ typeset OVERWRITING_DEVICE=$2
+
+ typeset atfile=0
+ set -A files
+ set -A cksums
+ set -A newcksums
+
+ while (( atfile < FILE_COUNT )); do
+ files[$atfile]=$TESTDIR/file.$atfile
+ log_must file_write -o create -f $TESTDIR/file.$atfile \
+ -b $FILE_SIZE -c 1
+ cksums[$atfile]=$(cksum ${files[$atfile]})
+ (( atfile = atfile + 1 ))
+ done
+
+ # dd the affected side of the mirror
+ log_must dd if=$OVERWRITING_DEVICE of=$AFFECTED_DEVICE \
+ seek=8 bs=$DD_BLOCK count=$(( DD_COUNT - 128 )) conv=notrunc
+
+ atfile=0
+
+ #
+ # Flush out the cache so that we ensure we're reading from disk.
+ #
+ log_must zpool export $TESTPOOL
+ log_must zpool import -d $SIDE_DIR $TESTPOOL
+
+ typeset -i failedcount=0
+ while (( atfile < FILE_COUNT )); do
+ files[$atfile]=$TESTDIR/file.$atfile
+ newcksum=$(cksum ${files[$atfile]})
+ if [[ $newcksum != ${cksums[$atfile]} ]]; then
+ (( failedcount = failedcount + 1 ))
+ fi
+ rm -f ${files[$atfile]}
+ (( atfile = atfile + 1 ))
+ done
+
+ if (( $failedcount > 0 )); then
+ log_fail "of the $FILE_COUNT files $failedcount did not " \
+ "have the same checksum before and after."
+ fi
+
+ log_must zpool scrub $TESTPOOL
+ log_must wait_scrubbed $TESTPOOL
+}
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh b/tests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh
new file mode 100755
index 000000000000..d5614bef0420
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/cleanup.ksh
@@ -0,0 +1,41 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/clean_mirror/default.cfg
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+destroy_pool $TESTPOOL
+log_must rm -f $SIDE_PRIMARY $SIDE_SECONDARY
+log_must rmdir $SIDE_DIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/default.cfg b/tests/zfs-tests/tests/functional/clean_mirror/default.cfg
new file mode 100644
index 000000000000..dfe7f1d0ba33
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/default.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export SIDE_DIR="${TEST_BASE_DIR}/clean_mirror"
+export SIDE_PRIMARY="${SIDE_DIR}/dev1"
+export SIDE_SECONDARY="${SIDE_DIR}/dev2"
+export FILE_COUNT=10
+export FILE_SIZE=$(( 1024 * 1024 ))
+export DD_BLOCK=$(( 64 * 1024 ))
+export DD_COUNT=$(( MINVDEVSIZE / DD_BLOCK ))
diff --git a/tests/zfs-tests/tests/functional/clean_mirror/setup.ksh b/tests/zfs-tests/tests/functional/clean_mirror/setup.ksh
new file mode 100755
index 000000000000..0024f284d8f5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/clean_mirror/setup.ksh
@@ -0,0 +1,41 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/clean_mirror/default.cfg
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_must mkdir -p $SIDE_DIR
+log_must truncate -s $MINVDEVSIZE $SIDE_PRIMARY $SIDE_SECONDARY
+default_mirror_setup $SIDE_PRIMARY $SIDE_SECONDARY
+
+log_pass
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."
diff --git a/tests/zfs-tests/tests/functional/cli_user/Makefile.am b/tests/zfs-tests/tests/functional/cli_user/Makefile.am
new file mode 100644
index 000000000000..119f8ee187f6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/Makefile.am
@@ -0,0 +1,6 @@
+SUBDIRS = \
+ misc \
+ zfs_list \
+ zpool_iostat \
+ zpool_list \
+ zpool_status
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/Makefile.am b/tests/zfs-tests/tests/functional/cli_user/misc/Makefile.am
new file mode 100644
index 000000000000..2d38e65777f7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/Makefile.am
@@ -0,0 +1,52 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_user/misc
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zdb_001_neg.ksh \
+ zfs_001_neg.ksh \
+ zfs_allow_001_neg.ksh \
+ zfs_clone_001_neg.ksh \
+ zfs_create_001_neg.ksh \
+ zfs_destroy_001_neg.ksh \
+ zfs_get_001_neg.ksh \
+ zfs_inherit_001_neg.ksh \
+ zfs_mount_001_neg.ksh \
+ zfs_promote_001_neg.ksh \
+ zfs_receive_001_neg.ksh \
+ zfs_rename_001_neg.ksh \
+ zfs_rollback_001_neg.ksh \
+ zfs_send_001_neg.ksh \
+ zfs_set_001_neg.ksh \
+ zfs_share_001_neg.ksh \
+ zfs_snapshot_001_neg.ksh \
+ zfs_unallow_001_neg.ksh \
+ zfs_unmount_001_neg.ksh \
+ zfs_unshare_001_neg.ksh \
+ zfs_upgrade_001_neg.ksh \
+ zpool_001_neg.ksh \
+ zpool_add_001_neg.ksh \
+ zpool_attach_001_neg.ksh \
+ zpool_clear_001_neg.ksh \
+ zpool_create_001_neg.ksh \
+ zpool_destroy_001_neg.ksh \
+ zpool_detach_001_neg.ksh \
+ zpool_export_001_neg.ksh \
+ zpool_get_001_neg.ksh \
+ zpool_history_001_neg.ksh \
+ zpool_import_001_neg.ksh \
+ zpool_import_002_neg.ksh \
+ zpool_offline_001_neg.ksh \
+ zpool_online_001_neg.ksh \
+ zpool_remove_001_neg.ksh \
+ zpool_replace_001_neg.ksh \
+ zpool_scrub_001_neg.ksh \
+ zpool_set_001_neg.ksh \
+ zpool_status_001_neg.ksh \
+ zpool_upgrade_001_neg.ksh \
+ arcstat_001_pos.ksh \
+ arc_summary_001_pos.ksh \
+ arc_summary_002_neg.ksh \
+ zpool_wait_privilege.ksh
+
+dist_pkgdata_DATA = \
+ misc.cfg
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh
new file mode 100755
index 000000000000..a445fbb48cf3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_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 (c) 2015 by Lawrence Livermore National Security, LLC.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+log_assert "arc_summary generates output and doesn't return an error code"
+
+# Depending on which version of arc_summary is installed some command
+# line options may not be available. The python3 version includes
+# several additional flags.
+python3 -V 2>&1 > /dev/null
+if (( $? )); then
+ # Some systems have Python 3 installed, but only older versions
+ # that don't have the subprocess.run() functionality. We catch
+ # these with a separate test. Remove this when all systems have
+ # reached 3.5 or greater
+ VERSIONPYTEST=$(python3 -V)
+ if [[ ${VERSIONPYTEST:9:1} -lt 5 ]]; then
+ set -A args "" "-a" "-d" "-p 1"
+ else
+ set -A args "" "-a" "-d" "-p 1" "-g" "-s arc" "-r"
+ fi
+else
+ set -A args "" "-a" "-d" "-p 1"
+fi
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_must eval "arc_summary ${args[i]} > /dev/null"
+ ((i = i + 1))
+done
+
+log_must eval "arc_summary | head > /dev/null"
+log_must eval "arc_summary | head -1 > /dev/null"
+
+log_pass "arc_summary generates output and doesn't return an error code"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh
new file mode 100755
index 000000000000..de747fba89d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.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 (c) 2015 by Lawrence Livermore National Security, LLC.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+typeset args=("-x" "-5" "-p 7" "--err" "-@")
+
+log_assert "arc_summary generates an error code with invalid options"
+
+for arg in "${args[@]}"; do
+ log_mustnot eval "arc_summary $arg > /dev/null"
+done
+
+log_pass "arc_summary generates an error code with invalid options"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh
new file mode 100755
index 000000000000..ab574731fed9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh
@@ -0,0 +1,41 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Lawrence Livermore National Security, LLC.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+set -A args "" "-s \",\"" "-x" "-v" \
+ "-f time,hit%,dh%,ph%,mh%"
+
+log_assert "arcstat generates output and doesn't return an error code"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_must eval "arcstat ${args[i]} > /dev/null"
+ ((i = i + 1))
+done
+log_pass "arcstat generates output and doesn't return an error code"
+
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh
new file mode 100755
index 000000000000..e3dc8c179c0a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/cleanup.ksh
@@ -0,0 +1,51 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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_user/misc/misc.cfg
+
+if poolexists $TESTPOOL.virt; then
+ log_must zpool destroy $TESTPOOL.virt
+fi
+
+if poolexists v1-pool; then
+ log_must zpool destroy v1-pool
+fi
+
+log_must rm -f $TEST_BASE_DIR/zfstest_datastream.dat
+log_must rm -f $TEST_BASE_DIR/disk1.dat $TEST_BASE_DIR/disk2.dat \
+ $TEST_BASE_DIR/disk3.dat $TEST_BASE_DIR/disk-additional.dat \
+ $TEST_BASE_DIR/disk-export.dat $TEST_BASE_DIR/disk-offline.dat \
+ $TEST_BASE_DIR/disk-spare1.dat $TEST_BASE_DIR/disk-spare2.dat
+log_must rm -f $TEST_BASE_DIR/zfs-pool-v1.dat \
+ $TEST_BASE_DIR/zfs-pool-v1.dat.bz2
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg b/tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg
new file mode 100644
index 000000000000..af867ded5374
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/misc.cfg
@@ -0,0 +1,123 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+if is_linux; then
+ # these are the set of setable ZFS properties
+ PROP_NAMES="\
+ acltype atime \
+ checksum compression devices \
+ exec mountpoint quota readonly \
+ recordsize reservation setuid \
+ snapdir"
+
+ # these are a set of values we apply, for use when testing the
+ # zfs get/set subcommands - ordered as per the list above so we
+ # can iterate over both sets in an array
+ PROP_VALS="\
+ posixacl on \
+ fletcher2 on on \
+ on legacy none on \
+ 128K none on \
+ visible"
+
+ # these are an alternate set of property values
+ PROP_ALTVALS="\
+ noacl off \
+ fletcher4 lzjb off \
+ off /tmp/zfstest 100M off \
+ 512 10m off \
+ hidden"
+elif is_freebsd; then
+ PROP_NAMES="\
+ acltype atime \
+ checksum compression devices \
+ exec mountpoint quota readonly \
+ recordsize reservation setuid \
+ snapdir"
+
+ # these are a set of values we apply, for use when testing the
+ # zfs get/set subcommands - ordered as per the list above so we
+ # can iterate over both sets in an array
+ PROP_VALS="\
+ posixacl on \
+ fletcher2 on on \
+ on legacy none on \
+ 128K none on \
+ visible"
+
+ # these are an alternate set of property values
+ PROP_ALTVALS="\
+ noacl off \
+ fletcher4 lzjb off \
+ off /tmp/zfstest 100M off \
+ 512 10m off \
+ hidden"
+
+else
+ # these are the set of setable ZFS properties
+ PROP_NAMES="\
+ aclinherit aclmode atime \
+ checksum compression devices \
+ exec mountpoint quota readonly \
+ recordsize reservation setuid sharenfs \
+ snapdir"
+
+ # these are a set of values we apply, for use when testing the
+ # zfs get/set subcommands - ordered as per the list above so we
+ # can iterate over both sets in an array
+ PROP_VALS="\
+ passthrough discard on \
+ fletcher2 on on \
+ on legacy none on \
+ 128K none on on \
+ visible"
+
+ # these are an alternate set of property values
+ PROP_ALTVALS="\
+ passthrough-x groupmask off \
+ fletcher4 lzjb off \
+ off /tmp/zfstest 100M off \
+ 512 10m off off \
+ hidden"
+fi
+
+# additional properties to worry about: canmount copies xattr zoned version
+
+POOL_PROPS="\
+ failmode autoreplace"
+
+POOL_VALS="\
+ continue on"
+
+POOL_ALTVALS="\
+ panic off"
+
+export TESTSNAP=testsnap-misc
+export TESTCLCT=testclct-misc
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/setup.ksh
new file mode 100755
index 000000000000..fc0ebde10025
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/setup.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 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_user/misc/misc.cfg
+
+# This setup script is moderately complex, as it creates scenarios for all
+# of the tests included in this directory. Usually we'd want each test case
+# to setup/teardown its own configuration, but this would be time consuming
+# given the nature of these tests. However, as a side-effect, one test
+# leaving the system in an unknown state could impact other test cases.
+
+
+DISK=${DISKS%% *}
+VOLSIZE=150m
+TESTVOL=testvol
+
+# Create a default setup that includes a volume
+default_setup_noexit "$DISK" "" "volume"
+
+#
+# The rest of this setup script creates a ZFS filesystem configuration
+# that is used to test the rest of the zfs subcommands in this directory.
+#
+
+# create a snapshot and a clone to test clone promote
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap
+log_must zfs clone $TESTPOOL/$TESTFS@snap $TESTPOOL/$TESTFS/clone
+# create a file in the filesystem that isn't in the above snapshot
+touch $TESTDIR/file.txt
+
+
+# create a non-default property and a child we can use to test inherit
+log_must zfs create $TESTPOOL/$TESTFS/$TESTFS2
+log_must zfs set snapdir=hidden $TESTPOOL/$TESTFS
+
+
+# create an unmounted filesystem to test unmount
+log_must zfs create $TESTPOOL/$TESTFS/$TESTFS2.unmounted
+log_must zfs unmount $TESTPOOL/$TESTFS/$TESTFS2.unmounted
+
+
+# send our snapshot to a known file in /tmp
+zfs send $TESTPOOL/$TESTFS@snap > $TEST_BASE_DIR/zfstest_datastream.dat
+if [ ! -s $TEST_BASE_DIR/zfstest_datastream.dat ]
+then
+ log_fail "ZFS send datafile was not created!"
+fi
+log_must chmod 644 $TEST_BASE_DIR/zfstest_datastream.dat
+
+
+# create a filesystem that has particular properties to test set/get
+log_must zfs create -o version=1 $TESTPOOL/$TESTFS/prop
+set -A props $PROP_NAMES
+set -A prop_vals $PROP_VALS
+typeset -i i=0
+
+while [[ $i -lt ${#props[*]} ]]
+do
+ prop_name=${props[$i]}
+ prop_val=${prop_vals[$i]}
+ log_must zfs set $prop_name=$prop_val $TESTPOOL/$TESTFS/prop
+ i=$(( $i + 1 ))
+done
+
+# create a filesystem we don't mind renaming
+log_must zfs create $TESTPOOL/$TESTFS/renameme
+
+
+if is_global_zone && ! is_linux
+then
+ # create a filesystem we can share
+ log_must zfs create $TESTPOOL/$TESTFS/unshared
+ log_must zfs set sharenfs=off $TESTPOOL/$TESTFS/unshared
+
+ # create a filesystem that we can unshare
+ log_must zfs create $TESTPOOL/$TESTFS/shared
+ log_must zfs set sharenfs=on $TESTPOOL/$TESTFS/shared
+fi
+
+
+log_must zfs create -o version=1 $TESTPOOL/$TESTFS/version1
+log_must zfs create -o version=1 $TESTPOOL/$TESTFS/allowed
+log_must zfs allow everyone create $TESTPOOL/$TESTFS/allowed
+
+if is_global_zone
+then
+
+ # Now create several virtual disks to test zpool with
+
+ mkfile $MINVDEVSIZE $TEST_BASE_DIR/disk1.dat
+ mkfile $MINVDEVSIZE $TEST_BASE_DIR/disk2.dat
+ mkfile $MINVDEVSIZE $TEST_BASE_DIR/disk3.dat
+ mkfile $MINVDEVSIZE $TEST_BASE_DIR/disk-additional.dat
+ mkfile $MINVDEVSIZE $TEST_BASE_DIR/disk-export.dat
+ mkfile $MINVDEVSIZE $TEST_BASE_DIR/disk-offline.dat
+ mkfile $MINVDEVSIZE $TEST_BASE_DIR/disk-spare1.dat
+ mkfile $MINVDEVSIZE $TEST_BASE_DIR/disk-spare2.dat
+
+ # and create a pool we can perform attach remove replace,
+ # etc. operations with
+ log_must zpool create $TESTPOOL.virt mirror $TEST_BASE_DIR/disk1.dat \
+ $TEST_BASE_DIR/disk2.dat $TEST_BASE_DIR/disk3.dat \
+ $TEST_BASE_DIR/disk-offline.dat spare $TEST_BASE_DIR/disk-spare1.dat
+
+
+ # Offline one of the disks to test online
+ log_must zpool offline $TESTPOOL.virt $TEST_BASE_DIR/disk-offline.dat
+
+
+ # create an exported pool to test import
+ log_must zpool create $TESTPOOL.exported $TEST_BASE_DIR/disk-export.dat
+ log_must zpool export $TESTPOOL.exported
+
+ set -A props $POOL_PROPS
+ set -A prop_vals $POOL_VALS
+ typeset -i i=0
+
+ while [[ $i -lt ${#props[*]} ]]
+ do
+ prop_name=${props[$i]}
+ prop_val=${prop_vals[$i]}
+ log_must zpool set $prop_name=$prop_val $TESTPOOL
+ i=$(( $i + 1 ))
+ done
+
+ # copy a v1 pool from cli_root
+ cp $STF_SUITE/tests/functional/cli_root/zpool_upgrade/blockfiles/zfs-pool-v1.dat.bz2 \
+ $TEST_BASE_DIR/
+ log_must bunzip2 $TEST_BASE_DIR/zfs-pool-v1.dat.bz2
+ log_must zpool import -d $TEST_BASE_DIR/ v1-pool
+fi
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zdb_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zdb_001_neg.ksh
new file mode 100755
index 000000000000..3adfc59f51ce
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zdb_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zdb can't run as a user on datasets, but can run without arguments
+#
+# STRATEGY:
+# 1. Run zdb as a user, it should print information
+# 2. Run zdb as a user on different datasets, it should fail
+#
+
+function check_zdb
+{
+ $@ > $TEST_BASE_DIR/zdb.$$
+ grep "Dataset mos" $TEST_BASE_DIR/zdb.$$
+ if [ $? -eq 0 ]
+ then
+ log_fail "$@ exited 0 when run as a non root user!"
+ fi
+ rm $TEST_BASE_DIR/zdb.$$
+}
+
+
+function cleanup
+{
+ rm -f $TEST_BASE_DIR/zdb_001_neg.$$.txt $TEST_BASE_DIR/zdb.$$
+}
+
+verify_runnable "global"
+
+log_assert "zdb can't run as a user on datasets, but can run without arguments"
+log_onexit cleanup
+
+log_must eval "zdb > $TEST_BASE_DIR/zdb_001_neg.$$.txt"
+# verify the output looks okay
+log_must grep pool_guid $TEST_BASE_DIR/zdb_001_neg.$$.txt
+log_must rm $TEST_BASE_DIR/zdb_001_neg.$$.txt
+
+# we shouldn't able to run it on any dataset
+check_zdb zdb $TESTPOOL
+check_zdb zdb $TESTPOOL/$TESTFS
+check_zdb zdb $TESTPOOL/$TESTFS@snap
+check_zdb zdb $TESTPOOL/$TESTFS.clone
+
+log_pass "zdb can't run as a user on datasets, but can run without arguments"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_001_neg.ksh
new file mode 100755
index 000000000000..bfe8cf4bb29a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs shows a usage message when run as a user
+#
+# STRATEGY:
+# 1. Run zfs as a user
+# 2. Verify it produces a usage message
+#
+
+function cleanup
+{
+ rm -f "$TEMPFILE"
+}
+
+log_onexit cleanup
+log_assert "zfs shows a usage message when run as a user"
+
+TEMPFILE="$TEST_BASE_DIR/zfs_001_neg.$$.txt"
+
+zfs > $TEMPFILE 2>&1
+log_must grep "usage: zfs command args" "$TEMPFILE"
+
+log_must eval "awk '{if (length(\$0) > 80) exit 1}' < $TEMPFILE"
+
+log_pass "zfs shows a usage message when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_neg.ksh
new file mode 100755
index 000000000000..56a74e4ae427
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_allow_001_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 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs allow returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Verify that trying to show allows works as a user
+# 2. Verify that trying to set allows fails as a user
+#
+#
+
+# check to see if we have zfs allow
+zfs 2>&1 | grep "allow" > /dev/null
+if (($? != 0)) then
+ log_unsupported "ZFS allow not supported on this machine."
+fi
+
+log_assert "zfs allow returns an error when run as a user"
+
+log_must zfs allow $TESTPOOL/$TESTFS
+log_mustnot zfs allow $(logname) create $TESTPOOL/$TESTFS
+
+# now verify that the above command actually did nothing by
+# checking for any allow output. ( if no allows are granted,
+# nothing should be output )
+OUTPUT=$(zfs allow $TESTPOOL/$TESTFS | grep "Local+Descendent" )
+if [ -n "$OUTPUT" ]
+then
+ log_fail "zfs allow permissions were granted on $TESTPOOL/$TESTFS"
+fi
+
+log_pass "zfs allow returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_neg.ksh
new file mode 100755
index 000000000000..7497553ed8a5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_clone_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs clone returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Verify that we're unable to clone snapshots as a user
+#
+#
+
+log_assert "zfs clone returns an error when run as a user"
+log_mustnot zfs clone $TESTPOOL/$TESTFS@snap $TESTPOOL/$TESTFS.myclone
+
+# check to see that the above command really did nothing
+if datasetexists $TESTPOOL/$TESTFS.myclone
+then
+ log_fail "Dataset $TESTPOOL/$TESTFS.myclone should not exist!"
+fi
+log_pass "zfs clone returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_neg.ksh
new file mode 100755
index 000000000000..aa74bcf40c1f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_create_001_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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+# Executing various badly formed 'zfs create' should fail.
+#
+# STRATEGY:
+# 1. Create an array of badly formed sub-commands.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "both"
+
+
+set -A args "" "create $TESTPOOL/$TESTFS" \
+ "create $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "create $TESTPOOL/$TESTCLCT/$TESTFS" \
+ "create $TESTFS/$TESTPOOL/$TESTCLCT"
+
+log_assert "Verify zfs create without parameters fails."
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zfs ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'create' fails as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_neg.ksh
new file mode 100755
index 000000000000..fabba4f13e9c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_destroy_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zfs destroy' fails as non-root.
+#
+# STRATEGY:
+# 1. Create an array of options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "both"
+
+
+set -A args "destroy" "destroy $TESTPOOL/$TESTFS" \
+ "destroy -f" "destroy -f $TESTPOOL/$TESTFS" \
+ "destroy -r" "destroy -r $TESTPOOL/$TESTFS" \
+ "destroy -rf $TESTPOOL/$TESTFS" \
+ "destroy -fr $TESTPOOL/$TESTFS" \
+ "destroy $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "destroy -f $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "destroy -r $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "destroy -rf $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "destroy -fr $TESTPOOL/$TESTFS@$TESTSNAP"
+
+log_assert "zfs destroy [-f|-r] [fs|snap]"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zfs ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'destroy' fails as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_get_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_get_001_neg.ksh
new file mode 100755
index 000000000000..0657b9143670
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_get_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs get works when run as a user
+#
+# STRATEGY:
+# 1. Run zfs get with an array of different arguments
+# 2. Verify for each property, we get the value that's expected
+#
+
+log_assert "zfs get works when run as a user"
+
+typeset -i i=0
+
+set -A props $PROP_NAMES
+set -A prop_vals $PROP_VALS
+
+while [[ $i -lt ${#props[*]} ]]
+do
+ PROP=${props[$i]}
+ EXPECTED=${prop_vals[$i]}
+ ACTUAL=$(zfs get -H -o value $PROP $TESTPOOL/$TESTFS/prop)
+ if [ "$ACTUAL" != "$EXPECTED" ]
+ then
+ log_fail "Property $PROP value was $ACTUAL, expected $EXPECTED"
+ fi
+ i=$(( $i + 1 ))
+done
+
+log_pass "zfs get works when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.ksh
new file mode 100755
index 000000000000..284c9f76dff1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_inherit_001_neg.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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs inherit returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Verify that we can't inherit a property when running as a user
+#
+#
+
+log_assert "zfs inherit returns an error when run as a user"
+log_mustnot zfs inherit snapdir $TESTPOOL/$TESTFS/$TESTFS2
+
+# check to see that the above command really did nothing
+PROP=$(zfs get snapdir $TESTPOOL/$TESTFS)
+if [ "$PROP" = "visible" ]
+then
+ log_fail "snapdir property inherited from the $TESTPOOL/$TESTFS!"
+fi
+
+log_pass "zfs inherit returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_neg.ksh
new file mode 100755
index 000000000000..8e4c39bfce75
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_mount_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs mount returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Verify that we can't mount the unmounted filesystem created in setup
+#
+#
+
+log_assert "zfs mount returns an error when run as a user"
+
+log_mustnot zfs mount $TESTPOOL/$TESTFS/$TESTFS2.unmounted
+
+# now verify that the above command didn't do anything
+MOUNTED=$(mount | grep $TESTPOOL/$TESTFS/$TESTFS2.unmounted)
+if [ -n "$MOUNTED" ]
+then
+ log_fail "Filesystem $TESTPOOL/$TESTFS/$TESTFS2.unmounted was mounted!"
+fi
+
+log_pass "zfs mount returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.ksh
new file mode 100755
index 000000000000..dd92f534d3a1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_promote_001_neg.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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs promote returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Verify we don't have permissions to promote a clone
+#
+#
+
+log_assert "zfs promote returns an error when run as a user"
+
+log_mustnot zfs promote $TESTPOOL/$TESTFS/clone
+
+# Now verify that the above command didn't do anything
+if datasetexists $TESTPOOL/$TESTFS/clone@snap
+then
+ log_fail "Clone $TESTPOOL/$TESTFS/clone was actually promoted!"
+fi
+
+log_pass "zfs promote returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_neg.ksh
new file mode 100755
index 000000000000..38c11a051028
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_receive_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs receive returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Attempt to receive a datastream as a user
+# 2. Verify that the dataset wasn't created
+#
+
+log_assert "zfs receive returns an error when run as a user"
+
+log_mustnot eval "zfs receive -d $TESTPOOL/$TESTFS/$TESTFS2 \
+ < $TEST_BASE_DIR/zfstest_datastream.dat"
+
+# verify that command actually did nothing
+
+if datasetexists $TESTPOOL/$TESTFS/$TESTFS2/$TESTFS
+then
+ log_fail "$TESTPOOL/$TESTFS/$TESTFS2/$TESTFS was received!"
+fi
+
+log_pass "zfs receive returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.ksh
new file mode 100755
index 000000000000..ac275b01e5f9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rename_001_neg.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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs rename returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to rename a dataset
+# 2. Verify that the renamed dataset does not exist.
+#
+#
+
+log_assert "zfs rename returns an error when run as a user"
+
+log_mustnot zfs rename $TESTPOOL/$TESTFS/renameme $TESTPOOL/$TESTFS/renameme1
+
+# now verify the above command didn't actually do anything
+if datasetexists $TESTPOOL/$TESTFS/renameme1
+then
+ log_fail "The dataset $TESTPOOL/$TESTFS/renameme was renamed!"
+fi
+
+log_pass "zfs rename returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_neg.ksh
new file mode 100755
index 000000000000..51b5162decfc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_rollback_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs rollback returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to rollback a snapshot
+# 2. Verify that a file which doesn't exist in the snapshot still exists
+# (showing the snapshot rollback failed)
+#
+#
+
+log_assert "zfs rollback returns an error when run as a user"
+
+log_mustnot zfs rollback $TESTPOOL/$TESTFS@snap
+
+# now verify the above command didn't actually do anything
+
+# in the above filesystem there's a file that should not exist once
+# the snapshot is rolled back - we check for it
+if [ ! -e /$TESTDIR/file.txt ]
+then
+ log_fail "Rollback of snapshot $TESTPOOL/$TESTFS@snap succeeded!"
+fi
+
+log_pass "zfs rollback returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_neg.ksh
new file mode 100755
index 000000000000..6ecb66a3584c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_send_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs send returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to send a dataset to a file
+# 2. Verify the file created has zero-size
+#
+#
+
+function cleanup
+{
+ if [ -e $TEST_BASE_DIR/zfstest_datastream.$$ ]
+ then
+ log_must rm $TEST_BASE_DIR/zfstest_datastream.$$
+ fi
+}
+
+log_assert "zfs send returns an error when run as a user"
+log_onexit cleanup
+
+log_mustnot eval "zfs send $TESTPOOL/$TESTFS@snap > $TEST_BASE_DIR/zfstest_datastream.$$"
+
+# Now check that the above command actually did nothing
+
+# We should have a non-zero-length file in /tmp
+if [ -s $TEST_BASE_DIR/zfstest_datastream.$$ ]
+then
+ log_fail "A zfs send file was created in $TEST_BASE_DIR/zfstest_datastream.$$ !"
+fi
+
+log_pass "zfs send returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_set_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_set_001_neg.ksh
new file mode 100755
index 000000000000..9cfb79210b11
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_set_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs set returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to set an array of properties on a dataset
+# 2. Verify that those properties were not set and retain their original values.
+#
+
+log_assert "zfs set returns an error when run as a user"
+
+typeset -i i=0
+
+set -A props $PROP_NAMES
+set -A prop_vals $PROP_VALS
+set -A prop_new $PROP_ALTVALS
+
+while [[ $i -lt ${#props[*]} ]]
+do
+ PROP=${props[$i]}
+ EXPECTED=${prop_vals[$i]}
+ NEW=${prop_new[$i]}
+ log_mustnot zfs set $PROP=$NEW $TESTPOOL/$TESTFS/prop
+
+ # Now verify that the above command did nothing
+ ACTUAL=$(zfs get -H -o value $PROP $TESTPOOL/$TESTFS/prop)
+ if [ "$ACTUAL" != "$EXPECTED" ]
+ then
+ log_fail "Property $PROP was set to $ACTUAL, expected $EXPECTED"
+ fi
+ i=$(( $i + 1 ))
+done
+
+log_pass "zfs set returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_neg.ksh
new file mode 100755
index 000000000000..14c35b3da664
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_share_001_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 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs share returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to share a dataset
+# 2. Verify the dataset was not shared.
+#
+#
+
+verify_runnable "global"
+
+if is_linux || is_freebsd; then
+ log_unsupported "Requires additional dependencies"
+fi
+
+log_assert "zfs share returns an error when run as a user"
+
+if is_shared $TESTDIR/unshared
+then
+ log_fail "$TESTPOOL/$TESTFS/unshared was incorrectly shared initially!"
+fi
+
+log_mustnot zfs share $TESTPOOL/$TESTFS/unshared
+
+# Now verify that the above command didn't actually do anything
+if is_shared $TESTDIR/unshared
+then
+ log_fail "$TESTPOOL/$TESTFS/unshared was actually shared!"
+fi
+
+log_pass "zfs share returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.ksh
new file mode 100755
index 000000000000..232d9574b51c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_snapshot_001_neg.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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs snapshot returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to snapshot a dataset
+# 2. Verify the snapshot wasn't taken
+#
+#
+
+log_assert "zfs snapshot returns an error when run as a user"
+
+log_mustnot zfs snapshot $TESTPOOL/$TESTFS@usersnap1
+
+# Now verify that the above command didn't actually do anything
+if datasetexists $TESTPOOL/$TESTFS@usersnap1
+then
+ log_fail "Snapshot $TESTPOOL/$TESTFS@usersnap1 was taken !"
+fi
+
+log_pass "zfs snapshot returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_001_neg.ksh
new file mode 100755
index 000000000000..98383a08762e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unallow_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 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs unallow returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to unallow a set of permissions
+# 2. Verify the unallow wasn't performed
+#
+#
+
+# check to see if we have zfs unallow
+zfs 2>&1 | grep "unallow" > /dev/null
+if (($? != 0)) then
+ log_unsupported "ZFS unallow not supported on this machine."
+fi
+
+log_assert "zfs unallow returns an error when run as a user"
+
+log_mustnot zfs unallow everyone $TESTPOOL/$TESTFS/allowed
+
+# now check with zfs allow to see if the permissions are still there
+OUTPUT=$(zfs allow $TESTPOOL/$TESTFS/allowed | grep "Local+Descendent" )
+if [ -z "$OUTPUT" ]
+then
+ log_fail "Error - create permissions were unallowed on \
+ $TESTPOOL/$TESTFS/allowed"
+fi
+
+log_pass "zfs unallow returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_neg.ksh
new file mode 100755
index 000000000000..5b0a773f15a9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unmount_001_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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zfs umount' and its variants fail as non-root.
+#
+# STRATEGY:
+# 1. Create an array of options.
+# 2. Execute each element of the array.
+# 3. Verify that the commands fail with an error code.
+#
+
+verify_runnable "both"
+
+set -A args "umount" "umount -f" "unmount" "unmount -f" \
+ "umount $TESTPOOL/$TESTFS" "umount -f $TESTPOOL/$TESTFS" \
+ "unmount $TESTPOOL/$TESTFS" "unmount -f $TESTPOOL/$TESTFS" \
+ "umount $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "umount -f $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "unmount $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "unmount -f $TESTPOOL/$TESTFS@$TESTSNAP" \
+ "umount $TESTDIR" "umount -f $TESTDIR" \
+ "unmount $TESTDIR" "unmount -f $TESTDIR"
+
+log_assert "zfs u[n]mount [-f] [mountpoint|fs|snap]"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zfs ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'u[n]mount' fails as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_neg.ksh
new file mode 100755
index 000000000000..7ae86fc4ec76
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_unshare_001_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 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs unshare returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to unshare a shared dataset
+# 2. Verify the dataset is still shared
+#
+#
+
+verify_runnable "global"
+
+if is_linux || is_freebsd; then
+ log_unsupported "Requires additional dependencies"
+fi
+
+log_assert "zfs unshare returns an error when run as a user"
+
+# verify that the filesystem was shared initially
+if not_shared $TESTDIR/shared
+then
+ log_fail "$TESTPOOL/$TESTFS/shared was not shared initially at all!"
+fi
+
+log_mustnot zfs unshare $TESTPOOL/$TESTFS/shared
+
+# now verify that the above command didn't do anything
+if not_shared $TESTDIR/shared
+then
+ log_fail "$TESTPOOL/$TESTFS/shared was actually unshared!"
+fi
+
+log_pass "zfs unshare returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_neg.ksh
new file mode 100755
index 000000000000..fd65feb8c001
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zfs_upgrade_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zfs upgrade returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to upgrade a version1 dataset
+# 2. Verify the dataset wasn't upgraded
+#
+#
+
+# check to see if we have upgrade capability
+zfs upgrade > /dev/null 2>&1
+HAS_UPGRADE=$?
+if [ $HAS_UPGRADE -ne 0 ]
+then
+ log_unsupported "Zfs upgrade not supported"
+fi
+
+log_assert "zfs upgrade returns an error when run as a user"
+
+
+log_mustnot zfs upgrade $TESTPOOL/$TESTFS/version1
+
+# now check to see the above command didn't do anything
+VERSION=$(zfs upgrade $TESTPOOL/$TESTFS/version1 2>&1 \
+ | grep "already at this version")
+if [ -n "$VERSION" ]
+then
+ log_fail "A filesystem was upgraded!"
+fi
+
+log_pass "zfs upgrade returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_001_neg.ksh
new file mode 100755
index 000000000000..0fddc08b25db
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool shows a usage message when run as a user
+#
+# STRATEGY:
+# 1. Run the zpool command
+# 2. Verify that a usage message is produced
+#
+#
+
+function cleanup
+{
+ if [ -e "$TEMPFILE" ]
+ then
+ rm -f "$TEMPFILE"
+ fi
+}
+
+TEMPFILE="$TEST_BASE_DIR/zpool_001_neg.$$.txt"
+
+log_onexit cleanup
+log_assert "zpool shows a usage message when run as a user"
+
+eval "zpool > $TEMPFILE 2>&1"
+log_must grep "usage: zpool command args" "$TEMPFILE"
+
+log_must eval "awk '{if (length(\$0) > 80) exit 1}' < $TEMPFILE"
+
+log_pass "zpool shows a usage message when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_neg.ksh
new file mode 100755
index 000000000000..7bcd911543ed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_add_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zpool add' fails as non-root.
+#
+# STRATEGY:
+# 1. Create an array of options.
+# 2. Execute each element of the array.
+# 3. Verify that an error is returned.
+#
+
+verify_runnable "global"
+
+ADD_DISK="${DISKS%% }"
+ADD_DISK="${ADD_DISK##* }"
+
+[[ -z $ADD_DISK ]] && \
+ log_fail "No spare disks available."
+
+# Under Linux dry-run commands have no legitimate reason to fail.
+if is_linux; then
+ set -A args "add" "add -f" "add -n" \
+ "add $TESTPOOL" "add -f $TESTPOOL" "add -n $TESTPOOL" \
+ "add -fn $TESTPOOL" "add -nf $TESTPOOL" \
+ "add $TESTPOOL $ADD_DISK" "add -f $TESTPOOL $ADD_DISK"
+else
+ set -A args "add" "add -f" "add -n" \
+ "add $TESTPOOL" "add -f $TESTPOOL" "add -n $TESTPOOL" \
+ "add -fn $TESTPOOL" "add -nf $TESTPOOL" \
+ "add $TESTPOOL $ADD_DISK" "add -f $TESTPOOL $ADD_DISK" \
+ "add -n $TESTPOOL $ADD_DISK" \
+ "add -fn $TESTPOOL $ADD_DISK" \
+ "add -nf $TESTPOOL $ADD_DISK"
+fi
+
+log_assert "zpool add [-fn] pool_name vdev"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'add' and its options fail as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_neg.ksh
new file mode 100755
index 000000000000..b0fadca8c9fe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_attach_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool attach returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to attach a disk to a pool
+# 2.Verify that the attach failed
+#
+#
+
+function check_for_attach
+{
+ RESULT=$(zpool status -v $TESTPOOL.virt | grep disk-additional.dat)
+ if [ -n "$RESULT" ]
+ then
+ log_fail "A disk was attached to the pool!"
+ fi
+}
+
+verify_runnable "global"
+
+log_assert "zpool attach returns an error when run as a user"
+
+log_mustnot zpool attach $TESTPOOL.virt /$TESTDIR/disk1.dat \
+ /$TESTDIR/disk-additional.dat
+check_for_attach
+
+log_mustnot zpool attach -f $TESTPOOL.virt /$TESTDIR/disk1.dat \
+ /$TESTDIR/disk-additional.dat
+check_for_attach
+
+log_pass "zpool attach returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.ksh
new file mode 100755
index 000000000000..5d6ef5ff3e4d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_clear_001_neg.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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool clear returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Attempt to clear errors on a zpool
+# 2. Verify that the command fails
+#
+
+verify_runnable "global"
+
+log_assert "zpool clear returns an error when run as a user"
+
+log_mustnot zpool clear $TESTPOOL
+
+log_pass "zpool clear returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_neg.ksh
new file mode 100755
index 000000000000..77d08ee39009
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_create_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zpool create' fails as a non-root user.
+#
+# STRATEGY:
+# 1. Create an array of options.
+# 2. Execute each element of the array.
+# 3. Verify that an error is returned.
+#
+
+verify_runnable "global"
+
+ADD_DISK="${DISKS%% }"
+ADD_DISK="${ADD_DISK##* }"
+
+[[ -z $ADD_DISK ]] && \
+ log_fail "No spare disks available."
+
+# Under Linux dry-run commands have no legitimate reason to fail.
+if is_linux; then
+ set -A args "create" "create -f" "create -n" \
+ "create $TESTPOOL" "create -f $TESTPOOL" "create -n $TESTPOOL" \
+ "create -fn $TESTPOOL" "create -nf $TESTPOOL" \
+ "create $TESTPOOL $ADD_DISK" "create -f $TESTPOOL $ADD_DISK"
+else
+ set -A args "create" "create -f" "create -n" \
+ "create $TESTPOOL" "create -f $TESTPOOL" "create -n $TESTPOOL" \
+ "create -fn $TESTPOOL" "create -nf $TESTPOOL" \
+ "create $TESTPOOL $ADD_DISK" "create -f $TESTPOOL $ADD_DISK" \
+ "create -n $TESTPOOL $ADD_DISK" \
+ "create -fn $TESTPOOL $ADD_DISK" \
+ "create -nf $TESTPOOL $ADD_DISK"
+fi
+
+log_assert "zpool create [-fn] pool_name vdev"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'create' and its options fail as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_neg.ksh
new file mode 100755
index 000000000000..acc93fe74826
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_destroy_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+# Verify that 'zpool destroy' fails as non-root.
+#
+# STRATEGY:
+# 1. Create an array of options.
+# 2. Execute each element of the array.
+# 3. Verify an error is returned.
+#
+
+verify_runnable "global"
+
+set -A args "destroy" "destroy -f" \
+ "destroy $TESTPOOL" "destroy -f $TESTPOOL" \
+ "destroy $TESTPOOL $TESTPOOL"
+
+log_assert "zpool destroy [-f] [pool_name ...]"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'destroy' and its options fail as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_neg.ksh
new file mode 100755
index 000000000000..dbc540cebbe7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_detach_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool detach returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Attempt to detach a device from a pool
+# 2. Verify the command fails
+#
+
+verify_runnable "global"
+
+log_assert "zpool detach returns an error when run as a user"
+
+log_mustnot zpool detach $TESTPOOL.virt /$TESTDIR/disk1.dat
+
+RESULT=$(zpool status -v $TESTPOOL.virt | grep disk1.dat)
+if [ -z "$RESULT" ]
+then
+ log_fail "A disk was detached from the pool!"
+fi
+
+log_pass "zpool detach returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_neg.ksh
new file mode 100755
index 000000000000..9bca4668d3d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_export_001_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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool export returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to export a pool
+# 2. Verify the command fails
+#
+
+function check_for_export
+{
+ RESULT=$(zpool list | grep $TESTPOOL.virt )
+ if [ -z "$RESULT" ]
+ then
+ log_fail "A pool was exported!"
+ fi
+
+}
+
+verify_runnable "global"
+
+log_assert "zpool export returns an error when run as a user"
+
+log_mustnot zpool export $TESTPOOL.virt
+check_for_export
+
+log_mustnot zpool export -f $TESTPOOL.virt
+check_for_export
+
+log_pass "zpool export returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_neg.ksh
new file mode 100755
index 000000000000..7415cebf236b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_get_001_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 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool get works when run as a user
+#
+# STRATEGY:
+#
+# 1. For each property, get that property
+# 2. Verify the property was the same as that set in setup
+#
+
+verify_runnable "global"
+
+log_assert "zpool get works when run as a user"
+
+set -A props $POOL_PROPS
+set -A prop_vals $POOL_VALS
+
+while [[ $i -lt ${#args[*]} ]]
+do
+ PROP=${props[$i]}
+ EXPECTED=${prop_vals[$i]}
+ ACTUAL=$( zpool get $PROP $TESTPOOL | grep $PROP | awk '{print $1}' )
+ if [ "$ACTUAL" != "$EXPECTED" ]
+ then
+ log_fail "Property $PROP value was $ACTUAL, expected $EXPECTED"
+ fi
+ i=$(( $i + 1 ))
+done
+
+log_must zpool get all $TESTPOOL
+
+log_pass "zpool get works when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.ksh
new file mode 100755
index 000000000000..47082e3524e3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_history_001_neg.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 2007 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_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool history works when run as a user
+#
+# STRATEGY:
+# 1. Attempt to get history on a test pool
+# 2. Verify the command fails
+#
+
+verify_runnable "global"
+
+log_assert "zpool history returns an error when run as a user"
+
+log_mustnot zpool history
+log_mustnot zpool history $TESTPOOL
+log_mustnot zpool history -i $TESTPOOL
+log_mustnot zpool history -l $TESTPOOL
+log_mustnot zpool history -il $TESTPOOL
+
+log_assert "zpool history returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_neg.ksh
new file mode 100755
index 000000000000..09fd775ff4cc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool import returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to import an exported pool
+# 2. Verify the command fails
+#
+#
+
+function check_for_import
+{
+ RESULT=$(zpool list -H -o name | grep $TESTPOOL.exported)
+ if [ -n "$RESULT" ]
+ then
+ log_fail "Pool $TESTPOOL.export was successfully imported!"
+ fi
+}
+
+verify_runnable "global"
+
+log_assert "zpool import returns an error when run as a user"
+log_mustnot zpool import
+
+log_mustnot zpool import -a
+check_for_import
+
+log_mustnot zpool import -d /$TESTDIR $TESTPOOL.exported
+check_for_import
+
+log_pass "zpool import returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_neg.ksh
new file mode 100755
index 000000000000..f3460186725c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_import_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+# Executing 'zpool import' as regular user should denied.
+#
+# STRATEGY:
+# 1. Create an array of options try to detect exported/destroyed pools.
+# 2. Execute 'zpool import' with each element of the array by regular user.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "both"
+
+typeset testpool
+if is_global_zone ; then
+ testpool=$TESTPOOL.exported
+else
+ testpool=${TESTPOOL%%/*}
+fi
+
+set -A args "" "-D" "-Df" "-f" "-f $TESTPOOL" "-Df $TESTPOOL" "-a"
+
+log_assert "Executing 'zpool import' by regular user fails"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool import ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Executing 'zpool import' by regular user fails as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_neg.ksh
new file mode 100755
index 000000000000..523883c6f0dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_offline_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool offline returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to offline a device in a pool
+# 2. Verify that the command fails
+#
+#
+
+function check_for_offline
+{
+ RESULT=$(zpool status -v $TESTPOOL.virt | grep disk-1.dat \
+ | grep OFFLINE )
+ if [ -n "$RESULT" ]
+ then
+ log_fail "A disk was taken offline!"
+ fi
+}
+
+verify_runnable "global"
+
+log_assert "zpool offline returns an error when run as a user"
+
+log_mustnot zpool offline $TESTPOOL.virt /$TESTDIR/disk-1.dat
+check_for_offline
+
+log_mustnot zpool offline -t $TESTPOOL.virt /$TESTDIR/disk-1.dat
+check_for_offline
+
+log_pass "zpool offline returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_neg.ksh
new file mode 100755
index 000000000000..cd290515357f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_online_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool online returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to online a device in a pool
+# 2. Verify the command fails
+#
+#
+
+function check_for_online
+{
+ RESULT=$(zpool status -v $TESTPOOL.virt | grep disk-offline.dat \
+ | grep ONLINE )
+ if [ -n "$RESULT" ]
+ then
+ log_fail "A disk was brought online!"
+ fi
+}
+
+verify_runnable "global"
+
+log_assert "zpool online returns an error when run as a user"
+
+log_mustnot zpool online $TESTPOOL.virt /$TESTDIR/disk-offline.dat
+check_for_online
+
+log_mustnot zpool online -t $TESTPOOL.virt /$TESTDIR/disk-offline.dat
+check_for_online
+
+log_pass "zpool online returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_neg.ksh
new file mode 100755
index 000000000000..1168e6bdac9f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_remove_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool remove returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to remove a device from a pool
+# 2. Verify the command fails
+#
+#
+
+verify_runnable "global"
+
+log_assert "zpool remove returns an error when run as a user"
+
+log_mustnot zpool remove $TESTPOOL.virt /$TESTDIR/disk-spare1.dat
+
+RESULT=$(zpool status -v $TESTPOOL.virt | grep disk-spare1.dat)
+if [ -z "$RESULT" ]
+then
+ log_fail "A disk was removed from the pool!"
+fi
+
+
+log_pass "zpool remove returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_neg.ksh
new file mode 100755
index 000000000000..6211e6575540
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_replace_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool replace returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to replace a device in a pool
+# 2. Verify the command fails
+#
+#
+
+function check_for_replace
+{
+ sleep 10
+ RESULT=$(zpool status -v $TESTPOOL.virt | grep disk-additional.dat)
+ if [ -n "$RESULT" ]
+ then
+ log_fail "A disk was replaced in the pool!"
+ fi
+}
+
+verify_runnable "global"
+
+log_assert "zpool replace returns an error when run as a user"
+
+log_mustnot zpool replace $TESTPOOL.virt /$TESTDIR/disk-1.dat \
+ /$TESTDIR/disk-additional.dat
+check_for_replace
+
+log_mustnot zpool replace -f $TESTPOOL.virt /$TESTDIR/disk-1.dat \
+ /$TESTDIR/disk-additional.dat
+check_for_replace
+
+log_pass "zpool replace returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.ksh
new file mode 100755
index 000000000000..bf9ee4cfadb0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_scrub_001_neg.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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2017 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool scrub returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to start a scrub on a pool
+# 2. Verify the command fails
+#
+#
+
+verify_runnable "global"
+
+log_assert "zpool scrub returns an error when run as a user"
+
+log_mustnot zpool scrub $TESTPOOL
+log_mustnot zpool scrub -p $TESTPOOL
+log_mustnot zpool scrub -s $TESTPOOL
+
+log_pass "zpool scrub returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_neg.ksh
new file mode 100755
index 000000000000..941e20c0010e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_set_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool set returns an error when run as a user
+#
+# STRATEGY:
+# 1. Attempt to set some properties on a pool
+# 2. Verify the command fails
+#
+#
+
+verify_runnable "global"
+
+log_assert "zpool set returns an error when run as a user"
+
+set -A props $POOL_NAMES
+set -A prop_vals $POOL_VALS
+set -A prop_new $POOL_ALTVALS
+
+while [[ $i -lt ${#args[*]} ]]
+do
+ PROP=${props[$i]}
+ EXPECTED=${prop_vals[$i]}
+ NEW=${prop_new[$i]}
+ log_mustnot $POOL set $PROP=$NEW $TESTPOOL
+
+ # Now verify that the above command did nothing
+ ACTUAL=$( zpool get $PROP $TESTPOOL | grep $PROP | awk '{print $1}' )
+ if [ "$ACTUAL" != "$EXPECTED" ]
+ then
+ log_fail "Property $PROP was set to $ACTUAL, expected $EXPECTED"
+ fi
+ i=$(( $i + 1 ))
+done
+
+
+log_pass "zpool set returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh
new file mode 100755
index 000000000000..9cd811a5487c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_status_001_neg.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool status works when run as a user
+#
+# STRATEGY:
+#
+# 1. Run zpool status as a user
+# 2. Verify we get output
+#
+
+function check_pool_status
+{
+ RESULT=$(grep "pool:" $TEST_BASE_DIR/pool-status.$$)
+ if [ -z "$RESULT" ]
+ then
+ log_fail "No pool: string found in zpool status output!"
+ fi
+ rm $TEST_BASE_DIR/pool-status.$$
+}
+
+verify_runnable "global"
+
+log_assert "zpool status works when run as a user"
+
+log_must eval "zpool status > $TEST_BASE_DIR/pool-status.$$"
+check_pool_status
+
+log_must eval "zpool status -v > $TEST_BASE_DIR/pool-status.$$"
+check_pool_status
+
+log_must eval "zpool status $TESTPOOL> $TEST_BASE_DIR/pool-status.$$"
+check_pool_status
+
+log_must eval "zpool status -v $TESTPOOL > $TEST_BASE_DIR/pool-status.$$"
+check_pool_status
+
+log_pass "zpool status works when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_001_neg.ksh
new file mode 100755
index 000000000000..aa380010574f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_upgrade_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_user/misc/misc.cfg
+
+#
+# DESCRIPTION:
+#
+# zpool upgrade returns an error when run as a user
+#
+# STRATEGY:
+#
+# 1. Attempt to upgrade a pool
+# 2. Verify the command fails
+#
+
+verify_runnable "global"
+
+log_assert "zpool upgrade returns an error when run as a user"
+
+# zpool upgrade returns 0 when it can't do anything
+log_must zpool upgrade $TESTPOOL.virt
+
+# Now try to upgrade our version 1 pool
+log_mustnot zpool upgrade v1-pool
+
+# if the pool has been upgraded, then v1-pool won't be listed in the output
+# of zpool upgrade anymore
+RESULT=$(zpool upgrade | grep v1-pool)
+if [ -z "$RESULT" ]
+then
+ log_fail "A pool was upgraded successfully!"
+fi
+
+log_pass "zpool upgrade returns an error when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/misc/zpool_wait_privilege.ksh b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_wait_privilege.ksh
new file mode 100755
index 000000000000..42a2dd2c63ee
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/misc/zpool_wait_privilege.ksh
@@ -0,0 +1,35 @@
+#!/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) 2019 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# zpool wait works when run as an unprivileged user
+#
+
+verify_runnable "global"
+
+log_must zpool wait $TESTPOOL
+
+# Make sure printing status works as unprivileged user.
+output=$(zpool wait -H $TESTPOOL 1) || \
+ log_fail "'zpool wait -H $TESTPOOL 1' failed"
+# There should be one line of status output in a pool with no activity.
+log_must eval '[[ $(wc -l <<<$output) -ge 1 ]]'
+
+log_pass "zpool wait works when run as a user"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/Makefile.am b/tests/zfs-tests/tests/functional/cli_user/zfs_list/Makefile.am
new file mode 100644
index 000000000000..8393072af225
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_user/zfs_list
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zfs_list_001_pos.ksh \
+ zfs_list_002_pos.ksh \
+ zfs_list_003_pos.ksh \
+ zfs_list_004_neg.ksh \
+ zfs_list_007_pos.ksh \
+ zfs_list_008_neg.ksh
+
+dist_pkgdata_DATA = \
+ zfs_list.cfg \
+ zfs_list.kshlib
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/cleanup.ksh
new file mode 100755
index 000000000000..115e00c47be5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+
+depth_fs_cleanup
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/setup.ksh
new file mode 100755
index 000000000000..b4c588282ff7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/setup.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+. $STF_SUITE/tests/functional/cli_user/zfs_list/zfs_list.cfg
+
+DISK=${DISKS%% *}
+
+default_setup_noexit $DISK
+
+# create datasets and set checksum options
+set -A cksumarray $CKSUMOPTS
+typeset -i index=0
+for dataset in $DATASETS
+do
+ log_must zfs create $TESTPOOL/$TESTFS/$dataset
+ sleep 1
+ log_must zfs snapshot $TESTPOOL/$TESTFS/${dataset}@snap
+
+ sleep 1
+ if is_global_zone ; then
+ log_must zfs create -V 64M $TESTPOOL/$TESTFS/${dataset}-vol
+ sleep 1
+ log_must zfs snapshot $TESTPOOL/$TESTFS/${dataset}-vol@snap
+ fi
+
+ # sleep to ensure that the datasets have different creation dates
+ sleep 1
+ log_must zfs set checksum=${cksumarray[$index]} \
+ $TESTPOOL/$TESTFS/$dataset
+ if datasetexists $TESTPOOL/$TESTFS/${dataset}-vol; then
+ log_must zfs set checksum=${cksumarray[$index]} \
+ $TESTPOOL/$TESTFS/${dataset}-vol
+ fi
+
+ index=$((index + 1))
+done
+
+depth_fs_setup
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.cfg b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.cfg
new file mode 100644
index 000000000000..59f367cfa544
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.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) 2013 by Delphix. All rights reserved.
+#
+
+# Datasets (in order of creation date) and which checksum options
+# we want to set for each dataset.
+# These are used by various zfs list tests
+export DATASETS="Apple Banana Carrot Orange apple banana carrot"
+export CKSUMOPTS="on sha256 sha256 sha256 fletcher4 off fletcher2"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib
new file mode 100644
index 000000000000..03c9d1f07a87
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list.kshlib
@@ -0,0 +1,118 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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
+
+#
+# A function that verifies sort order. It takes as input
+# a command, which gets executed. We then iterate over the results
+# comparing that the sort order passed in via the list
+#
+function verify_sort { # command list name
+
+ # now verify we've sorted by creation date:
+ typeset CMD=$1
+ typeset list=$2
+ typeset name=$3
+
+ typeset -i RET=0
+ typeset -i index=1
+
+ # run the command to verify that it works
+ log_must eval "$CMD > /dev/null"
+
+ # Now check the sort order
+ for dataset in $( $CMD )
+ do
+ ACTUAL=$(basename $dataset)
+ if [ "$dataset" != "$TESTPOOL/$TESTFS" ]
+ then
+ EXPECTED=$(echo $list | awk "{print \$$index}")
+ if [ "$ACTUAL" != "$EXPECTED" ]
+ then
+ log_note "WARNING:" \
+ "'$ACTUAL' does not equal '$EXPECTED'"
+ log_fail "ERROR: Sort by $name fails."
+ fi
+
+ ((index = index + 1))
+ fi
+ done
+
+ # finally check to see if we have the expected number of elements
+ if [ $index -ne $(echo $list | awk '{print split($0,arr)+1}') ]
+ then
+ log_fail "Warning: " \
+ "unexpected number of filesystems found in list output!"
+ fi
+}
+
+# A function that verifies reverse sort order. It takes as input
+# a command, which gets executed. We then iterate over the results
+# comparing that the sort order passed in via the list
+#
+function verify_reverse_sort { # command list name
+
+ typeset CMD=$1
+ typeset list=$2
+ typeset name=$3
+
+ # set our index to the be number of elements in the list
+ typeset -i index=$(echo $list | awk '{print split($0,arr)}')
+
+ log_note "Checking reverse sort by '$name'," \
+ "expecting the reverse of '$list'"
+ log_must eval "$CMD > /dev/null"
+
+ for dataset in $( $CMD )
+ do
+ ACTUAL=$(basename $dataset)
+ if [ "$dataset" != "$TESTPOOL/$TESTFS" ]
+ then
+ EXPECTED=$(echo $list | awk "{print \$$index}")
+ if [ "$ACTUAL" != "$EXPECTED" ]
+ then
+ log_note "Warning:" \
+ "'$ACTUAL' does not equal to" \
+ "the reverse of '$EXPECTED'"
+ log_fail "ERROR: Reverse sort by '$name' fails."
+ fi
+
+ ((index = index - 1))
+ fi
+ done
+
+ # finally check to see if we have the expected number of elements
+ if [ $index -ne 0 ]
+ then
+ log_fail "Warning: " \
+ "unexpected number of filesystems found in list output!"
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_001_pos.ksh
new file mode 100755
index 000000000000..5d995a79ba33
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+
+#
+# DESCRIPTION:
+# Executing well-formed 'zfs list' commands should return success.
+#
+# STRATEGY:
+# 1. Create an array of valid options.
+# 2. Execute each element in the array.
+# 3. Verify success is returned.
+#
+
+verify_runnable "both"
+
+set -A args "list" "list -r" "list -H" \
+ "list $TESTPOOL/$TESTFS" \
+ "list -r $TESTPOOL/$TESTFS" "list -H $TESTPOOL/$TESTFS" \
+ "list -rH $TESTPOOL/$TESTFS" "list -Hr $TESTPOOL/$TESTFS" \
+ "list -o name $TESTPOOL/$TESTFS" "list -r -o name $TESTPOOL/$TESTFS" \
+ "list -H -o name $TESTPOOL/$TESTFS" "list -rH -o name $TESTPOOL/$TESTFS" \
+ "list -Hr -o name $TESTPOOL/$TESTFS"
+
+set -A d_args " " "-r" "-H" \
+ "$TESTPOOL/$TESTFS" \
+ "-r $TESTPOOL/$TESTFS" "-H $TESTPOOL/$TESTFS" \
+ "-rH $TESTPOOL/$TESTFS" "-Hr $TESTPOOL/$TESTFS" \
+ "-o name $TESTPOOL/$TESTFS" "-r -o name $TESTPOOL/$TESTFS" \
+ "-H -o name $TESTPOOL/$TESTFS" "-rH -o name $TESTPOOL/$TESTFS" \
+ "-Hr -o name $TESTPOOL/$TESTFS"
+
+typeset -i m=${#args[*]}
+typeset -i n=0
+typeset -i k=0
+while (( n<${#depth_options[*]} ));
+do
+ (( k=0 ))
+ while (( k<${#d_args[*]} ));
+ do
+ args[$m]="list"" -${depth_options[$n]}"" ${d_args[$k]}"
+ (( k+=1 ))
+ (( m+=1 ))
+ done
+ (( n+=1 ))
+done
+
+set -A pathargs "list -r $TESTDIR" "list -H $TESTDIR" \
+ "list -r ./../$TESTDIR" "list -H ./../$TESTDIR"
+
+set -A d_pathargs " $TESTDIR" "-r $TESTDIR" "-H $TESTDIR" \
+ "-r ./../$TESTDIR" "-H ./../$TESTDIR"
+
+(( m=${#pathargs[*]} ))
+(( n=0 ))
+(( k=0 ))
+while (( n<${#depth_options[*]} ));
+do
+ (( k=0 ))
+ while (( k<${#d_pathargs[*]} ));
+ do
+ pathargs[$m]="list"" -${depth_options[$n]}"" ${d_pathargs[$k]}"
+ (( k+=1 ))
+ (( m+=1 ))
+ done
+ (( n+=1 ))
+done
+
+log_assert "Verify 'zfs list [-rH] [-o property[,prop]*] [fs|clct|vol]'."
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_must eval "zfs ${args[i]} > /dev/null"
+ ((i = i + 1))
+done
+
+# Verify 'zfs list <path>' will succeed on absolute or relative path.
+
+cd /tmp
+typeset -i i=0
+while [[ $i -lt ${#pathargs[*]} ]]; do
+ log_must eval "zfs ${pathargs[i]} > /dev/null"
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'list' succeeds as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_pos.ksh
new file mode 100755
index 000000000000..382b2cb7f0b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_user/zfs_list/zfs_list.kshlib
+
+#
+# DESCRIPTION:
+# The sort functionality in 'zfs list' works as expected.
+#
+# STRATEGY:
+# 1. Using several zfs datasets with names, creation dates, checksum options
+# 2. Sort the datasets by name, checksum options, creation date.
+# 3. Verify that the datasets are sorted correctly.
+#
+
+verify_runnable "both"
+
+# datasets ordered by name
+fs_name="Apple Banana Carrot Orange apple banana carrot"
+vol_name="Apple-vol Banana-vol Carrot-vol Orange-vol apple-vol"
+vol_name="$vol_name banana-vol carrot-vol"
+if is_global_zone ; then
+ snap_name="Apple-vol@snap Apple@snap Banana-vol@snap Banana@snap"
+ snap_name="$snap_name Carrot-vol@snap Carrot@snap Orange-vol@snap Orange@snap"
+ snap_name="$snap_name apple-vol@snap apple@snap banana-vol@snap banana@snap"
+ snap_name="$snap_name carrot-vol@snap carrot@snap"
+else
+ snap_name="Apple@snap Banana@snap"
+ snap_name="$snap_name Carrot@snap Orange@snap"
+ snap_name="$snap_name apple@snap banana@snap"
+ snap_name="$snap_name carrot@snap"
+fi
+
+fs_creation=$fs_name
+vol_creation=$vol_name
+if is_global_zone ; then
+ snap_creation="Apple@snap Apple-vol@snap Banana@snap Banana-vol@snap"
+ snap_creation="$snap_creation Carrot@snap Carrot-vol@snap Orange@snap Orange-vol@snap"
+ snap_creation="$snap_creation apple@snap apple-vol@snap banana@snap banana-vol@snap"
+ snap_creation="$snap_creation carrot@snap carrot-vol@snap"
+else
+ snap_creation="Apple@snap Banana@snap"
+ snap_creation="$snap_creation Carrot@snap Orange@snap"
+ snap_creation="$snap_creation apple@snap banana@snap"
+ snap_creation="$snap_creation carrot@snap"
+fi
+
+#
+# datsets ordered by checksum options (note, Orange, Carrot & Banana have the
+# same checksum options, so ZFS should revert to sorting them alphabetically by
+# name)
+#
+fs_cksum="carrot apple banana Apple Banana Carrot Orange"
+vol_cksum="carrot-vol apple-vol banana-vol Apple-vol Banana-vol"
+vol_cksum="$vol_cksum Carrot-vol Orange-vol"
+snap_cksum=$snap_creation
+
+fs_rev_cksum="carrot apple banana Apple Orange Carrot Banana"
+vol_rev_cksum="carrot-vol apple-vol banana-vol Apple-vol Orange-vol"
+vol_rev_cksum="$vol_rev_cksum Carrot-vol Banana-vol"
+
+log_assert "The sort functionality in 'zfs list' works as expected."
+
+#
+# we must be in the C locale here, as running in other locales
+# will make zfs use that locale's sort order.
+#
+LC_ALL=C; export LC_ALL
+
+# sort by creation
+verify_sort \
+ "zfs list -H -r -o name -s creation -t filesystem $TESTPOOL/$TESTFS" \
+ "$fs_creation" "creation date"
+if is_global_zone ; then
+ verify_sort \
+ "zfs list -H -r -o name -s creation -t volume $TESTPOOL/$TESTFS" \
+ "$vol_creation" "creation date"
+fi
+verify_sort \
+ "zfs list -H -r -o name -s creation -t snapshot $TESTPOOL/$TESTFS" \
+ "$snap_creation" "creation date"
+
+# sort by checksum
+verify_sort \
+ "zfs list -H -r -o name -s checksum -t filesystem $TESTPOOL/$TESTFS" \
+ "$fs_cksum" "checksum"
+if is_global_zone ; then
+ verify_sort \
+ "zfs list -H -r -o name -s checksum -t volume $TESTPOOL/$TESTFS" \
+ "$vol_cksum" "checksum"
+fi
+verify_sort \
+ "zfs list -H -r -o name -s checksum -t snapshot $TESTPOOL/$TESTFS" \
+ "$snap_cksum" "checksum"
+verify_sort \
+ "zfs list -H -r -o name -S checksum -t snapshot $TESTPOOL/$TESTFS" \
+ "$snap_cksum" "checksum"
+
+# sort by name
+verify_sort \
+ "zfs list -H -r -o name -s name -t filesystem $TESTPOOL/$TESTFS" \
+ "$fs_name" "name"
+if is_global_zone ; then
+ verify_sort \
+ "zfs list -H -r -o name -s name -t volume $TESTPOOL/$TESTFS" \
+ "$vol_name" "name"
+fi
+verify_sort \
+ "zfs list -H -r -o name -s name -t snapshot $TESTPOOL/$TESTFS" \
+ "$snap_name" "name"
+
+# reverse sort by creation
+verify_reverse_sort \
+ "zfs list -H -r -o name -S creation -t filesystem $TESTPOOL/$TESTFS" \
+ "$fs_creation" "creation date"
+if is_global_zone ; then
+ verify_reverse_sort \
+ "zfs list -H -r -o name -S creation -t volume $TESTPOOL/$TESTFS" \
+ "$vol_creation" "creation date"
+fi
+verify_reverse_sort \
+ "zfs list -H -r -o name -S creation -t snapshot $TESTPOOL/$TESTFS" \
+ "$snap_creation" "creation date"
+
+# reverse sort by checksum
+verify_reverse_sort \
+ "zfs list -H -r -o name -S checksum -t filesystem $TESTPOOL/$TESTFS" \
+ "$fs_rev_cksum" "checksum"
+if is_global_zone ; then
+ verify_reverse_sort \
+ "zfs list -H -r -o name -S checksum -t volume $TESTPOOL/$TESTFS" \
+ "$vol_rev_cksum" "checksum"
+fi
+
+# reverse sort by name
+verify_reverse_sort \
+ "zfs list -H -r -o name -S name -t filesystem $TESTPOOL/$TESTFS"\
+ "$fs_name" "name"
+if is_global_zone ; then
+ verify_reverse_sort \
+ "zfs list -H -r -o name -S name -t volume $TESTPOOL/$TESTFS"\
+ "$vol_name" "name"
+fi
+verify_reverse_sort \
+ "zfs list -H -r -o name -S name -t snapshot $TESTPOOL/$TESTFS"\
+ "$snap_name" "name"
+
+log_pass "The sort functionality in 'zfs list' works as expected."
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_003_pos.ksh
new file mode 100755
index 000000000000..43cfd0cf2101
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_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 2007 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
+
+#
+# DESCRIPTION:
+# Verify 'zfs list -r' could recursively display any children
+# of the dataset.
+#
+# STRATEGY:
+# 1. Prepare a set of datasets by hierarchy.
+# 2. Execute 'zfs list -r' at the top of these datasets.
+# 3. Verify all child datasets are all be shown.
+#
+
+function cleanup
+{
+ if [[ -f $tmpfile ]]; then
+ rm -f $tmpfile
+ fi
+}
+
+verify_runnable "both"
+log_onexit cleanup
+
+log_assert "Verify 'zfs list -r' could display any children recursively."
+
+tmpfile=$TEST_BASE_DIR/zfslist.out.$$
+children="$TESTPOOL/$TESTFS"
+
+for fs in $DATASETS ; do
+ children="$children $TESTPOOL/$TESTFS/$fs"
+done
+
+cd /tmp
+
+for path in $TESTPOOL/$TESTFS $TESTDIR ./../$TESTDIR ; do
+ zfs list -rH -o name $path > $tmpfile
+ for fs in $children ; do
+ grep "^${fs}$" $tmpfile > /dev/null 2>&1
+ if (( $? != 0 )); then
+ log_fail "$fs not shown in the output list."
+ fi
+ done
+done
+
+log_pass "'zfs list -r' could display any children recursively."
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_neg.ksh
new file mode 100755
index 000000000000..5d1114dacfa1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_004_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs list [-r]' should fail while
+# * the given dataset does not exist
+# * the given path does not exist.
+# * the given path does not belong to zfs.
+#
+# STRATEGY:
+# 1. Create an array of invalid options.
+# 2. Execute each element in the array.
+# 3. Verify failure is returned.
+#
+
+verify_runnable "both"
+
+log_assert "Verify 'zfs list [-r]' should fail while the given " \
+ "dataset/path does not exist or not belong to zfs."
+
+paths="$TESTPOOL/NONEXISTFS $TESTPOOL/$TESTFS/NONEXISTFS \
+ /$TESTDIR/NONEXISTFS /devices /tmp ./../devices ./../tmp"
+
+cd /tmp
+
+for fs in $paths ; do
+ log_mustnot zfs list $fs
+ log_mustnot zfs list -r $fs
+done
+
+log_pass "'zfs list [-r]' fails while the given dataset/path does not exist " \
+ "or not belong to zfs."
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_007_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_007_pos.ksh
new file mode 100755
index 000000000000..8e9009bd5500
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zfs_get/zfs_get_list_d.kshlib
+
+#
+# DESCRIPTION:
+# 'zfs list -d <n>' should get expected output.
+#
+# STRATEGY:
+# 1. 'zfs list -d <n>' to get the output.
+# 2. 'zfs list -r|egrep' to get the expected output.
+# 3. Compare the two outputs, they should be same.
+#
+
+verify_runnable "both"
+
+set -A fs_type "all" "filesystem" "snapshot"
+if is_global_zone ; then
+ set -A fs_type ${fs_type[*]} "volume"
+fi
+
+function cleanup
+{
+ log_must rm -f $DEPTH_OUTPUT
+ log_must rm -f $EXPECT_OUTPUT
+}
+
+log_onexit cleanup
+log_assert "'zfs list -d <n>' should get expected output."
+
+DEPTH_OUTPUT="$TEST_BASE_DIR/depth_output"
+EXPECT_OUTPUT="$TEST_BASE_DIR/expect_output"
+typeset -i old_val=0
+typeset -i j=0
+typeset -i fs=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
+ (( fs=0 ))
+ while (( fs<${#fs_type[*]} )); do
+ if [[ "$dp" == "0" ]] && \
+ [[ "${fs_type[$fs]}" == "volume" || "${fs_type[$fs]}" == "snapshot" ]]; then
+ log_must eval "zfs list -H -d $dp -o name -t ${fs_type[$fs]} $DEPTH_FS > $DEPTH_OUTPUT"
+ [[ -s "$DEPTH_OUTPUT" ]] && \
+ log_fail "$DEPTH_OUTPUT should be null."
+ log_mustnot zfs list -rH -o name -t ${fs_type[$fs]} $DEPTH_FS | egrep -e '$eg_opt'
+ else
+ log_must eval "zfs list -H -d $dp -o name -t ${fs_type[$fs]} $DEPTH_FS > $DEPTH_OUTPUT"
+ log_must eval "zfs list -rH -o name -t ${fs_type[$fs]} $DEPTH_FS | egrep -e '$eg_opt' > $EXPECT_OUTPUT"
+ log_must diff $DEPTH_OUTPUT $EXPECT_OUTPUT
+ fi
+ (( fs+=1 ))
+ done
+ (( old_val=dp ))
+done
+
+log_pass "'zfs list -d <n>' should get expected output."
diff --git a/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.ksh
new file mode 100755
index 000000000000..4f3504ac41ba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zfs_list/zfs_list_008_neg.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $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 list -d <n>'
+#
+# STRATEGY:
+# 1. Run zfs list -d with negative depth or non numeric depth
+# 2. Verify that zfs list returns error
+#
+
+verify_runnable "both"
+
+log_assert "A negative depth or a non numeric depth should fail in 'zfs list -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 list -d ${badargs[i]} $DEPTH_FS >/dev/null 2>&1"
+ (( i = i + 1 ))
+done
+
+log_pass "A negative depth or a non numeric depth should fail in 'zfs list -d <n>'"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/Makefile.am b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/Makefile.am
new file mode 100644
index 000000000000..5ee30eafc358
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_user/zpool_iostat
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_iostat_001_neg.ksh \
+ zpool_iostat_002_pos.ksh \
+ zpool_iostat_003_neg.ksh \
+ zpool_iostat_004_pos.ksh \
+ zpool_iostat_005_pos.ksh \
+ zpool_iostat_-c_disable.ksh \
+ zpool_iostat_-c_searchpath.ksh \
+ zpool_iostat_-c_homedir.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/setup.ksh
new file mode 100755
index 000000000000..77eb6bd34f40
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_raidz_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.ksh
new file mode 100755
index 000000000000..0d64eb0ec624
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_disable.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) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool iostat command mode (-c) respects ZPOOL_SCRIPTS_ENABLED.
+#
+# STRATEGY:
+# 1. Set ZPOOL_SCRIPTS_ENABLED to 0, disabling zpool iostat -c
+# 2. zpool iostat -c must not run successfully
+# 3. Set ZPOOL_SCRIPTS_ENABLED to 1, enabling zpool iostat -c
+# 4. zpool iostat -c must run successfully
+# 5. Unset ZPOOL_SCRIPTS_ENABLED, enabling zpool iostat -c
+# 6. zpool iostat -c must run successfully
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+verify_runnable "both"
+
+log_assert "zpool iostat -c properly handles ZPOOL_SCRIPTS_ENABLED"
+
+export ZPOOL_SCRIPTS_ENABLED=0
+log_mustnot zpool iostat -c media
+
+export ZPOOL_SCRIPTS_ENABLED=1
+log_must zpool iostat -c media
+
+unset ZPOOL_SCRIPTS_ENABLED
+log_must zpool iostat -c media
+
+log_pass "zpool iostat -c properly handles ZPOOL_SCRIPTS_ENABLED passed"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.ksh
new file mode 100755
index 000000000000..5cb50fde6fba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_homedir.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 (c) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool iostat command mode (-c) works with scripts in user's
+# home directory.
+#
+# STRATEGY:
+# 1. Change HOME to /var/tmp
+# 2. Make a simple script that echos a key value pair
+# in /var/tmp/.zpool.d
+# 3. Make sure it can be run with -c
+# 4. Remove the script we created
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+verify_runnable "both"
+
+# In tree testing sets this variable, we need to unset it
+# to restore zpool's search path.
+unset ZPOOL_SCRIPTS_PATH
+
+# change HOME
+export HOME="$TEST_BASE_DIR"
+typeset USER_SCRIPT_FULL="$HOME/.zpool.d/userscript"
+
+function cleanup
+{
+ log_must rm -rf "$HOME/.zpool.d"
+}
+
+log_assert "zpool iostat -c can run scripts from ~/.zpool.d"
+
+if [ -e "$USER_SCRIPT_FULL" ]; then
+ log_fail "$USER_SCRIPT_FULL already exists."
+fi
+
+log_onexit cleanup
+
+# create simple script
+log_must mkdir -p "$HOME/.zpool.d"
+cat > "$USER_SCRIPT_FULL" << EOF
+#!/bin/sh
+echo "USRCOL=USRVAL"
+EOF
+log_must chmod +x "$USER_SCRIPT_FULL"
+
+# test that we can run the script
+typeset USER_SCRIPT=$(basename "$USER_SCRIPT_FULL")
+test_zpool_script "$USER_SCRIPT" "$TESTPOOL" "zpool iostat -P -c"
+
+log_pass "zpool iostat -c can run scripts from ~/.zpool.d passed"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.ksh
new file mode 100755
index 000000000000..1197ea2d1176
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_-c_searchpath.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 (c) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool iostat command mode (-c) works with ZPOOL_SCRIPTS_PATH
+# defined.
+#
+# STRATEGY:
+# 1. Set ZPOOL_SCRIPTS_PATH to contain a couple of non-default dirs
+# 2. Make a simple script that echos a key value pair in each dir
+# 3. Make sure scripts can be run with -c
+# 4. Remove the scripts we created
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+verify_runnable "both"
+
+typeset SCRIPT_1="$TEST_BASE_DIR/scripts1/test1"
+typeset SCRIPT_2="$TEST_BASE_DIR/scripts2/test2"
+
+function cleanup
+{
+ log_must rm -rf $(dirname "$SCRIPT_1")
+ log_must rm -rf $(dirname "$SCRIPT_2")
+}
+
+log_assert "zpool iostat -c can run scripts from custom search path"
+
+if [ -e "$SCRIPT_1" ]; then
+ log_fail "$SCRIPT_1 already exists."
+fi
+
+if [ -e "$SCRIPT_2" ]; then
+ log_fail "$SCRIPT_2 already exists."
+fi
+
+log_onexit cleanup
+
+# change zpool iostat search path
+export ZPOOL_SCRIPTS_PATH="$(dirname $SCRIPT_1):$(dirname $SCRIPT_2)"
+
+# create simple script in each dir
+log_must mkdir -p $(dirname "$SCRIPT_1")
+cat > "$SCRIPT_1" << EOF
+#!/bin/sh
+echo "USRCOL1=USRVAL1"
+EOF
+log_must chmod +x "$SCRIPT_1"
+
+log_must mkdir -p $(dirname "$SCRIPT_2")
+cat > "$SCRIPT_2" << EOF
+#!/bin/sh
+echo "USRCOL2=USRVAL2"
+EOF
+log_must chmod +x "$SCRIPT_2"
+
+# test that we can run the scripts
+typeset CMD_1=$(basename "$SCRIPT_1")
+typeset CMD_2=$(basename "$SCRIPT_2")
+test_zpool_script "$CMD_1" "$TESTPOOL" "zpool iostat -P -c"
+test_zpool_script "$CMD_2" "$TESTPOOL" "zpool iostat -P -c"
+test_zpool_script "$CMD_2,$CMD_1" "$TESTPOOL" "zpool iostat -P -c"
+
+log_pass "zpool iostat -c can run scripts from custom search path passed"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh
new file mode 100755
index 000000000000..d99d42984780
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that 'zpool iostat' can be executed as non-root.
+#
+# STRATEGY:
+# 1. Create an array of options.
+# 2. Execute each element of the array.
+# 3. Verify that a success is returned.
+#
+
+verify_runnable "both"
+
+typeset testpool
+if is_global_zone ; then
+ testpool=$TESTPOOL
+else
+ testpool=${TESTPOOL%%/*}
+fi
+
+set -A args "iostat" "iostat $testpool"
+
+log_assert "zpool iostat [pool_name ...] [interval]"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_must zpool ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'iostat' succeeds as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.ksh
new file mode 100755
index 000000000000..49be7d0701c2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_002_pos.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 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
+
+#
+# DESCRIPTION:
+# Verify that 'zpool iostat [interval [count]]' can be executed as non-root.
+#
+# STRATEGY:
+# 1. Set the interval to 1 and count to 4.
+# 2. Sleep for 4 seconds.
+# 3. Verify that the output has 4 records.
+# 4. Set interval to 0.5 and count to 1 to test floating point intervals.
+
+verify_runnable "both"
+
+typeset tmpfile=$TEST_BASE_DIR/zfsiostat.out.$$
+typeset -i stat_count=0
+
+function cleanup
+{
+ if [[ -f $tmpfile ]]; then
+ rm -f $tmpfile
+ fi
+}
+
+log_onexit cleanup
+log_assert "zpool iostat [pool_name ...] [interval] [count]"
+
+if ! is_global_zone ; then
+ TESTPOOL=${TESTPOOL%%/*}
+fi
+
+zpool iostat $TESTPOOL 1 4 > $tmpfile 2>&1 &
+sleep 4
+stat_count=$(grep $TESTPOOL $tmpfile | wc -l)
+
+if [[ $stat_count -ne 4 ]]; then
+ log_fail "zpool iostat [pool_name] [interval] [count] failed"
+fi
+
+# Test a floating point interval value
+log_must zpool iostat -v 0.5 1
+
+log_pass "zpool iostat [pool_name ...] [interval] [count] passed"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_neg.ksh
new file mode 100755
index 000000000000..b6bcf71bffff
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_003_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool iostat' command with bad options fails.
+#
+# STRATEGY:
+# 1. Create an array of badly formed 'zpool iostat' options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "both"
+
+typeset testpool
+if is_global_zone ; then
+ testpool=$TESTPOOL
+else
+ testpool=${TESTPOOL%%/*}
+fi
+
+set -A args "" "-?" "-f" "nonexistpool" "$TESTPOOL/$TESTFS" \
+ "$testpool 0" "$testpool -1" "$testpool 1 0" \
+ "$testpool 0 0" "$testpool -wl" "$testpool -wq" "$testpool -wr" \
+ "$testpool -rq" "$testpool -lr"
+
+log_assert "Executing 'zpool iostat' with bad options fails"
+
+typeset -i i=1
+while [[ $i -lt ${#args[*]} ]]; do
+ log_assert "doing zpool iostat ${args[i]}"
+ log_mustnot zpool iostat ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Executing 'zpool iostat' with bad options fails"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_pos.ksh
new file mode 100755
index 000000000000..a20321950113
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_004_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+# Copyright (C) 2016 Lawrence Livermore National Security, LLC.
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Executing 'zpool iostat' command with various combinations of extended
+# stats (-lqwr), parsable/script options (-pH), and misc lists of pools
+# and vdevs.
+#
+# STRATEGY:
+# 1. Create an array of mixed 'zpool iostat' options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "both"
+
+typeset testpool
+if is_global_zone ; then
+ testpool=$TESTPOOL
+else
+ testpool=${TESTPOOL%%/*}
+fi
+
+set -A args "" "-v" "-q" "-l" "-lq $TESTPOOL" "-ql ${DISKS[0]} ${DISKS[1]}" \
+ "-w $TESTPOOL ${DISKS[0]} ${DISKS[1]}" \
+ "-wp $TESTPOOL" \
+ "-qlH $TESTPOOL ${DISKS[0]}" \
+ "-vpH ${DISKS[0]}" \
+ "-wpH ${DISKS[0]}" \
+ "-r ${DISKS[0]}" \
+ "-rpH ${DISKS[0]}"
+
+log_assert "Executing 'zpool iostat' with extended stat options succeeds"
+log_note "testpool: $TESTPOOL, disks $DISKS"
+
+typeset -i i=1
+while [[ $i -lt ${#args[*]} ]]; do
+ log_note "doing zpool iostat ${args[i]}"
+ log_must zpool iostat ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Executing 'zpool iostat' with extended stat options succeeds"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_pos.ksh
new file mode 100755
index 000000000000..53652ec11b5a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_iostat/zpool_iostat_005_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+#
+# Copyright (c) 2016-2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool iostat command mode (-c) works for all pre-baked scripts.
+#
+# STRATEGY:
+# 1. Make sure each script creates at least one new column.
+# 2. Make sure the new column values exist.
+# 3. Make sure we can run multiple scripts in one -c line
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+verify_runnable "both"
+
+typeset testpool
+if is_global_zone ; then
+ testpool=$TESTPOOL
+else
+ testpool=${TESTPOOL%%/*}
+fi
+
+files="$(ls $ZPOOL_SCRIPT_DIR)"
+scripts=""
+for i in $files ; do
+ if [ ! -x "$ZPOOL_SCRIPT_DIR/$i" ] ; then
+ # Skip non-executables
+ continue
+ fi
+
+ # Collect executable script names
+ scripts="$scripts $i"
+
+ # Run each one with -c
+ test_zpool_script "$i" "$testpool" "zpool iostat -Pv -c"
+done
+
+# Test that we can run multiple scripts separated with a comma by running
+# all the scripts in a single -c line.
+allscripts="$(echo $scripts | sed -r 's/[[:blank:]]+/,/g')"
+test_zpool_script "$allscripts" "$testpool" "zpool iostat -Pv -c"
+
+exit 0
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/Makefile.am b/tests/zfs-tests/tests/functional/cli_user/zpool_list/Makefile.am
new file mode 100644
index 000000000000..de8cb366924d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_user/zpool_list
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_list_001_pos.ksh \
+ zpool_list_002_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/setup.ksh
new file mode 100755
index 000000000000..d275e063b13a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_001_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_001_pos.ksh
new file mode 100755
index 000000000000..4c57413f1464
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_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 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
+
+#
+# DESCRIPTION:
+# Verify that 'zpool list' succeeds as non-root.
+#
+# STRATEGY:
+# 1. Create an array of options.
+# 2. Execute each element of the array.
+# 3. Verify the command succeeds.
+#
+
+verify_runnable "both"
+
+if ! is_global_zone; then
+ TESTPOOL=${TESTPOOL%%/*}
+fi
+
+set -A args "list $TESTPOOL" "list -H $TESTPOOL" "list" "list -H" \
+ "list -H -o name $TESTPOOL" "list -o name $TESTPOOL" \
+ "list -o name,size,capacity,health,altroot $TESTPOOL" \
+ "list -H -o name,size,capacity,health,altroot $TESTPOOL" \
+ "list -o alloc,free $TESTPOOL"
+log_assert "zpool list [-H] [-o filed[,filed]*] [<pool_name> ...]"
+
+typeset -i i=0
+while [[ $i -lt ${#args[*]} ]]; do
+ log_must zpool ${args[i]}
+
+ ((i = i + 1))
+done
+
+log_pass "The sub-command 'list' succeeds as non-root."
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_neg.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_neg.ksh
new file mode 100755
index 000000000000..4ed38d475cd7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_list/zpool_list_002_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 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
+
+#
+# DESCRIPTION:
+# Executing 'zpool list' command with bad options fails.
+#
+# STRATEGY:
+# 1. Create an array of badly formed 'zpool list' options.
+# 2. Execute each element of the array.
+# 3. Verify an error code is returned.
+#
+
+verify_runnable "both"
+
+set -A args "" "-?" "-f" "-o" \
+ "-o fakeproperty" "-o name,size,fakeproperty"
+
+log_assert "Executing 'zpool list' with bad options fails"
+
+typeset -i i=1
+while [[ $i -lt ${#args[*]} ]]; do
+ log_mustnot zpool list ${args[i]}
+ ((i = i + 1))
+done
+
+log_pass "Executing 'zpool list' with bad options fails"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/Makefile.am b/tests/zfs-tests/tests/functional/cli_user/zpool_status/Makefile.am
new file mode 100644
index 000000000000..e1b339657749
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_user/zpool_status
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ zpool_status_003_pos.ksh \
+ zpool_status_-c_disable.ksh \
+ zpool_status_-c_homedir.ksh \
+ zpool_status_-c_searchpath.ksh
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/cleanup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/cleanup.ksh
new file mode 100755
index 000000000000..79cd6e9f908e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/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_user/zpool_status/setup.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/setup.ksh
new file mode 100755
index 000000000000..6a9af3bc28c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/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_user/zpool_status/zpool_status_-c_disable.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_disable.ksh
new file mode 100755
index 000000000000..c8105fb4a50a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_disable.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) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool status command mode (-c) respects ZPOOL_SCRIPTS_ENABLED.
+#
+# STRATEGY:
+# 1. Set ZPOOL_SCRIPTS_ENABLED to 0, disabling zpool status -c
+# 2. zpool status -c must not run successfully
+# 3. Set ZPOOL_SCRIPTS_ENABLED to 1, enabling zpool status -c
+# 4. zpool status -c must run successfully
+# 5. Unset ZPOOL_SCRIPTS_ENABLED, enabling zpool status -c
+# 6. zpool status -c must run successfully
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+verify_runnable "both"
+
+log_assert "zpool status -c properly handles ZPOOL_SCRIPTS_ENABLED"
+
+export ZPOOL_SCRIPTS_ENABLED=0
+log_mustnot zpool status -c media
+
+export ZPOOL_SCRIPTS_ENABLED=1
+log_must zpool status -c media
+
+unset ZPOOL_SCRIPTS_ENABLED
+log_must zpool status -c media
+
+log_pass "zpool status -c properly handles ZPOOL_SCRIPTS_ENABLED passed"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.ksh
new file mode 100755
index 000000000000..4cc3deb6dadf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_homedir.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 (c) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool status command mode (-c) works with scripts in user's
+# home directory.
+#
+# STRATEGY:
+# 1. Change HOME to /var/tmp
+# 2. Make a simple script that echos a key value pair
+# in /var/tmp/.zpool.d
+# 3. Make sure it can be run with -c
+# 4. Remove the script we created
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+verify_runnable "both"
+
+# In tree testing sets this variable, we need to unset it
+# to restore zpool's search path.
+unset ZPOOL_SCRIPTS_PATH
+
+# change HOME
+export HOME="$TEST_BASE_DIR"
+typeset USER_SCRIPT_FULL="$HOME/.zpool.d/userscript"
+
+function cleanup
+{
+ log_must rm -rf "$HOME/.zpool.d"
+}
+
+log_assert "zpool status -c can run scripts from ~/.zpool.d"
+
+if [ -e "$USER_SCRIPT_FULL" ]; then
+ log_fail "$USER_SCRIPT_FULL already exists."
+fi
+
+log_onexit cleanup
+
+# create simple script
+log_must mkdir -p "$HOME/.zpool.d"
+cat > "$USER_SCRIPT_FULL" << EOF
+#!/bin/sh
+echo "USRCOL=USRVAL"
+EOF
+log_must chmod +x "$USER_SCRIPT_FULL"
+
+# test that we can run the script
+typeset USER_SCRIPT=$(basename "$USER_SCRIPT_FULL")
+test_zpool_script "$USER_SCRIPT" "$TESTPOOL" "zpool status -P -c"
+
+log_pass "zpool status -c can run scripts from ~/.zpool.d passed"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.ksh
new file mode 100755
index 000000000000..a075b9a0c181
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_-c_searchpath.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 (c) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool status command mode (-c) works with ZPOOL_SCRIPTS_PATH
+# defined.
+#
+# STRATEGY:
+# 1. Set ZPOOL_SCRIPTS_PATH to contain a couple of non-default dirs
+# 2. Make a simple script that echos a key value pair in each dir
+# 3. Make sure scripts can be run with -c
+# 4. Remove the scripts we created
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+verify_runnable "both"
+
+typeset SCRIPT_1="$TEST_BASE_DIR/scripts1/test1"
+typeset SCRIPT_2="$TEST_BASE_DIR/scripts2/test2"
+
+function cleanup
+{
+ log_must rm -rf $(dirname "$SCRIPT_1")
+ log_must rm -rf $(dirname "$SCRIPT_2")
+}
+
+log_assert "zpool status -c can run scripts from custom search path"
+
+if [ -e "$SCRIPT_1" ]; then
+ log_fail "$SCRIPT_1 already exists."
+fi
+
+if [ -e "$SCRIPT_2" ]; then
+ log_fail "$SCRIPT_2 already exists."
+fi
+
+log_onexit cleanup
+
+# change zpool status search path
+export ZPOOL_SCRIPTS_PATH="$(dirname $SCRIPT_1):$(dirname $SCRIPT_2)"
+
+# create simple script in each dir
+log_must mkdir -p $(dirname "$SCRIPT_1")
+cat > "$SCRIPT_1" << EOF
+#!/bin/sh
+echo "USRCOL1=USRVAL1"
+EOF
+log_must chmod +x "$SCRIPT_1"
+
+log_must mkdir -p $(dirname "$SCRIPT_2")
+cat > "$SCRIPT_2" << EOF
+#!/bin/sh
+echo "USRCOL2=USRVAL2"
+EOF
+log_must chmod +x "$SCRIPT_2"
+
+# test that we can run the scripts
+typeset CMD_1=$(basename "$SCRIPT_1")
+typeset CMD_2=$(basename "$SCRIPT_2")
+test_zpool_script "$CMD_1" "$TESTPOOL" "zpool status -P -c"
+test_zpool_script "$CMD_2" "$TESTPOOL" "zpool status -P -c"
+test_zpool_script "$CMD_2,$CMD_1" "$TESTPOOL" "zpool status -P -c"
+
+log_pass "zpool status -c can run scripts from custom search path passed"
diff --git a/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_003_pos.ksh b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_003_pos.ksh
new file mode 100755
index 000000000000..fa7d3f3f2d56
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cli_user/zpool_status/zpool_status_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+#
+# Copyright (c) 2016-2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool status command mode (-c) works for all pre-baked scripts.
+#
+# STRATEGY:
+# 1. Make sure each script creates at least one new column.
+# 2. Make sure the new column values exist.
+# 3. Make sure we can run multiple scripts in one -c line
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+verify_runnable "both"
+
+typeset testpool
+if is_global_zone ; then
+ testpool="$TESTPOOL"
+else
+ testpool="${TESTPOOL%%/*}"
+fi
+
+files="$(ls $ZPOOL_SCRIPT_DIR)"
+scripts=""
+for i in $files ; do
+ if [ ! -x "$ZPOOL_SCRIPT_DIR/$i" ] ; then
+ # Skip non-executables
+ continue
+ fi
+
+ # Collect executable script names
+ scripts="$scripts $i"
+
+ # Run each one with -c
+ test_zpool_script "$i" "$testpool" "zpool status -P -c"
+done
+
+# Test that we can run multiple scripts separated with a comma by running
+# all the scripts in a single -c line.
+allscripts="$(echo $scripts | sed -r 's/[[:blank:]]+/,/g')"
+test_zpool_script "$allscripts" "$testpool" "zpool status -P -c"
+
+exit 0
diff --git a/tests/zfs-tests/tests/functional/compression/Makefile.am b/tests/zfs-tests/tests/functional/compression/Makefile.am
new file mode 100644
index 000000000000..92a973258d65
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/Makefile.am
@@ -0,0 +1,15 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/compression
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ compress_001_pos.ksh \
+ compress_002_pos.ksh \
+ compress_003_pos.ksh \
+ compress_004_pos.ksh \
+ l2arc_compressed_arc.ksh \
+ l2arc_compressed_arc_disabled.ksh \
+ l2arc_encrypted.ksh \
+ l2arc_encrypted_no_compressed_arc.ksh
+
+dist_pkgdata_DATA = \
+ compress.cfg
diff --git a/tests/zfs-tests/tests/functional/compression/cleanup.ksh b/tests/zfs-tests/tests/functional/compression/cleanup.ksh
new file mode 100755
index 000000000000..0573003b6af5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/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) 2013 by Delphix. All rights reserved.
+#
+
+. ${STF_SUITE}/include/libtest.shlib
+
+default_container_cleanup
diff --git a/tests/zfs-tests/tests/functional/compression/compress.cfg b/tests/zfs-tests/tests/functional/compression/compress.cfg
new file mode 100644
index 000000000000..b2373064505f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/compress.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export BLOCKSZ=8192
+export NUM_WRITES=16384
+export DATA=13
diff --git a/tests/zfs-tests/tests/functional/compression/compress_001_pos.ksh b/tests/zfs-tests/tests/functional/compression/compress_001_pos.ksh
new file mode 100755
index 000000000000..fe3a3acacc04
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/compress_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) 2007, Sun Microsystems Inc. All rights reserved.
+# Copyright (c) 2013, 2016, Delphix. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/compression/compress.cfg
+
+#
+# DESCRIPTION:
+# Create two files of exactly the same size. One with compression
+# and one without. Ensure the compressed file is smaller.
+#
+# STRATEGY:
+# Use "zfs set" to turn on compression and create files before
+# and after the set call. The compressed file should be smaller.
+#
+
+verify_runnable "both"
+
+typeset OP=create
+
+log_assert "Ensure that compressed files are smaller."
+
+log_note "Ensure compression is off"
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+
+log_note "Writing file without compression..."
+log_must file_write -o $OP -f $TESTDIR/$TESTFILE0 -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+
+log_note "Add compression property to the dataset and write another file"
+log_must zfs set compression=on $TESTPOOL/$TESTFS
+
+log_must file_write -o $OP -f $TESTDIR/$TESTFILE1 -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+
+sleep 60
+
+FILE0_BLKS=`du -k $TESTDIR/$TESTFILE0 | awk '{ print $1}'`
+FILE1_BLKS=`du -k $TESTDIR/$TESTFILE1 | awk '{ print $1}'`
+
+if [[ $FILE0_BLKS -le $FILE1_BLKS ]]; then
+ log_fail "$TESTFILE0 is smaller than $TESTFILE1" \
+ "($FILE0_BLKS <= $FILE1_BLKS)"
+fi
+
+log_pass "$TESTFILE0 is bigger than $TESTFILE1 ($FILE0_BLKS > $FILE1_BLKS)"
diff --git a/tests/zfs-tests/tests/functional/compression/compress_002_pos.ksh b/tests/zfs-tests/tests/functional/compression/compress_002_pos.ksh
new file mode 100755
index 000000000000..a07d70824042
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/compress_002_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 2007 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/compression/compress.cfg
+
+#
+# DESCRIPTION:
+# Create two files of exactly the same size. One with compression
+# and one without. Ensure the compressed file is smaller.
+#
+# NOTE: This test uses a dataset rather than a simple file system.
+#
+# STRATEGY:
+# Create a dataset, turn on compression and create files before
+# and after the property change. The compressed file should be smaller.
+#
+
+verify_runnable "both"
+
+typeset OP=create
+
+log_assert "Ensure that compressed files in a dataset are smaller."
+
+log_note "Ensure compression is off"
+log_must zfs set compression=off $TESTPOOL/$TESTCTR
+
+log_note "Writing file without compression..."
+log_must file_write -o $OP -f $TESTDIR1/$TESTFILE0 -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+
+log_note "Add compression property to the dataset and write another file"
+log_must zfs set compression=on $TESTPOOL/$TESTCTR
+
+log_must file_write -o $OP -f $TESTDIR1/$TESTFILE1 -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+
+sleep 60
+
+FILE0_BLKS=`du -k $TESTDIR1/$TESTFILE0 | awk '{ print $1}'`
+FILE1_BLKS=`du -k $TESTDIR1/$TESTFILE1 | awk '{ print $1}'`
+
+if [[ $FILE0_BLKS -le $FILE1_BLKS ]]; then
+ log_fail "$TESTFILE0 is smaller than $TESTFILE1" \
+ "($FILE0_BLKS <= $FILE1_BLKS)"
+fi
+
+log_pass "$TESTFILE0 is bigger than $TESTFILE1 ($FILE0_BLKS > $FILE1_BLKS)"
diff --git a/tests/zfs-tests/tests/functional/compression/compress_003_pos.ksh b/tests/zfs-tests/tests/functional/compression/compress_003_pos.ksh
new file mode 100755
index 000000000000..d5b7256b52d6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/compress_003_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) 2007, Sun Microsystems Inc. All rights reserved.
+# Copyright (c) 2013, 2016, Delphix. All rights reserved.
+# Copyright (c) 2019, Kjeld Schouten-Lebbing. All rights reserved.
+# Use is subject to license terms.
+#
+
+
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# With 'compression' or 'compress' set, changing filesystem blocksize cannot
+# cause system panic
+#
+# STRATEGY:
+# 1. Set 'compression' or "compress" to on
+# 2. Set different blocksize with ZFS filesystem
+# 3. Use 'mkfile' create single block and multi-block files
+# 4. Verify the system continued work
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -f $TESTDIR/*
+}
+
+log_assert "Changing blocksize doesn't cause system panic with compression settings"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+single_blk_file=$TESTDIR/singleblkfile.$$
+multi_blk_file=$TESTDIR/multiblkfile.$$
+typeset -i blksize=512
+typeset -i fsize=0
+typeset -i offset=0
+
+for propname in "compression" "compress"
+do
+ for value in "${compress_prop_vals[@]:1}"
+ do
+ log_must zfs set $propname=$value $fs
+ if [[ $value == "gzip-6" ]]; then
+ value="gzip"
+ fi
+ real_val=$(get_prop $propname $fs)
+ [[ $real_val != $value ]] && \
+ log_fail "Set property $propname=$value failed."
+
+ (( blksize = 512 ))
+ while (( blksize <= 131072 )); do
+ log_must zfs set recordsize=$blksize $fs
+ (( offset = $RANDOM ))
+ if (( offset > blksize )); then
+ (( offset = offset % blksize ))
+ fi
+ if (( (offset % 2) == 0 )); then
+ #keep offset as non-power-of-2
+ (( offset = offset + 1 ))
+ fi
+ (( fsize = offset ))
+ log_must mkfile $fsize $single_blk_file
+ (( fsize = blksize + offset ))
+ log_must mkfile $fsize $multi_blk_file
+
+ (( blksize = blksize * 2 ))
+ done
+ done
+done
+
+log_pass "The system works as expected while changing blocksize with compression settings"
diff --git a/tests/zfs-tests/tests/functional/compression/compress_004_pos.ksh b/tests/zfs-tests/tests/functional/compression/compress_004_pos.ksh
new file mode 100755
index 000000000000..b924bcd0ba62
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/compress_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 (c) 2007, Sun Microsystems Inc. All rights reserved.
+# Copyright (c) 2013, 2016, Delphix. All rights reserved.
+# Copyright (c) 2019, Kjeld Schouten-Lebbing. All Rights Reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# With 'compression' set, a file with non-power-of-2 blocksize storage space
+# can be freed as will normally.
+#
+# STRATEGY:
+# 1. Set 'compression' or 'compress' to on or lzjb
+# 2. Set different recordsize with ZFS filesystem
+# 3. Repeatedly using 'randfree_file' to create a file and then free its
+# storage space with different range, the system should work normally.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -f $TESTDIR/*
+}
+
+function create_free_testing #<file size> <file>
+{
+ typeset -i fsz=$1
+ typeset file=$2
+ typeset -i start=0
+ typeset -i len=0
+ typeset -i dist=0
+
+ for start in 0 `expr $RANDOM % $fsz`
+ do
+ (( dist = fsz - start ))
+ for len in `expr $RANDOM % $dist` $dist \
+ `expr $start + $dist`; do
+
+ # Zero length results in EINVAL for fallocate(2).
+ if is_linux; then
+ if (( len == 0 )); then
+ continue
+ fi
+ fi
+
+ log_must randfree_file -l fsz -s $start \
+ -n $len $file
+ [[ -e $file ]] && \
+ log_must rm -f $file
+ done
+ done
+}
+
+
+log_assert "Creating non-power-of-2 blocksize file and freeing the file \
+ storage space at will should work normally with compression setting"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+single_blk_file=$TESTDIR/singleblkfile.$$
+multi_blk_file=$TESTDIR/multiblkfile.$$
+typeset -i blksize=512
+typeset -i fsize=0
+typeset -i avail=0
+typeset -i blknum=0
+
+for propname in "compression" "compress"
+do
+ for value in "${compress_prop_vals[@]:1}"
+ do
+ log_must zfs set compression=$value $fs
+ real_val=$(get_prop $propname $fs)
+ if [[ $value == "gzip-6" ]]; then
+ value="gzip"
+ fi
+ [[ $real_val != $value ]] && \
+ log_fail "Set property $propname=$value failed."
+
+ (( blksize = 512 ))
+ while (( blksize <= 131072 )); do
+ log_must zfs set recordsize=$blksize $fs
+
+ # doing single block testing
+ (( fsize = $RANDOM ))
+ if (( fsize > blksize )); then
+ (( fsize = fsize % blksize ))
+ fi
+ if (( (fsize % 2) == 0 )); then
+ #make sure fsize is non-power-of-2
+ (( fsize = fsize + 1 ))
+ fi
+ create_free_testing $fsize $single_blk_file
+
+ # doing multiple blocks testing
+ avail=$(get_prop available $fs)
+ (( blknum = avail / blksize ))
+ # we just test <10 multi-blocks to limit testing time
+ (( blknum = blknum % 9 ))
+ while (( blknum < 2 )); do
+ (( blknum = blknum + $RANDOM % 9 ))
+ done
+ if (( (blknum % 2) == 0 )); then
+ (( blknum = blknum + 1 )) # keep blknum as odd
+ fi
+ (( fsize = blknum * blksize ))
+ create_free_testing $fsize $multi_blk_file
+
+ (( blksize = blksize * 2 ))
+ done
+ done
+done
+
+log_pass "Creating and freeing non-power-of-2 blocksize file work as expected."
diff --git a/tests/zfs-tests/tests/functional/compression/l2arc_compressed_arc.ksh b/tests/zfs-tests/tests/functional/compression/l2arc_compressed_arc.ksh
new file mode 100755
index 000000000000..5980ce156934
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/l2arc_compressed_arc.ksh
@@ -0,0 +1,97 @@
+#!/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
+
+export SIZE=1G
+export VDIR=$TESTDIR/disk.persist_l2arc
+export VDEV="$VDIR/a"
+export VDEV_CACHE="$VDIR/b"
+
+# fio options
+export DIRECTORY=/$TESTPOOL-l2arc
+export NUMJOBS=4
+export RUNTIME=30
+export PERF_RANDSEED=1234
+export PERF_COMPPERCENT=66
+export PERF_COMPCHUNK=0
+export BLOCKSIZE=128K
+export SYNC_TYPE=0
+export DIRECT=1
+
+#
+# DESCRIPTION:
+# System with compressed_arc disabled succeeds at reading from L2ARC
+#
+# STRATEGY:
+# 1. Enable compressed_arc.
+# 2. Create pool with a cache device and compression enabled.
+# 3. Read the number of L2ARC checksum failures.
+# 4. Create a random file in that pool and random read for 30 sec.
+# 5. Read the number of L2ARC checksum failures.
+#
+
+verify_runnable "global"
+
+log_assert "L2ARC with compressed_arc enabled succeeds."
+
+origin_carc_setting=$(get_tunable COMPRESSED_ARC_ENABLED)
+
+function cleanup
+{
+ if poolexists $TESTPOOL-l2arc ; then
+ destroy_pool $TESTPOOL-l2arc
+ fi
+
+ log_must set_tunable64 COMPRESSED_ARC_ENABLED $origin_carc_setting
+}
+log_onexit cleanup
+
+# Enable Compressed ARC so that in-ARC and on-disk will match
+log_must set_tunable64 COMPRESSED_ARC_ENABLED 1
+
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must mkfile $SIZE $VDEV
+
+typeset fill_mb=800
+typeset cache_sz=$(( floor($fill_mb / 2) ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -O compression=lz4 -f $TESTPOOL-l2arc $VDEV cache $VDEV_CACHE
+
+l2_cksum_bad_start=$(get_arcstat l2_cksum_bad)
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+l2_cksum_bad_end=$(get_arcstat l2_cksum_bad)
+
+log_note "L2ARC Failed Checksums before: $l2_cksum_bad_start After:"\
+ "$l2_cksum_bad_end"
+log_must test $(( $l2_cksum_bad_end - $l2_cksum_bad_start )) -eq 0
+
+log_must zpool destroy -f $TESTPOOL-l2arc
+
+log_pass "L2ARC with compressed_arc enabled does not result in checksum errors."
diff --git a/tests/zfs-tests/tests/functional/compression/l2arc_compressed_arc_disabled.ksh b/tests/zfs-tests/tests/functional/compression/l2arc_compressed_arc_disabled.ksh
new file mode 100755
index 000000000000..4c3b6a61c25f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/l2arc_compressed_arc_disabled.ksh
@@ -0,0 +1,98 @@
+#!/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
+
+export SIZE=1G
+export VDIR=$TESTDIR/disk.persist_l2arc
+export VDEV="$VDIR/a"
+export VDEV_CACHE="$VDIR/b"
+
+# fio options
+export DIRECTORY=/$TESTPOOL-l2arc
+export NUMJOBS=4
+export RUNTIME=30
+export PERF_RANDSEED=1234
+export PERF_COMPPERCENT=66
+export PERF_COMPCHUNK=0
+export BLOCKSIZE=128K
+export SYNC_TYPE=0
+export DIRECT=1
+
+#
+# DESCRIPTION:
+# System with compressed_arc disabled succeeds at reading from L2ARC
+#
+# STRATEGY:
+# 1. Disable compressed_arc.
+# 2. Create pool with a cache device and compression enabled.
+# 3. Read the number of L2ARC checksum failures.
+# 4. Create a random file in that pool and random read for 30 sec.
+# 5. Read the number of L2ARC checksum failures.
+#
+
+verify_runnable "global"
+
+log_assert "L2ARC with compressed_arc disabled succeeds."
+
+origin_carc_setting=$(get_tunable COMPRESSED_ARC_ENABLED)
+
+function cleanup
+{
+ if poolexists $TESTPOOL-l2arc ; then
+ destroy_pool $TESTPOOL-l2arc
+ fi
+
+ log_must set_tunable64 COMPRESSED_ARC_ENABLED $origin_carc_setting
+}
+log_onexit cleanup
+
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must mkfile $SIZE $VDEV
+
+# Disable Compressed ARC so that in-ARC and on-disk will not match
+log_must set_tunable64 COMPRESSED_ARC_ENABLED 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( floor($fill_mb / 2) ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -O compression=lz4 -f $TESTPOOL-l2arc $VDEV cache $VDEV_CACHE
+
+l2_cksum_bad_start=$(get_arcstat l2_cksum_bad)
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+l2_cksum_bad_end=$(get_arcstat l2_cksum_bad)
+
+log_note "L2ARC Failed Checksums before: $l2_cksum_bad_start After:"\
+ "$l2_cksum_bad_end"
+log_must test $(( $l2_cksum_bad_end - $l2_cksum_bad_start )) -eq 0
+
+log_must zpool destroy -f $TESTPOOL-l2arc
+
+log_pass "L2ARC with compressed_arc disabled does not result in checksum"\
+ "errors."
diff --git a/tests/zfs-tests/tests/functional/compression/l2arc_encrypted.ksh b/tests/zfs-tests/tests/functional/compression/l2arc_encrypted.ksh
new file mode 100755
index 000000000000..fb460daf6837
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/l2arc_encrypted.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) 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
+
+export SIZE=1G
+export VDIR=$TESTDIR/disk.persist_l2arc
+export VDEV="$VDIR/a"
+export VDEV_CACHE="$VDIR/b"
+export PASSPHRASE="password"
+
+# fio options
+export DIRECTORY=/$TESTPOOL-l2arc/encrypted
+export NUMJOBS=4
+export RUNTIME=30
+export PERF_RANDSEED=1234
+export PERF_COMPPERCENT=66
+export PERF_COMPCHUNK=0
+export BLOCKSIZE=128K
+export SYNC_TYPE=0
+export DIRECT=1
+
+#
+# DESCRIPTION:
+# System with compressed_arc disabled succeeds at reading from L2ARC
+#
+# STRATEGY:
+# 1. Enable compressed_arc.
+# 2. Create pool with a cache device, encryption, and compression enabled.
+# 3. Read the number of L2ARC checksum failures.
+# 4. Create a random file in that pool and random read for 30 sec.
+# 5. Read the number of L2ARC checksum failures.
+#
+
+verify_runnable "global"
+
+log_assert "L2ARC with encryption enabled succeeds."
+
+origin_carc_setting=$(get_tunable COMPRESSED_ARC_ENABLED)
+
+function cleanup
+{
+ if poolexists $TESTPOOL-l2arc ; then
+ destroy_pool $TESTPOOL-l2arc
+ fi
+
+ log_must set_tunable64 COMPRESSED_ARC_ENABLED $origin_carc_setting
+}
+log_onexit cleanup
+
+# Enable Compressed ARC so that in-ARC and on-disk will match
+log_must set_tunable64 COMPRESSED_ARC_ENABLED 1
+
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must mkfile $SIZE $VDEV
+
+typeset fill_mb=800
+typeset cache_sz=$(( floor($fill_mb / 2) ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -O compression=zstd -f $TESTPOOL-l2arc $VDEV cache $VDEV_CACHE
+
+log_must eval "echo $PASSPHRASE | zfs create -o compression=zstd " \
+ "-o encryption=on -o keyformat=passphrase -o keylocation=prompt " \
+ "$TESTPOOL-l2arc/encrypted"
+
+l2_cksum_bad_start=$(get_arcstat l2_cksum_bad)
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+l2_cksum_bad_end=$(get_arcstat l2_cksum_bad)
+
+log_note "L2ARC Failed Checksums before: $l2_cksum_bad_start After:"\
+ "$l2_cksum_bad_end"
+log_must test $(( $l2_cksum_bad_end - $l2_cksum_bad_start )) -eq 0
+
+log_must zpool destroy -f $TESTPOOL-l2arc
+
+log_pass "L2ARC with encryption and compressed_arc enabled does not result in"\
+ "checksum errors."
diff --git a/tests/zfs-tests/tests/functional/compression/l2arc_encrypted_no_compressed_arc.ksh b/tests/zfs-tests/tests/functional/compression/l2arc_encrypted_no_compressed_arc.ksh
new file mode 100755
index 000000000000..45ef489c3145
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/l2arc_encrypted_no_compressed_arc.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) 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
+
+export SIZE=1G
+export VDIR=$TESTDIR/disk.persist_l2arc
+export VDEV="$VDIR/a"
+export VDEV_CACHE="$VDIR/b"
+export PASSPHRASE="password"
+
+# fio options
+export DIRECTORY=/$TESTPOOL-l2arc/encrypted
+export NUMJOBS=4
+export RUNTIME=30
+export PERF_RANDSEED=1234
+export PERF_COMPPERCENT=66
+export PERF_COMPCHUNK=0
+export BLOCKSIZE=128K
+export SYNC_TYPE=0
+export DIRECT=1
+
+#
+# DESCRIPTION:
+# System with compressed_arc disabled succeeds at reading from L2ARC
+#
+# STRATEGY:
+# 1. Disable compressed_arc.
+# 2. Create pool with a cache device, encryption, and compression enabled.
+# 3. Read the number of L2ARC checksum failures.
+# 4. Create a random file in that pool and random read for 30 sec.
+# 5. Read the number of L2ARC checksum failures.
+#
+
+verify_runnable "global"
+
+log_assert "L2ARC with compressed_arc disabled succeeds."
+
+origin_carc_setting=$(get_tunable COMPRESSED_ARC_ENABLED)
+
+function cleanup
+{
+ if poolexists $TESTPOOL-l2arc ; then
+ destroy_pool $TESTPOOL-l2arc
+ fi
+
+ log_must set_tunable64 COMPRESSED_ARC_ENABLED $origin_carc_setting
+}
+log_onexit cleanup
+
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must mkfile $SIZE $VDEV
+
+# Disable Compressed ARC so that in-ARC and on-disk will not match
+log_must set_tunable64 COMPRESSED_ARC_ENABLED 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( floor($fill_mb / 2) ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -O compression=zstd -f $TESTPOOL-l2arc $VDEV cache $VDEV_CACHE
+
+log_must eval "echo $PASSPHRASE | zfs create -o compression=zstd " \
+ "-o encryption=on -o keyformat=passphrase -o keylocation=prompt " \
+ "$TESTPOOL-l2arc/encrypted"
+
+l2_cksum_bad_start=$(get_arcstat l2_cksum_bad)
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+l2_cksum_bad_end=$(get_arcstat l2_cksum_bad)
+
+log_note "L2ARC Failed Checksums before: $l2_cksum_bad_start After:"\
+ "$l2_cksum_bad_end"
+log_must test $(( $l2_cksum_bad_end - $l2_cksum_bad_start )) -eq 0
+
+log_must zpool destroy -f $TESTPOOL-l2arc
+
+log_pass "L2ARC with encryption enabled and compressed_arc disabled does not"\
+ "result in checksum errors."
diff --git a/tests/zfs-tests/tests/functional/compression/setup.ksh b/tests/zfs-tests/tests/functional/compression/setup.ksh
new file mode 100755
index 000000000000..677cb12d79ac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/compression/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_container_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/cp_files/.gitignore b/tests/zfs-tests/tests/functional/cp_files/.gitignore
new file mode 100644
index 000000000000..eac05e155378
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/.gitignore
@@ -0,0 +1 @@
+/cp_files
diff --git a/tests/zfs-tests/tests/functional/cp_files/Makefile.am b/tests/zfs-tests/tests/functional/cp_files/Makefile.am
new file mode 100644
index 000000000000..06c31f5f3f92
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/Makefile.am
@@ -0,0 +1,13 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cp_files
+
+dist_pkgdata_SCRIPTS = \
+ cp_files_001_pos.ksh \
+ cleanup.ksh \
+ setup.ksh
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cp_files
+
+pkgexec_PROGRAMS = cp_files
+cp_files_SOURCES= cp_files.c
diff --git a/tests/zfs-tests/tests/functional/cp_files/cleanup.ksh b/tests/zfs-tests/tests/functional/cp_files/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/cp_files/cp_files.c b/tests/zfs-tests/tests/functional/cp_files/cp_files.c
new file mode 100644
index 000000000000..9af64a112631
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/cp_files.c
@@ -0,0 +1,58 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+
+int
+main(int argc, char *argv[])
+{
+ int tfd;
+ DIR *sdir;
+ struct dirent *dirent;
+
+ if (argc != 3) {
+ fprintf(stderr, "Usage: %s SRC DST\n", argv[0]);
+ exit(1);
+ }
+
+ sdir = opendir(argv[1]);
+ if (sdir == NULL) {
+ fprintf(stderr, "Failed to open %s: %s\n",
+ argv[1], strerror(errno));
+ exit(2);
+ }
+
+ tfd = open(argv[2], O_DIRECTORY);
+ if (tfd < 0) {
+ fprintf(stderr, "Failed to open %s: %s\n",
+ argv[2], strerror(errno));
+ closedir(sdir);
+ exit(3);
+ }
+
+ while ((dirent = readdir(sdir)) != NULL) {
+ if (dirent->d_name[0] == '.' &&
+ (dirent->d_name[1] == '.' || dirent->d_name[1] == '\0'))
+ continue;
+
+ int fd = openat(tfd, dirent->d_name, O_CREAT|O_WRONLY, 0666);
+ if (fd < 0) {
+ fprintf(stderr, "Failed to create %s/%s: %s\n",
+ argv[2], dirent->d_name, strerror(errno));
+ closedir(sdir);
+ close(tfd);
+ exit(4);
+ }
+ close(fd);
+ }
+
+ closedir(sdir);
+ close(tfd);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.ksh b/tests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.ksh
new file mode 100755
index 000000000000..3e138cfc9f72
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/cp_files_001_pos.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 by Nutanix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Copy a large number of files between 2 directories
+# within a zfs filesystem works without errors.
+# This make sure zap upgrading and expanding works.
+#
+# STRATEGY:
+#
+# 1. Create NR_FILES files in directory src
+# 2. Check the number of files is correct
+# 3. Copy files from src to dst in readdir order
+# 4. Check the number of files is correct
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ rm -rf $TESTDIR/src $TESTDIR/dst
+}
+
+log_assert "Copy a large number of files between 2 directories" \
+ "within a zfs filesystem works without errors"
+
+log_onexit cleanup
+
+NR_FILES=60000
+BATCH=1000
+
+log_must mkdir $TESTDIR/src
+log_must mkdir $TESTDIR/dst
+
+WD=$(pwd)
+cd $TESTDIR/src
+# create NR_FILES in BATCH at a time to prevent overflowing argument buffer
+for i in $(seq $(($NR_FILES/$BATCH))); do touch $(seq $((($i-1)*$BATCH+1)) $(($i*$BATCH))); done
+cd $WD
+
+log_must test $NR_FILES -eq $(ls -U $TESTDIR/src | wc -l)
+
+# copy files from src to dst, use cp_files to make sure we copy in readdir order
+log_must $STF_SUITE/tests/functional/cp_files/cp_files $TESTDIR/src $TESTDIR/dst
+
+log_must test $NR_FILES -eq $(ls -U $TESTDIR/dst | wc -l)
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/cp_files/setup.ksh b/tests/zfs-tests/tests/functional/cp_files/setup.ksh
new file mode 100755
index 000000000000..fc5cec3063a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/cp_files/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/ctime/.gitignore b/tests/zfs-tests/tests/functional/ctime/.gitignore
new file mode 100644
index 000000000000..9e4539d5fee0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/ctime/.gitignore
@@ -0,0 +1 @@
+/ctime
diff --git a/tests/zfs-tests/tests/functional/ctime/Makefile.am b/tests/zfs-tests/tests/functional/ctime/Makefile.am
new file mode 100644
index 000000000000..e7479ae81056
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/ctime/Makefile.am
@@ -0,0 +1,13 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/ctime
+
+dist_pkgdata_SCRIPTS = \
+ ctime_001_pos.ksh \
+ cleanup.ksh \
+ setup.ksh
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/ctime
+
+pkgexec_PROGRAMS = ctime
+ctime_SOURCES = ctime.c
diff --git a/tests/zfs-tests/tests/functional/ctime/cleanup.ksh b/tests/zfs-tests/tests/functional/ctime/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/ctime/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/ctime/ctime.c b/tests/zfs-tests/tests/functional/ctime/ctime.c
new file mode 100644
index 000000000000..d01fa0d4ed3e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/ctime/ctime.c
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ */
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#ifndef __FreeBSD__
+#include <sys/xattr.h>
+#endif
+#include <utime.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <libgen.h>
+#include <string.h>
+
+#define ST_ATIME 0
+#define ST_CTIME 1
+#define ST_MTIME 2
+
+#define ALL_MODE (mode_t)(S_IRWXU|S_IRWXG|S_IRWXO)
+
+typedef struct timetest {
+ int type;
+ char *name;
+ int (*func)(const char *pfile);
+} timetest_t;
+
+static char tfile[BUFSIZ] = { 0 };
+
+/*
+ * DESCRIPTION:
+ * Verify time will be changed correctly after each operation.
+ *
+ * STRATEGY:
+ * 1. Define time test array.
+ * 2. Loop through each item in this array.
+ * 3. Verify the time is changed after each operation.
+ *
+ */
+
+static int
+get_file_time(const char *pfile, int what, time_t *ptr)
+{
+ struct stat stat_buf;
+
+ if (pfile == NULL || ptr == NULL) {
+ return (-1);
+ }
+
+ if (stat(pfile, &stat_buf) == -1) {
+ return (-1);
+ }
+
+ switch (what) {
+ case ST_ATIME:
+ *ptr = stat_buf.st_atime;
+ return (0);
+ case ST_CTIME:
+ *ptr = stat_buf.st_ctime;
+ return (0);
+ case ST_MTIME:
+ *ptr = stat_buf.st_mtime;
+ return (0);
+ default:
+ return (-1);
+ }
+}
+
+static int
+do_read(const char *pfile)
+{
+ int fd, ret = 0;
+ char buf[BUFSIZ] = { 0 };
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if ((fd = open(pfile, O_RDONLY, ALL_MODE)) == -1) {
+ return (-1);
+ }
+ if (read(fd, buf, sizeof (buf)) == -1) {
+ (void) fprintf(stderr, "read(%d, buf, %zd) failed with errno "
+ "%d\n", fd, sizeof (buf), errno);
+ (void) close(fd);
+ return (1);
+ }
+ (void) close(fd);
+
+ return (ret);
+}
+
+static int
+do_write(const char *pfile)
+{
+ int fd, ret = 0;
+ char buf[BUFSIZ] = "call function do_write()";
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if ((fd = open(pfile, O_WRONLY, ALL_MODE)) == -1) {
+ return (-1);
+ }
+ if (write(fd, buf, strlen(buf)) == -1) {
+ (void) fprintf(stderr, "write(%d, buf, %d) failed with errno "
+ "%d\n", fd, (int)strlen(buf), errno);
+ (void) close(fd);
+ return (1);
+ }
+ (void) close(fd);
+
+ return (ret);
+}
+
+static int
+do_link(const char *pfile)
+{
+ int ret = 0;
+ char link_file[BUFSIZ] = { 0 };
+ char pfile_copy[BUFSIZ] = { 0 };
+ char *dname;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ strncpy(pfile_copy, pfile, sizeof (pfile_copy)-1);
+ pfile_copy[sizeof (pfile_copy) - 1] = '\0';
+ /*
+ * Figure out source file directory name, and create
+ * the link file in the same directory.
+ */
+ dname = dirname((char *)pfile_copy);
+ (void) snprintf(link_file, BUFSIZ, "%s/%s", dname, "link_file");
+
+ if (link(pfile, link_file) == -1) {
+ (void) fprintf(stderr, "link(%s, %s) failed with errno %d\n",
+ pfile, link_file, errno);
+ return (1);
+ }
+
+ (void) unlink(link_file);
+
+ return (ret);
+}
+
+static int
+do_creat(const char *pfile)
+{
+ int fd, ret = 0;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if ((fd = creat(pfile, ALL_MODE)) == -1) {
+ (void) fprintf(stderr, "creat(%s, ALL_MODE) failed with errno "
+ "%d\n", pfile, errno);
+ return (1);
+ }
+ (void) close(fd);
+
+ return (ret);
+}
+
+static int
+do_utime(const char *pfile)
+{
+ int ret = 0;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ /*
+ * Times of the file are set to the current time
+ */
+ if (utime(pfile, NULL) == -1) {
+ (void) fprintf(stderr, "utime(%s, NULL) failed with errno "
+ "%d\n", pfile, errno);
+ return (1);
+ }
+
+ return (ret);
+}
+
+static int
+do_chmod(const char *pfile)
+{
+ int ret = 0;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if (chmod(pfile, ALL_MODE) == -1) {
+ (void) fprintf(stderr, "chmod(%s, ALL_MODE) failed with "
+ "errno %d\n", pfile, errno);
+ return (1);
+ }
+
+ return (ret);
+}
+
+static int
+do_chown(const char *pfile)
+{
+ int ret = 0;
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if (chown(pfile, getuid(), getgid()) == -1) {
+ (void) fprintf(stderr, "chown(%s, %d, %d) failed with errno "
+ "%d\n", pfile, (int)getuid(), (int)getgid(), errno);
+ return (1);
+ }
+
+ return (ret);
+}
+
+#ifndef __FreeBSD__
+static int
+do_xattr(const char *pfile)
+{
+ int ret = 0;
+ char *value = "user.value";
+
+ if (pfile == NULL) {
+ return (-1);
+ }
+
+ if (setxattr(pfile, "user.x", value, strlen(value), 0) == -1) {
+ (void) fprintf(stderr, "setxattr(%s, %d, %d) failed with errno "
+ "%d\n", pfile, (int)getuid(), (int)getgid(), errno);
+ return (1);
+ }
+ return (ret);
+}
+#endif
+
+static void
+cleanup(void)
+{
+ if ((strlen(tfile) != 0) && (access(tfile, F_OK) == 0)) {
+ (void) unlink(tfile);
+ }
+}
+
+static timetest_t timetest_table[] = {
+ { ST_ATIME, "st_atime", do_read },
+ { ST_ATIME, "st_atime", do_utime },
+ { ST_MTIME, "st_mtime", do_creat },
+ { ST_MTIME, "st_mtime", do_write },
+ { ST_MTIME, "st_mtime", do_utime },
+ { ST_CTIME, "st_ctime", do_creat },
+ { ST_CTIME, "st_ctime", do_write },
+ { ST_CTIME, "st_ctime", do_chmod },
+ { ST_CTIME, "st_ctime", do_chown },
+ { ST_CTIME, "st_ctime", do_link },
+ { ST_CTIME, "st_ctime", do_utime },
+#ifndef __FreeBSD__
+ { ST_CTIME, "st_ctime", do_xattr },
+#endif
+};
+
+#define NCOMMAND (sizeof (timetest_table) / sizeof (timetest_table[0]))
+
+/* ARGSUSED */
+int
+main(int argc, char *argv[])
+{
+ int i, ret, fd;
+ char *penv[] = {"TESTDIR", "TESTFILE0"};
+
+ (void) atexit(cleanup);
+
+ /*
+ * Get the environment variable values.
+ */
+ for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
+ if ((penv[i] = getenv(penv[i])) == NULL) {
+ (void) fprintf(stderr, "getenv(penv[%d])\n", i);
+ return (1);
+ }
+ }
+ (void) snprintf(tfile, sizeof (tfile), "%s/%s", penv[0], penv[1]);
+
+ /*
+ * If the test file is exists, remove it first.
+ */
+ if (access(tfile, F_OK) == 0) {
+ (void) unlink(tfile);
+ }
+ ret = 0;
+ if ((fd = open(tfile, O_WRONLY | O_CREAT | O_TRUNC, ALL_MODE)) == -1) {
+ (void) fprintf(stderr, "open(%s) failed: %d\n", tfile, errno);
+ return (1);
+ }
+ (void) close(fd);
+
+ for (i = 0; i < NCOMMAND; i++) {
+ time_t t1, t2;
+
+ /*
+ * Get original time before operating.
+ */
+ ret = get_file_time(tfile, timetest_table[i].type, &t1);
+ if (ret != 0) {
+ (void) fprintf(stderr, "get_file_time(%s %d) = %d\n",
+ tfile, timetest_table[i].type, ret);
+ return (1);
+ }
+
+ /*
+ * Sleep 2 seconds, then invoke command on given file
+ */
+ (void) sleep(2);
+ timetest_table[i].func(tfile);
+
+ /*
+ * Get time after operating.
+ */
+ ret = get_file_time(tfile, timetest_table[i].type, &t2);
+ if (ret != 0) {
+ (void) fprintf(stderr, "get_file_time(%s %d) = %d\n",
+ tfile, timetest_table[i].type, ret);
+ return (1);
+ }
+
+ if (t1 == t2) {
+ (void) fprintf(stderr, "%s: t1(%ld) == t2(%ld)\n",
+ timetest_table[i].name, (long)t1, (long)t2);
+ return (1);
+ } else {
+ (void) fprintf(stderr, "%s: t1(%ld) != t2(%ld)\n",
+ timetest_table[i].name, (long)t1, (long)t2);
+ }
+ }
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh b/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.ksh
new file mode 100755
index 000000000000..de12efe46bc0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/ctime/ctime_001_pos.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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+# . $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# Verify [acm]time is modified appropriately with xattr=on|sa
+
+set -A args "sa" "on"
+
+log_note "Verify [acm]time is modified appropriately."
+
+for arg in ${args[*]}; do
+ log_note "Testing with xattr set to $arg"
+ log_must zfs set xattr=$arg $TESTPOOL
+ log_must $STF_SUITE/tests/functional/ctime/ctime
+done
+
+log_pass "PASS"
diff --git a/tests/zfs-tests/tests/functional/ctime/setup.ksh b/tests/zfs-tests/tests/functional/ctime/setup.ksh
new file mode 100755
index 000000000000..fc5cec3063a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/ctime/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/deadman/Makefile.am b/tests/zfs-tests/tests/functional/deadman/Makefile.am
new file mode 100644
index 000000000000..7b70ca09df56
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/deadman/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/deadman
+dist_pkgdata_SCRIPTS = \
+ deadman_sync.ksh \
+ deadman_zio.ksh
+
+dist_pkgdata_DATA = \
+ deadman.cfg
diff --git a/tests/zfs-tests/tests/functional/deadman/deadman.cfg b/tests/zfs-tests/tests/functional/deadman/deadman.cfg
new file mode 100644
index 000000000000..e767f3dd5a98
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/deadman/deadman.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 (c) 2018 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+export DISK1=${DISKS%% *}
+
+export SYNCTIME_DEFAULT=600000
+export ZIOTIME_DEFAULT=300000
+export CHECKTIME_DEFAULT=60000
+export FAILMODE_DEFAULT="wait"
diff --git a/tests/zfs-tests/tests/functional/deadman/deadman_sync.ksh b/tests/zfs-tests/tests/functional/deadman/deadman_sync.ksh
new file mode 100755
index 000000000000..5d803af85bed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/deadman/deadman_sync.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) 2017 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+# DESCRIPTION:
+# Verify spa deadman detects a hung txg
+#
+# STRATEGY:
+# 1. Reduce the zfs_deadman_synctime_ms to 5s.
+# 2. Reduce the zfs_deadman_checktime_ms to 1s.
+# 3. Inject a 10s zio delay to force long IOs.
+# 4. Write enough data to force a long txg sync time due to the delay.
+# 5. Verify a "deadman" event is posted.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/deadman/deadman.cfg
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+ default_cleanup_noexit
+
+ log_must set_tunable64 DEADMAN_SYNCTIME_MS $SYNCTIME_DEFAULT
+ log_must set_tunable64 DEADMAN_CHECKTIME_MS $CHECKTIME_DEFAULT
+ log_must set_tunable64 DEADMAN_FAILMODE $FAILMODE_DEFAULT
+}
+
+log_assert "Verify spa deadman detects a hung txg"
+log_onexit cleanup
+
+log_must set_tunable64 DEADMAN_SYNCTIME_MS 5000
+log_must set_tunable64 DEADMAN_CHECKTIME_MS 1000
+log_must set_tunable64 DEADMAN_FAILMODE "wait"
+
+# Create a new pool in order to use the updated deadman settings.
+default_setup_noexit $DISK1
+log_must zpool events -c
+
+# Force each IO to take 10s by allow them to run concurrently.
+log_must zinject -d $DISK1 -D10000:10 $TESTPOOL
+
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+log_must file_write -b 1048576 -c 8 -o create -d 0 -f $mntpnt/file
+sleep 10
+
+log_must zinject -c all
+log_must zpool sync
+
+# Log txg sync times for reference and the zpool event summary.
+log_must cat /proc/spl/kstat/zfs/$TESTPOOL/txgs
+log_must zpool events
+
+# Verify at least 5 deadman events were logged. The first after 5 seconds,
+# and another each second thereafter until the delay is clearer.
+events=$(zpool events | grep -c ereport.fs.zfs.deadman)
+if [ "$events" -lt 5 ]; then
+ log_fail "Expect >=5 deadman events, $events found"
+fi
+
+log_pass "Verify spa deadman detected a hung txg and $events deadman events"
diff --git a/tests/zfs-tests/tests/functional/deadman/deadman_zio.ksh b/tests/zfs-tests/tests/functional/deadman/deadman_zio.ksh
new file mode 100755
index 000000000000..c1cfc1151239
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/deadman/deadman_zio.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 (c) 2017 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+# DESCRIPTION:
+# Verify zio deadman detects a hung zio
+#
+# STRATEGY:
+# 1. Reduce the zfs_deadman_ziotime_ms to 5s.
+# 2. Reduce the zfs_deadman_checktime_ms to 1s.
+# 3. Inject a 10s zio delay to force long IOs.
+# 4. Read an uncached file in the background.
+# 5. Verify a "deadman" event is posted.
+# 6. Inject a 100ms zio delay which is under the 5s allowed.
+# 7. Read an uncached file in the background.
+# 8. Verify a "deadman" event is not posted.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/deadman/deadman.cfg
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+ default_cleanup_noexit
+
+ log_must set_tunable64 DEADMAN_ZIOTIME_MS $ZIOTIME_DEFAULT
+ log_must set_tunable64 DEADMAN_CHECKTIME_MS $CHECKTIME_DEFAULT
+ log_must set_tunable64 DEADMAN_FAILMODE $FAILMODE_DEFAULT
+}
+
+log_assert "Verify zio deadman detects a hung zio"
+log_onexit cleanup
+
+# 1. Reduce the zfs_deadman_ziotime_ms to 5s.
+log_must set_tunable64 DEADMAN_ZIOTIME_MS 5000
+# 2. Reduce the zfs_deadman_checktime_ms to 1s.
+log_must set_tunable64 DEADMAN_CHECKTIME_MS 1000
+log_must set_tunable64 DEADMAN_FAILMODE "wait"
+
+# Create a new pool in order to use the updated deadman settings.
+default_setup_noexit $DISK1
+
+# Write a file and export/import the pool to clear the ARC.
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+log_must file_write -b 1048576 -c 8 -o create -d 0 -f $mntpnt/file1
+log_must file_write -b 1048576 -c 8 -o create -d 0 -f $mntpnt/file2
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+log_must stat -t /$mntpnt/file1
+log_must stat -t /$mntpnt/file2
+
+# 3. Inject a 10s zio delay to force long IOs and serialize them..
+log_must zpool events -c
+log_must zinject -d $DISK1 -D10000:1 $TESTPOOL
+
+# 4. Read an uncached file in the background, it's expected to hang.
+log_must eval "dd if=/$mntpnt/file1 of=/dev/null bs=1048576 &"
+sleep 10
+log_must zinject -c all
+log_must zpool sync
+wait
+
+# 5. Verify a "deadman" event is posted. The first appears after 5
+# seconds, and another each second thereafter until the delay is cleared.
+events=$(zpool events | grep -c ereport.fs.zfs.deadman)
+if [ "$events" -lt 1 ]; then
+ log_fail "Expect >=1 deadman events, $events found"
+fi
+
+# 6. Inject a 100ms zio delay which is under the 5s allowed, allow them
+# to run concurrently so they don't get starved in the queue.
+log_must zpool events -c
+log_must zinject -d $DISK1 -D100:10 $TESTPOOL
+
+# 7. Read an uncached file in the background.
+log_must eval "dd if=/$mntpnt/file2 of=/dev/null bs=1048576 &"
+sleep 10
+log_must zinject -c all
+wait
+
+# 8. Verify a "deadman" event is not posted.
+events=$(zpool events | grep -c ereport.fs.zfs.deadman)
+if [ "$events" -ne 0 ]; then
+ log_fail "Expect 0 deadman events, $events found"
+fi
+
+log_pass "Verify zio deadman detected a hung zio and $events deadman events"
diff --git a/tests/zfs-tests/tests/functional/delegate/Makefile.am b/tests/zfs-tests/tests/functional/delegate/Makefile.am
new file mode 100644
index 000000000000..c33da3374d88
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/Makefile.am
@@ -0,0 +1,28 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/delegate
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zfs_allow_001_pos.ksh \
+ zfs_allow_002_pos.ksh \
+ zfs_allow_003_pos.ksh \
+ zfs_allow_004_pos.ksh \
+ zfs_allow_005_pos.ksh \
+ zfs_allow_006_pos.ksh \
+ zfs_allow_007_pos.ksh \
+ zfs_allow_008_pos.ksh \
+ zfs_allow_009_neg.ksh \
+ zfs_allow_010_pos.ksh \
+ zfs_allow_011_neg.ksh \
+ zfs_allow_012_neg.ksh \
+ zfs_unallow_001_pos.ksh \
+ zfs_unallow_002_pos.ksh \
+ zfs_unallow_003_pos.ksh \
+ zfs_unallow_004_pos.ksh \
+ zfs_unallow_005_pos.ksh \
+ zfs_unallow_006_pos.ksh \
+ zfs_unallow_007_neg.ksh \
+ zfs_unallow_008_neg.ksh
+
+dist_pkgdata_DATA = \
+ delegate.cfg \
+ delegate_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/delegate/cleanup.ksh b/tests/zfs-tests/tests/functional/delegate/cleanup.ksh
new file mode 100755
index 000000000000..1951c00e2cf3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/cleanup.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) 2013, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2018 George Melikov. All Rights Reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+cleanup_user_group
+
+if ! is_linux; then
+ # restore the state of svc:/network/nis/client:default
+ if [[ -e $NISSTAFILE ]]; then
+ log_must svcadm enable svc:/network/nis/client:default
+ log_must rm -f $NISSTAFILE
+ fi
+fi
+
+if is_freebsd; then
+ log_must sysctl vfs.usermount=0
+fi
+
+if is_linux; then
+ log_must set_tunable64 ADMIN_SNAPSHOT 0
+fi
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/delegate/delegate.cfg b/tests/zfs-tests/tests/functional/delegate/delegate.cfg
new file mode 100644
index 000000000000..a9a46281b185
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/delegate.cfg
@@ -0,0 +1,72 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+export NISSTAFILE=$TEST_BASE_DIR/nis_state
+
+export STAFF_GROUP=zfsgrp
+export STAFF1=staff1
+export STAFF2=staff2
+
+export OTHER_GROUP=othergrp
+export OTHER1=other1
+export OTHER2=other2
+
+export EVERYONE="$STAFF1 $STAFF2 $OTHER1 $OTHER2"
+
+#
+# 'readonly' is disabled for Linux because it requires remounting the
+# filesystem which is restricted to root for older versions of mount(8).
+#
+if is_linux; then
+ LOCAL_SET="snapshot"
+ LOCAL_DESC_SET="checksum"
+ DESC_SET="compression"
+else
+ LOCAL_SET="snapshot"
+ LOCAL_DESC_SET="readonly,checksum"
+ DESC_SET="compression"
+fi
+export LOCAL_SET
+export LOCAL_DESC_SET
+export DESC_SET
+
+export TESTVOL=testvol.delegate
+export VOLSIZE=150m
+
+export ROOT_TESTVOL=$TESTPOOL/$TESTVOL
+export ROOT_TESTFS=$TESTPOOL/$TESTFS
+export SUBFS=$ROOT_TESTFS/SUBFS
+export SUBFS2=$ROOT_TESTFS/SUBFS2
+
+DATASETS="$ROOT_TESTFS"
+if is_global_zone ; then
+ DATASETS=$DATASETS
+fi
+export DATASETS
diff --git a/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib b/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib
new file mode 100644
index 000000000000..e39b015b21b8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib
@@ -0,0 +1,1713 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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.
+# Copyright 2016 Nexenta Systems, Inc.
+# Copyright (c) 2018 George Melikov. All Rights Reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/delegate/delegate.cfg
+
+#
+# Cleanup exist user/group.
+#
+function cleanup_user_group
+{
+ typeset i
+ for i in $STAFF1 $STAFF2 $OTHER1 $OTHER2 ; do
+ del_user $i
+ done
+ for i in $STAFF_GROUP $OTHER_GROUP ; do
+ del_group $i
+ done
+
+ return 0
+}
+
+#
+# Restore test file system to the original status.
+#
+function restore_root_datasets
+{
+ destroy_dataset "$ROOT_TESTFS" "-Rf"
+ log_must zfs create $ROOT_TESTFS
+
+ if is_global_zone ; then
+ destroy_dataset "$ROOT_TESTVOL" "-Rf"
+ log_must zfs create -V $VOLSIZE $ROOT_TESTVOL
+ block_device_wait
+ fi
+
+ return 0
+}
+
+#
+# Verify the specified user have permission on the dataset
+#
+# $1 dataset
+# $2 permissions which are separated by comma(,)
+# $3-n users
+#
+function verify_perm
+{
+ typeset dtst=$1
+ typeset permissions=$2
+ shift 2
+
+ if [[ -z $@ || -z $permissions || -z $dtst ]]; then
+ return 1
+ fi
+
+ typeset type=$(get_prop type $dtst)
+ permissions=$(echo $permissions | tr -s "," " ")
+
+ typeset user
+ for user in $@; do
+ typeset perm
+ for perm in $permissions; do
+ typeset -i ret=1
+ if [[ $type == "filesystem" ]]; then
+ check_fs_perm $user $perm $dtst
+ ret=$?
+ elif [[ $type == "volume" ]]; then
+ check_vol_perm $user $perm $dtst
+ ret=$?
+ fi
+
+ log_note "Check $type $user $perm $dtst"
+ if ((ret != 0)) ; then
+ log_note "Fail: $user should have $perm" \
+ "on $dtst"
+ return 1
+ fi
+ done
+ done
+
+ return 0
+}
+
+#
+# Verify the specified user have no permission on the dataset
+#
+# $1 dataset
+# $2 permissions which are separated by comma(,)
+# $3-n users
+#
+function verify_noperm
+{
+ typeset dtst=$1
+ typeset permissions=$2
+ shift 2
+
+ if [[ -z $@ || -z $permissions || -z $dtst ]]; then
+ return 1
+ fi
+
+ typeset type=$(get_prop type $dtst)
+ permissions=$(echo $permissions | tr -s "," " ")
+
+ typeset user
+ for user in $@; do
+ typeset perm
+ for perm in $permissions; do
+ typeset -i ret=1
+ if [[ $type == "filesystem" ]]; then
+ check_fs_perm $user $perm $dtst
+ ret=$?
+ elif [[ $type == "volume" ]]; then
+ check_vol_perm $user $perm $dtst
+ ret=$?
+ fi
+
+ if ((ret == 0)) ; then
+ log_note "Fail: $user should not have $perm " \
+ "on $dtst"
+ return 1
+ fi
+ done
+ done
+
+ return 0
+}
+
+function common_perm
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset -i ret=1
+ case $perm in
+ send)
+ verify_send $user $perm $dtst
+ ret=$?
+ ;;
+ allow)
+ verify_allow $user $perm $dtst
+ ret=$?
+ ;;
+ userprop)
+ verify_userprop $user $perm $dtst
+ ret=$?
+ ;;
+ compression|checksum|readonly)
+ verify_ccr $user $perm $dtst
+ ret=$?
+ ;;
+ copies)
+ verify_copies $user $perm $dtst
+ ret=$?
+ ;;
+ reservation)
+ verify_reservation $user $perm $dtst
+ ret=$?
+ ;;
+ *)
+ ret=1
+ ;;
+ esac
+
+ return $ret
+}
+
+function check_fs_perm
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset -i ret=1
+ case $perm in
+ create)
+ verify_fs_create $user $perm $fs
+ ret=$?
+ ;;
+ destroy)
+ verify_fs_destroy $user $perm $fs
+ ret=$?
+ ;;
+ snapshot)
+ verify_fs_snapshot $user $perm $fs
+ ret=$?
+ ;;
+ rollback)
+ verify_fs_rollback $user $perm $fs
+ ret=$?
+ ;;
+ clone)
+ verify_fs_clone $user $perm $fs
+ ret=$?
+ ;;
+ rename)
+ verify_fs_rename $user $perm $fs
+ ret=$?
+ ;;
+ mount)
+ verify_fs_mount $user $perm $fs
+ ret=$?
+ ;;
+ share)
+ verify_fs_share $user $perm $fs
+ ret=$?
+ ;;
+ mountpoint)
+ verify_fs_mountpoint $user $perm $fs
+ ret=$?
+ ;;
+ promote)
+ verify_fs_promote $user $perm $fs
+ ret=$?
+ ;;
+ canmount)
+ verify_fs_canmount $user $perm $fs
+ ret=$?
+ ;;
+ dnodesize)
+ verify_fs_dnodesize $user $perm $fs
+ ret=$?
+ ;;
+ recordsize)
+ verify_fs_recordsize $user $perm $fs
+ ret=$?
+ ;;
+ quota)
+ verify_fs_quota $user $perm $fs
+ ret=$?
+ ;;
+ aclmode)
+ verify_fs_aclmode $user $perm $fs
+ ret=$?
+ ;;
+ aclinherit)
+ verify_fs_aclinherit $user $perm $fs
+ ret=$?
+ ;;
+ snapdir)
+ verify_fs_snapdir $user $perm $fs
+ ret=$?
+ ;;
+ atime|exec|devices|setuid|xattr)
+ verify_fs_aedsx $user $perm $fs
+ ret=$?
+ ;;
+ zoned)
+ verify_fs_zoned $user $perm $fs
+ ret=$?
+ ;;
+ sharenfs)
+ verify_fs_sharenfs $user $perm $fs
+ ret=$?
+ ;;
+ receive)
+ verify_fs_receive $user $perm $fs
+ ret=$?
+ ;;
+ *)
+ common_perm $user $perm $fs
+ ret=$?
+ ;;
+ esac
+
+ return $ret
+}
+
+function check_vol_perm
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset -i ret=1
+ case $perm in
+ destroy)
+ verify_vol_destroy $user $perm $vol
+ ret=$?
+ ;;
+ snapshot)
+ verify_vol_snapshot $user $perm $vol
+ ret=$?
+ ;;
+ rollback)
+ verify_vol_rollback $user $perm $vol
+ ret=$?
+ ;;
+ clone)
+ verify_vol_clone $user $perm $vol
+ ret=$?
+ ;;
+ rename)
+ verify_vol_rename $user $perm $vol
+ ret=$?
+ ;;
+ promote)
+ verify_vol_promote $user $perm $vol
+ ret=$?
+ ;;
+ volsize)
+ verify_vol_volsize $user $perm $vol
+ ret=$?
+ ;;
+ *)
+ common_perm $user $perm $vol
+ ret=$?
+ ;;
+ esac
+
+ return $ret
+}
+
+function setup_unallow_testenv
+{
+ log_must restore_root_datasets
+
+ log_must zfs create $SUBFS
+
+ for dtst in $DATASETS ; do
+ log_must zfs allow -l $STAFF1 $LOCAL_SET $dtst
+ log_must zfs allow -d $STAFF2 $DESC_SET $dtst
+ log_must zfs allow $OTHER1 $LOCAL_DESC_SET $dtst
+ log_must zfs allow $OTHER2 $LOCAL_DESC_SET $dtst
+
+ log_must verify_perm $dtst $LOCAL_SET $STAFF1
+ log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER1
+ log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER2
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must verify_perm $SUBFS $DESC_SET $STAFF2
+ log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER1
+ log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER2
+ fi
+ done
+
+ return 0
+}
+
+#
+# Verify permission send for specified user on the dataset
+# $1 user
+# $2 permission
+# $3 dataset
+#
+function verify_send
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset oldval
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset snap=$dtst@snap.$stamp
+
+ typeset -i ret=1
+
+ log_must zfs snapshot $snap
+ typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
+ typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
+
+ user_run $user eval "zfs send $snap > $bak_user"
+ log_must eval "zfs send $snap > $bak_root"
+
+ if [[ $(checksum $bak_user) == $(checksum $bak_root) ]]; then
+ ret=0
+ fi
+
+ rm -rf $bak_user > /dev/null
+ rm -rf $bak_root > /dev/null
+
+ return $ret
+}
+
+function verify_fs_receive
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset dtst
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset newfs=$fs/newfs.$stamp
+ typeset newvol=$fs/newvol.$stamp
+ typeset bak_user=$TEST_BASE_DIR/bak.$user.$stamp
+ typeset bak_root=$TEST_BASE_DIR/bak.root.$stamp
+
+ log_must zfs create $newfs
+ typeset datasets="$newfs"
+ if is_global_zone ; then
+ log_must zfs create -V $VOLSIZE $newvol
+ block_device_wait
+ datasets="$newfs $newvol"
+ fi
+
+ for dtst in $datasets ; do
+
+ typeset dtstsnap=$dtst@snap.$stamp
+ log_must zfs snapshot $dtstsnap
+
+ log_must eval "zfs send $dtstsnap > $bak_root"
+ log_must_busy zfs destroy -rf $dtst
+
+ user_run $user eval "zfs receive $dtst < $bak_root"
+ if datasetexists $dtstsnap ; then
+ return 1
+ fi
+
+ log_must zfs allow $user create $fs
+ user_run $user eval "zfs receive $dtst < $bak_root"
+ log_must zfs unallow $user create $fs
+ if datasetexists $dtstsnap ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user eval "zfs receive $dtst < $bak_root"
+ log_must zfs unallow $user mount $fs
+ if datasetexists $dtstsnap ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount,create $fs
+ user_run $user eval "zfs receive $dtst < $bak_root"
+ log_must zfs unallow $user mount,create $fs
+ if ! datasetexists $dtstsnap ; then
+ return 1
+ fi
+
+ # check the data integrity
+ log_must eval "zfs send $dtstsnap > $bak_user"
+ log_must_busy zfs destroy -rf $dtst
+ log_must eval "zfs receive $dtst < $bak_root"
+ log_must eval "zfs send $dtstsnap > $bak_root"
+ log_must_busy zfs destroy -rf $dtst
+ if [[ $(checksum $bak_user) != $(checksum $bak_root) ]]; then
+ return 1
+ fi
+
+ rm -rf $bak_user > /dev/null
+ rm -rf $bak_root > /dev/null
+
+ done
+
+ return 0
+}
+
+function verify_userprop
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+
+ user_run $user zfs set "$user:ts=$stamp" $dtst
+ zpool sync ${dtst%%/*}
+ if [[ $stamp != $(get_prop "$user:ts" $dtst) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_ccr
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset oldval
+
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $dtst)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $dtst"
+ user_run $user zfs set $perm=${modes[$n]} $dtst
+ if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_copies
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset oldval
+
+ set -A modes 1 2 3
+ oldval=$(get_prop $perm $dtst)
+ if [[ $oldval -eq 1 ]]; then
+ n=1
+ elif [[ $oldval -eq 2 ]]; then
+ n=2
+ elif [[ $oldval -eq 3 ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $dtst"
+ user_run $user zfs set $perm=${modes[$n]} $dtst
+ if [[ ${modes[$n]} != $(get_prop $perm $dtst) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_reservation
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset value32m=$(( 1024 * 1024 * 32 ))
+ typeset oldval=$(get_prop reservation $dtst)
+ user_run $user zfs set reservation=$value32m $dtst
+ if [[ $value32m != $(get_prop reservation $dtst) ]]; then
+ log_must zfs set reservation=$oldval $dtst
+ return 1
+ fi
+
+ log_must zfs set reservation=$oldval $dtst
+ return 0
+}
+
+function verify_fs_create
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset newfs=$fs/nfs.$stamp
+ typeset newvol=$fs/nvol.$stamp
+
+ user_run $user zfs create $newfs
+ if datasetexists $newfs ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user zfs create $newfs
+ log_must zfs unallow $user mount $fs
+ if ! datasetexists $newfs ; then
+ return 1
+ fi
+
+ log_must zfs destroy $newfs
+
+ if is_global_zone ; then
+ # mount permission is required for sparse volume
+ user_run $user zfs create -V 150m -s $newvol
+ block_device_wait
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user zfs create -V 150m -s $newvol
+ log_must zfs unallow $user mount $fs
+ if ! datasetexists $newvol ; then
+ return 1
+ fi
+
+ block_device_wait
+ log_must zfs destroy $newvol
+ block_device_wait
+
+ # mount and reserveration permission are
+ # required for normal volume
+ user_run $user zfs create -V 150m $newvol
+ block_device_wait
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user zfs create -V 150m $newvol
+ block_device_wait
+ log_must zfs unallow $user mount $fs
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user reservation $fs
+ user_run $user zfs create -V 150m $newvol
+ block_device_wait
+ log_must zfs unallow $user reservation $fs
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user refreservation $fs
+ user_run $user zfs create -V 150m $newvol
+ block_device_wait
+ log_must zfs unallow $user refreservation $fs
+ if datasetexists $newvol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ log_must zfs allow $user reservation $fs
+ log_must zfs allow $user refreservation $fs
+ user_run $user zfs create -V 150m $newvol
+ log_must zfs unallow $user mount $fs
+ log_must zfs unallow $user reservation $fs
+ log_must zfs unallow $user refreservation $fs
+ if ! datasetexists $newvol ; then
+ return 1
+ fi
+
+ block_device_wait
+ log_must zfs destroy $newvol
+ block_device_wait
+ fi
+
+ return 0
+}
+
+function verify_fs_destroy
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ if ! ismounted $fs ; then
+ user_run $user zfs destroy $fs
+ if datasetexists $fs ; then
+ return 1
+ fi
+ fi
+
+ if ismounted $fs ; then
+ user_run $user zfs destroy $fs
+ if ! datasetexists $fs ; then
+ return 1
+ fi
+
+ # mount permission is required
+ log_must zfs allow $user mount $fs
+ user_run $user zfs destroy $fs
+ if datasetexists $fs ; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+# Verify that given the correct delegation, a regular user can:
+# Take a snapshot of an unmounted dataset
+# Take a snapshot of a mounted dataset
+# Create a snapshot by making a directory in the .zfs/snapshot directory
+function verify_fs_snapshot
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset snap=$fs@snap.$stamp
+ typeset mntpt=$(get_prop mountpoint $fs)
+
+ if [[ "yes" == $(get_prop mounted $fs) ]]; then
+ log_must zfs umount $fs
+ fi
+
+ user_run $user zfs snapshot $snap
+ if ! datasetexists $snap ; then
+ return 1
+ fi
+ log_must zfs destroy $snap
+
+ if [[ "no" == $(get_prop mounted $fs) ]]; then
+ log_must zfs mount $fs
+ fi
+
+ user_run $user zfs snapshot $snap
+ if ! datasetexists $snap ; then
+ return 1
+ fi
+ log_must zfs destroy $snap
+
+ # Creating snaps via mkdir is not supported on FreeBSD
+ if ! is_freebsd; then
+ typeset snapdir=${mntpt}/.zfs/snapshot/snap.$stamp
+ user_run $user mkdir $snapdir
+ if ! datasetexists $snap ; then
+ return 1
+ fi
+ log_must zfs destroy $snap
+ fi
+
+ return 0
+}
+
+function verify_fs_rollback
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset snap=$fs@snap.$stamp
+ typeset mntpt=$(get_prop mountpoint $fs)
+
+ oldval=$(datasetcksum $fs)
+ log_must zfs snapshot $snap
+
+ if ! ismounted $fs; then
+ log_must zfs mount $fs
+ fi
+ log_must touch $mntpt/testfile.$stamp
+
+ user_run $user zfs rollback -R $snap
+ if is_global_zone ; then
+ if [[ $oldval != $(datasetcksum $fs) ]]; then
+ return 1
+ fi
+ else
+ # datasetcksum can not be used in local zone
+ if [[ -e $mntpt/testfile.$stamp ]]; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function verify_fs_clone
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basefs=${fs%/*}
+ typeset snap=$fs@snap.$stamp
+ typeset clone=$basefs/cfs.$stamp
+
+ log_must zfs snapshot $snap
+ user_run $user zfs clone $snap $clone
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user create $basefs
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user create $basefs
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $basefs
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user mount $basefs
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $basefs
+ log_must zfs allow $user create $basefs
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user create $basefs
+ log_must zfs unallow $user mount $basefs
+ if ! datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs destroy -R $snap
+
+ return 0
+}
+
+function verify_fs_rename
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basefs=${fs%/*}
+ typeset snap=$fs@snap.$stamp
+ typeset renamefs=$basefs/nfs.$stamp
+
+ if ! ismounted $fs; then
+ log_must zfs mount $fs
+ fi
+
+ # case 1
+ user_run $user zfs rename $fs $renamefs
+ if datasetexists $renamefs ; then
+ return 1
+ fi
+
+ # case 2
+ log_must zfs allow $user create $basefs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user create $basefs
+ if datasetexists $renamefs ; then
+ return 1
+ fi
+
+ # case 3
+ log_must zfs allow $user mount $basefs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user mount $basefs
+ if datasetexists $renamefs ; then
+ return 1
+ fi
+
+ # case 4
+ log_must zfs allow $user mount $fs
+ user_run $user zfs rename $fs $renamefs
+ if datasetexists $renamefs ; then
+ log_must zfs unallow $user mount $renamefs
+ return 1
+ fi
+ log_must zfs unallow $user mount $fs
+
+ # case 5
+ log_must zfs allow $user create $basefs
+ log_must zfs allow $user mount $fs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user create $basefs
+ if datasetexists $renamefs ; then
+ log_must zfs unallow $user mount $renamefs
+ return 1
+ fi
+ log_must zfs unallow $user mount $fs
+
+ # case 6
+ log_must zfs allow $user mount $basefs
+ log_must zfs allow $user mount $fs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user mount $basefs
+ if datasetexists $renamefs ; then
+ log_must zfs unallow $user mount $renamefs
+ return 1
+ fi
+ log_must zfs unallow $user mount $fs
+
+ # case 7
+ log_must zfs allow $user create $basefs
+ log_must zfs allow $user mount $basefs
+ user_run $user zfs rename $fs $renamefs
+ log_must zfs unallow $user mount $basefs
+ log_must zfs unallow $user create $basefs
+ if ! datasetexists $renamefs ; then
+ return 1
+ fi
+
+ log_must zfs rename $renamefs $fs
+
+ return 0
+}
+
+function verify_fs_mount
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset mntpt=$(get_prop mountpoint $fs)
+ typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
+
+ if ismounted $fs ; then
+ user_run $user zfs unmount $fs
+ if ismounted $fs ; then
+ return 1
+ fi
+ fi
+
+ if ! ismounted $fs ; then
+ log_must zfs set mountpoint=$newmntpt $fs
+ log_must rm -rf $newmntpt
+ log_must mkdir $newmntpt
+
+ user_run $user zfs mount $fs
+ if ismounted $fs ; then
+ return 1
+ fi
+
+ # mountpoint's owner must be the user
+ log_must chown $user $newmntpt
+ user_run $user zfs mount $fs
+ if ! ismounted $fs ; then
+ return 1
+ fi
+ log_must zfs umount $fs
+ log_must rm -rf $newmntpt
+ log_must zfs set mountpoint=$mntpt $fs
+ fi
+
+ return 0
+}
+
+function verify_fs_share
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+ typeset -i ret=0
+
+ svcadm enable -rs nfs/server
+ typeset stat=$(svcs -H -o STA nfs/server:default)
+ if [[ $stat != "ON" ]]; then
+ log_fail "Could not enable nfs/server"
+ fi
+
+ log_must zfs set sharenfs=on $fs
+ zfs unshare $fs
+
+ user_run $user zfs share $fs
+ if ! is_shared $fs; then
+ ret=1
+ fi
+
+ zfs unshare $fs
+ log_must zfs set sharenfs=off $fs
+
+ return $ret
+}
+
+function verify_fs_mountpoint
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset mntpt=$(get_prop mountpoint $fs)
+ typeset newmntpt=$TEST_BASE_DIR/mnt.$stamp
+
+ if ! ismounted $fs ; then
+ user_run $user zfs set mountpoint=$newmntpt $fs
+ if [[ $newmntpt != \
+ $(get_prop mountpoint $fs) ]] ; then
+ return 1
+ fi
+ log_must zfs set mountpoint=$mntpt $fs
+ fi
+
+ if ismounted $fs ; then
+ user_run $user zfs set mountpoint=$newmntpt $fs
+ if [[ $mntpt != $(get_prop mountpoint $fs) ]]; then
+ return 1
+ fi
+
+ # require mount permission when fs is mounted
+ log_must zfs allow $user mount $fs
+ user_run $user zfs set mountpoint=$newmntpt $fs
+ log_must zfs unallow $user mount $fs
+ if [[ $newmntpt != \
+ $(get_prop mountpoint $fs) ]] ; then
+ return 1
+ fi
+ log_must zfs set mountpoint=$mntpt $fs
+ fi
+
+ return 0
+}
+
+function verify_fs_promote
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basefs=${fs%/*}
+ typeset snap=$fs@snap.$stamp
+ typeset clone=$basefs/cfs.$stamp
+
+ log_must zfs snapshot $snap
+ log_must zfs clone $snap $clone
+ log_must zfs promote $clone
+
+ typeset fs_orig=$(get_prop origin $fs)
+ typeset clone_orig=$(get_prop origin $clone)
+
+ user_run $user zfs promote $fs
+ # promote should fail if original fs does not have
+ # promote permission
+ if [[ $fs_orig != $(get_prop origin $fs) || \
+ $clone_orig != $(get_prop origin $clone) ]]; then
+ return 1
+ fi
+
+ log_must zfs allow $user promote $clone
+ user_run $user zfs promote $fs
+ log_must zfs unallow $user promote $clone
+ if [[ $fs_orig != $(get_prop origin $fs) || \
+ $clone_orig != $(get_prop origin $clone) ]]; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ user_run $user zfs promote $fs
+ log_must zfs unallow $user mount $fs
+ if [[ $fs_orig != $(get_prop origin $fs) || \
+ $clone_orig != $(get_prop origin $clone) ]]; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $fs
+ log_must zfs allow $user promote $clone
+ user_run $user zfs promote $fs
+ log_must zfs unallow $user promote $clone
+ log_must zfs unallow $user mount $fs
+ if [[ $snap != $(get_prop origin $clone) || \
+ $clone_orig != $(get_prop origin $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_canmount
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ typeset stamp=${perm}.${user}.$RANDOM
+
+ if ! ismounted $fs ; then
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $fs"
+ user_run $user zfs set $perm=${modes[$n]} $fs
+ if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ fi
+
+
+ # fs is mounted
+ if ismounted $fs ; then
+ # property value does not change if
+ # no mount permission
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $fs"
+ log_must zfs allow $user mount $fs
+ user_run $user zfs set $perm=${modes[$n]} $fs
+ log_must zfs unallow $user mount $fs
+ if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function verify_fs_recordsize
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset value8k=$(( 1024 * 8 ))
+ user_run $user zfs set recordsize=$value8k $fs
+ if [[ $value8k != $(get_prop recordsize $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_dnodesize
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+ value="2k"
+
+ user_run $user zfs set dnodesize=$value $fs
+ if [[ $value != $(get_prop dnodesize $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_quota
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset value32m=$(( 1024 * 1024 * 32 ))
+ user_run $user zfs set quota=$value32m $fs
+ if [[ $value32m != $(get_prop quota $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_aclmode
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ set -A modes "discard" "groupmask" "passthrough"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "discard" ]]; then
+ n=1
+ elif [[ $oldval == "groupmask" ]]; then
+ n=2
+ elif [[ $oldval == "passthrough" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set aclmode=${modes[$n]} $fs"
+ user_run $user zfs set aclmode=${modes[$n]} $fs
+ if [[ ${modes[$n]} != $(get_prop aclmode $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_aclinherit
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ #
+ # PSARC/2008/231 change the default value of aclinherit to "restricted"
+ # but still keep the old interface of "secure"
+ #
+
+ typeset oldval
+ set -A modes "discard" "noallow" "secure" "passthrough"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "discard" ]]; then
+ n=1
+ elif [[ $oldval == "noallow" ]]; then
+ n=2
+ elif [[ $oldval == "secure" || $oldval == "restricted" ]]; then
+ n=3
+ elif [[ $oldval == "passthrough" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set aclinherit=${modes[$n]} $fs"
+ user_run $user zfs set aclinherit=${modes[$n]} $fs
+
+ typeset newval=$(get_prop aclinherit $fs)
+ if [[ ${modes[$n]} == "secure" && $newval == "restricted" ]]; then
+ return 0
+ elif [[ ${modes[$n]} != $(get_prop aclinherit $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_snapdir
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ set -A modes "visible" "hidden"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "visible" ]]; then
+ n=1
+ elif [[ $oldval == "hidden" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set snapdir=${modes[$n]} $fs"
+ user_run $user zfs set snapdir=${modes[$n]} $fs
+ if [[ ${modes[$n]} != $(get_prop snapdir $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_aedsx
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $fs"
+ user_run $user zfs set $perm=${modes[$n]} $fs
+ if [[ ${modes[$n]} != $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_fs_zoned
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+
+ typeset oldval
+ set -A modes "on" "off"
+ oldval=$(get_prop $perm $fs)
+ if [[ $oldval == "on" ]]; then
+ n=1
+ elif [[ $oldval == "off" ]]; then
+ n=0
+ fi
+ log_note "$user zfs set $perm=${modes[$n]} $fs"
+ if is_global_zone ; then
+ if ! ismounted $fs ; then
+ user_run $user zfs set \
+ $perm=${modes[$n]} $fs
+ if [[ ${modes[$n]} != \
+ $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ if [[ $n -eq 0 ]]; then
+ log_mustnot zfs mount $fs
+ else
+ log_must zfs mount $fs
+ fi
+ fi
+
+ if ismounted $fs; then
+ # n always is 1 in this case
+ user_run $user zfs set \
+ $perm=${modes[$n]} $fs
+ if [[ $oldval != \
+ $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+
+ # mount permission is needed
+ # to make zoned=on
+ log_must zfs allow $user mount $fs
+ user_run $user zfs set \
+ $perm=${modes[$n]} $fs
+ log_must zfs unallow $user mount $fs
+ if [[ ${modes[$n]} != \
+ $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ fi
+ fi
+
+ if ! is_global_zone; then
+ user_run $user zfs set $perm=${modes[$n]} $fs
+ if [[ $oldval != $(get_prop $perm $fs) ]]; then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function verify_fs_sharenfs
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset fs=$3
+ typeset nmode omode
+
+ omode=$(get_prop $perm $fs)
+ if [[ $omode == "off" ]]; then
+ nmode="on"
+ else
+ nmode="off"
+ fi
+
+ log_note "$user zfs set $perm=$nmode $fs"
+ user_run $user zfs set $perm=$nmode $fs
+ if [[ $(get_prop $perm $fs) != $nmode ]]; then
+ return 1
+ fi
+
+ log_note "$user zfs set $perm=$omode $fs"
+ user_run $user zfs set $perm=$omode $fs
+ if [[ $(get_prop $perm $fs) != $omode ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_destroy
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ user_run $user zfs destroy $vol
+ if ! datasetexists $vol ; then
+ return 1
+ fi
+
+ # mount permission is required
+ log_must zfs allow $user mount $vol
+ user_run $user zfs destroy $vol
+ if datasetexists $vol ; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_snapshot
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+
+ user_run $user zfs snapshot $snap
+ if datasetexists $snap ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $vol
+ user_run $user zfs snapshot $snap
+ log_must zfs unallow $user mount $vol
+ if ! datasetexists $snap ; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_rollback
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+
+ typeset oldval
+ log_must zfs snapshot $snap
+ oldval=$(datasetcksum $vol)
+
+ log_must dd if=/dev/urandom of=$ZVOL_RDEVDIR/$vol \
+ bs=512 count=1
+
+ user_run $user zfs rollback -R $snap
+ sleep 10
+ if [[ $oldval == $(datasetcksum $vol) ]]; then
+ return 1
+ fi
+
+ # rollback on volume has to be with mount permission
+ log_must zfs allow $user mount $vol
+ user_run $user zfs rollback -R $snap
+ sleep 10
+ log_must zfs unallow $user mount $vol
+ if [[ $oldval != $(datasetcksum $vol) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_clone
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+ typeset clone=$basevol/cvol.$stamp
+
+ log_must zfs snapshot $snap
+
+ user_run $user zfs clone $snap $clone
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user create $basevol
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user create $basevol
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $basevol
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user mount $basevol
+ if datasetexists $clone ; then
+ return 1
+ fi
+
+ # require create permission on parent and
+ # mount permission on itself as well
+ log_must zfs allow $user mount $basevol
+ log_must zfs allow $user create $basevol
+ user_run $user zfs clone $snap $clone
+ log_must zfs unallow $user create $basevol
+ log_must zfs unallow $user mount $basevol
+ if ! datasetexists $clone ; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_rename
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+ typeset clone=$basevol/cvol.$stamp
+ typeset renamevol=$basevol/nvol.$stamp
+
+ user_run $user zfs rename $vol $renamevol
+ if datasetexists $renamevol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user create $basevol
+ user_run $user zfs rename $vol $renamevol
+ log_must zfs unallow $user create $basevol
+ if datasetexists $renamevol ; then
+ return 1
+ fi
+
+ log_must zfs allow $user mount $basevol
+ user_run $user zfs rename $vol $renamevol
+ log_must zfs unallow $user mount $basevol
+ if datasetexists $renamevol ; then
+ return 1
+ fi
+
+ # require both create permission on parent and
+ # mount permission on parent as well
+ log_must zfs allow $user mount $basevol
+ log_must zfs allow $user create $basevol
+ user_run $user zfs rename $vol $renamevol
+ log_must zfs unallow $user mount $basevol
+ log_must zfs unallow $user create $basevol
+ if ! datasetexists $renamevol ; then
+ return 1
+ fi
+
+ log_must zfs rename $renamevol $vol
+
+ return 0
+}
+
+function verify_vol_promote
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset stamp=${perm}.${user}.$RANDOM
+ typeset basevol=${vol%/*}
+ typeset snap=$vol@snap.$stamp
+ typeset clone=$basevol/cvol.$stamp
+
+ log_must zfs snapshot $snap
+ log_must zfs clone $snap $clone
+ log_must zfs promote $clone
+
+ typeset vol_orig=$(get_prop origin $vol)
+ typeset clone_orig=$(get_prop origin $clone)
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 1
+ user_run $user zfs promote $vol
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 2
+ log_must zfs allow $user promote $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user promote $clone
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 3
+ log_must zfs allow $user mount $vol
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user mount $vol
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 4
+ log_must zfs allow $user mount $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user mount $clone
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 5
+ log_must zfs allow $user promote $clone
+ log_must zfs allow $user mount $vol
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user promote $clone
+ log_must zfs unallow $user mount $vol
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 6
+ log_must zfs allow $user promote $clone
+ log_must zfs allow $user mount $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user promote $clone
+ log_must zfs unallow $user mount $vol
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote should fail if $vol and $clone
+ # miss either mount or promote permission
+ # case 7
+ log_must zfs allow $user mount $vol
+ log_must zfs allow $user mount $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user mount $vol
+ log_must zfs unallow $user mount $clone
+ if [[ $vol_orig != $(get_prop origin $vol) || \
+ $clone_orig != $(get_prop origin $clone) ]];
+ then
+ return 1
+ fi
+
+ # promote only succeeds when $vol and $clone
+ # have both mount and promote permission
+ # case 8
+ log_must zfs allow $user promote $clone
+ log_must zfs allow $user mount $vol
+ log_must zfs allow $user mount $clone
+ user_run $user zfs promote $vol
+ log_must zfs unallow $user promote $clone
+ log_must zfs unallow $user mount $vol
+ log_must zfs unallow $user mount $clone
+ if [[ $snap != $(get_prop origin $clone) || \
+ $clone_orig != $(get_prop origin $vol) ]]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_vol_volsize
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset vol=$3
+
+ typeset oldval
+ oldval=$(get_prop volsize $vol)
+ (( newval = oldval * 2 ))
+
+ reserv_size=$(get_prop refreservation $vol)
+
+ if [[ "0" == $reserv_size ]]; then
+ # sparse volume
+ user_run $user zfs set volsize=$newval $vol
+ if [[ $oldval == $(get_prop volsize $vol) ]];
+ then
+ return 1
+ fi
+
+ else
+ # normal volume, reservation permission
+ # is required
+ user_run $user zfs set volsize=$newval $vol
+ if [[ $newval == $(get_prop volsize $vol) ]];
+ then
+ return 1
+ fi
+
+ log_must zfs allow $user reservation $vol
+ log_must zfs allow $user refreservation $vol
+ user_run $user zfs set volsize=$newval $vol
+ log_must zfs unallow $user reservation $vol
+ log_must zfs unallow $user refreservation $vol
+ if [[ $oldval == $(get_prop volsize $vol) ]];
+ then
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+function verify_allow
+{
+ typeset user=$1
+ typeset perm=$2
+ typeset dtst=$3
+
+ typeset -i ret
+
+ user_run $user zfs allow $user allow $dtst
+ ret=$?
+ if [[ $ret -eq 0 ]]; then
+ return 1
+ fi
+
+ log_must zfs allow $user copies $dtst
+ user_run $user zfs allow $user copies $dtst
+ ret=$?
+ log_must zfs unallow $user copies $dtst
+ if [[ $ret -eq 1 ]]; then
+ return 1
+ fi
+
+ return 0
+
+}
diff --git a/tests/zfs-tests/tests/functional/delegate/setup.ksh b/tests/zfs-tests/tests/functional/delegate/setup.ksh
new file mode 100755
index 000000000000..2f13da750436
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/setup.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) 2013, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2018 George Melikov. All Rights Reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+if is_illumos; then
+ # check svc:/network/nis/client:default state
+ # disable it if the state is ON
+ # and the state will be restored during cleanup.ksh
+ log_must rm -f $NISSTAFILE
+ if [[ "ON" == $(svcs -H -o sta svc:/network/nis/client:default) ]]; then
+ log_must svcadm disable -t svc:/network/nis/client:default
+ log_must touch $NISSTAFILE
+ fi
+fi
+
+if is_freebsd; then
+ # To pass user mount tests
+ log_must sysctl vfs.usermount=1
+fi
+
+cleanup_user_group
+
+# Create staff group and add two user to it
+log_must add_group $STAFF_GROUP
+log_must add_user $STAFF_GROUP $STAFF1
+log_must add_user $STAFF_GROUP $STAFF2
+
+# Create other group and add two user to it
+log_must add_group $OTHER_GROUP
+log_must add_user $OTHER_GROUP $OTHER1
+log_must add_user $OTHER_GROUP $OTHER2
+
+#
+# Verify the test user can execute the zfs utilities. This may not
+# be possible due to default permissions on the user home directory.
+# This can be resolved granting group read access.
+#
+# chmod 0750 $HOME
+#
+user_run $STAFF1 zfs list
+if [ $? -ne 0 ]; then
+ log_unsupported "Test user $STAFF1 cannot execute zfs utilities"
+fi
+
+DISK=${DISKS%% *}
+
+if is_linux; then
+ log_must set_tunable64 ADMIN_SNAPSHOT 1
+fi
+
+default_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_001_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_001_pos.ksh
new file mode 100755
index 000000000000..1e0ed80d3203
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_001_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# "everyone" is interpreted as the keyword "everyone" whatever the same
+# name user or group is existing.
+#
+# STRATEGY:
+# 1. Create user 'everyone'.
+# 2. Verify 'everyone' is interpreted as keywords.
+# 3. Create group 'everyone'.
+# 4. Verify 'everyone' is interpreted as keywords.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if [[ $user_added == "TRUE" ]] ; then
+ del_user everyone
+ fi
+ if [[ $group_added == "TRUE" ]] ; then
+ del_group everyone
+ fi
+
+ restore_root_datasets
+}
+
+log_assert "everyone' is interpreted as a keyword even if a user " \
+ "or group named 'everyone' exists."
+log_onexit cleanup
+
+eval set -A dataset $DATASETS
+typeset perms="snapshot,reservation,compression,checksum,send,userprop"
+
+log_note "Create a user called 'everyone'."
+if ! id everyone > /dev/null 2>&1; then
+ user_added="TRUE"
+ log_must add_user $STAFF_GROUP everyone
+fi
+for dtst in $DATASETS ; do
+ log_must zfs allow everyone $perms $dtst
+ log_must verify_perm $dtst $perms $EVERYONE "everyone"
+done
+log_must restore_root_datasets
+if [[ $user_added == "TRUE" ]]; then
+ log_must del_user everyone
+fi
+
+log_note "Created a group called 'everyone'."
+if ! cat /etc/group | awk -F: '{print $1}' | \
+ grep -w 'everyone' > /dev/null 2>&1
+then
+ group_added="TRUE"
+ log_must add_group everyone
+fi
+
+for dtst in $DATASETS ; do
+ log_must zfs allow everyone $perms $dtst
+ log_must verify_perm $dtst $perms $EVERYONE
+done
+log_must restore_root_datasets
+if [[ $group_added == "TRUE" ]]; then
+ log_must del_group everyone
+fi
+
+log_pass "everyone is always interpreted as keyword passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_002_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_002_pos.ksh
new file mode 100755
index 000000000000..fc603eae19dc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# <user|group> argument is interpreted as a user if possible, then as a group as
+# possible.
+#
+# STRATEGY:
+# 1. Create user $STAFF_GROUP
+# 2. Delegate permissions to $STAFF_GROUP
+# 3. Verify user $STAFF_GROUP has the permissions.
+# 4. Delete user $STAFF_GROUP and allow the permission to $STAFF_GROUP
+# 5. Verify $STAFF_GROUP is interpreted as group.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if id $STAFF_GROUP > /dev/null 2>&1; then
+ log_must del_user $STAFF_GROUP
+ if is_freebsd; then
+ # pw userdel also deletes the group with the same name
+ # and has no way to opt out of this behavior (yet).
+ # Recreate the group as a workaround.
+ log_must add_group $STAFF_GROUP
+ log_must add_user $STAFF_GROUP $STAFF1
+ log_must add_user $STAFF_GROUP $STAFF2
+ fi
+ fi
+
+ restore_root_datasets
+}
+
+log_assert "<user|group> is interpreted as user if possible, then as group."
+log_onexit cleanup
+
+eval set -A dataset $DATASETS
+typeset perms="snapshot,reservation,compression,checksum,send,userprop"
+
+log_must add_user $STAFF_GROUP $STAFF_GROUP
+for dtst in $DATASETS ; do
+ log_must zfs allow $STAFF_GROUP $perms $dtst
+ log_must verify_perm $dtst $perms $STAFF_GROUP
+ log_must verify_noperm $dtst $perms $STAFF1 $STAFF2
+done
+
+log_must restore_root_datasets
+
+log_must del_user $STAFF_GROUP
+if is_freebsd; then
+ # pw userdel also deletes the group with the same name
+ # and has no way to opt out of this behavior (yet).
+ # Recreate the group as a workaround.
+ log_must add_group $STAFF_GROUP
+ log_must add_user $STAFF_GROUP $STAFF1
+ log_must add_user $STAFF_GROUP $STAFF2
+fi
+for dtst in $datasets ; do
+ log_must zfs allow $STAFF_GROUP $perms $dtst
+ log_must verify_perm $dtst $perms $STAFF1 $STAFF2
+done
+
+log_pass "<user|group> is interpreted as user if possible, then as group passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_003_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_003_pos.ksh
new file mode 100755
index 000000000000..d8eb58ae1d65
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify option '-l' only allow permission to the dataset itself.
+#
+# STRATEGY:
+# 1. Create descendent datasets of $ROOT_TESTFS
+# 2. Select user, group and everyone and set local permission separately.
+# 3. Set locally permissions to $ROOT_TESTFS or $ROOT_TESTVOL.
+# 4. Verify the permissions are only allow on $ROOT_TESTFS or
+# $ROOT_TESTVOL.
+#
+
+verify_runnable "both"
+
+log_assert "Verify option '-l' only allow permission to the dataset itself."
+log_onexit restore_root_datasets
+
+childfs=$ROOT_TESTFS/childfs
+
+eval set -A dataset $DATASETS
+typeset perms="snapshot,reservation,compression,checksum,userprop"
+
+log_must zfs create $childfs
+
+for dtst in $DATASETS ; do
+ log_must zfs allow -l $STAFF1 $perms $dtst
+ log_must verify_perm $dtst $perms $STAFF1
+ if [[ $dtst == $ROOT_TESTFS ]] ; then
+ log_must verify_noperm $childfs $perms \
+ $STAFF1 $STAFF2 $OTHER1 $OTHER2
+ fi
+done
+
+log_must restore_root_datasets
+
+log_must zfs create $childfs
+for dtst in $DATASETS ; do
+ log_must zfs allow -l -g $STAFF_GROUP $perms $dtst
+ log_must verify_perm $dtst $perms $STAFF1 $STAFF2
+ if [[ $dtst == $ROOT_TESTFS ]] ; then
+ log_must verify_noperm $childfs $perms \
+ $STAFF1 $STAFF2 $OTHER1 $OTHER2
+ fi
+done
+
+log_must restore_root_datasets
+
+log_must zfs create $childfs
+for dtst in $DATASETS ; do
+ log_must zfs allow -l -e $perms $dtst
+ log_must verify_perm $dtst $perms $STAFF1 $STAFF2 $OTHER1 $OTHER2
+ if [[ $dtst == $ROOT_TESTFS ]] ; then
+ log_must verify_noperm $childfs $perms \
+ $STAFF1 $STAFF2 $OTHER1 $OTHER2
+ fi
+done
+
+log_must restore_root_datasets
+
+log_pass "Verify option '-l' only allow permission to the dataset itself pass."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_004_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_004_pos.ksh
new file mode 100755
index 000000000000..1462f5ebe984
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify option '-d' allow permission to the descendent datasets, and not
+# for this dataset itself.
+#
+# STRATEGY:
+# 1. Create descendent datasets of $ROOT_TESTFS
+# 2. Select user, group and everyone and set descendent permission
+# separately.
+# 3. Set descendent permissions to $ROOT_TESTFS or $ROOT_TESTVOL.
+# 4. Verify those permissions are allowed to $ROOT_TESTFS's
+# descendent dataset.
+# 5. Verify the permissions are not allowed to $ROOT_TESTFS or
+# $ROOT_TESTVOL.
+#
+
+verify_runnable "both"
+
+log_assert "Verify option '-d' allow permission to the descendent datasets."
+log_onexit restore_root_datasets
+
+childfs=$ROOT_TESTFS/childfs
+
+eval set -A dataset $DATASETS
+typeset perms="snapshot,reservation,compression,checksum,userprop"
+
+# Verify option '-d' only affect sub-datasets
+log_must zfs create $childfs
+for dtst in $DATASETS ; do
+ log_must zfs allow -d $STAFF1 $perms $dtst
+ log_must verify_noperm $dtst $perms $STAFF1
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must verify_perm $childfs $perms $STAFF1
+ fi
+done
+
+log_must restore_root_datasets
+
+# Verify option '-d + -g' affect group in sub-datasets.
+log_must zfs create $childfs
+for dtst in $DATASETS ; do
+ log_must zfs allow -d -g $STAFF_GROUP $perms $dtst
+ log_must verify_noperm $dtst $perms $STAFF2
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must verify_perm $childfs $perms $STAFF2
+ fi
+done
+
+log_must restore_root_datasets
+
+# Verify option '-d + -e' affect everyone in sub-datasets.
+log_must zfs create $childfs
+for dtst in $DATASETS ; do
+ log_must zfs allow -d -e $perms $dtst
+ log_must verify_noperm $dtst $perms $OTHER1 $OTHER2
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must verify_perm $childfs $perms $OTHER1 $OTHER2
+ fi
+done
+
+log_must restore_root_datasets
+
+log_pass "Verify option '-d' allow permission to the descendent datasets pass."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_005_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_005_pos.ksh
new file mode 100755
index 000000000000..3feb598c4ced
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify option '-c' will be granted locally to the creator on any
+# newly-created descendent file systems.
+#
+# STRATEGY:
+# 1. Allow create permissions to everyone on $ROOT_TESTFS locally.
+# 2. Allow '-c' create to $ROOT_TESTFS.
+# 3. chmod 777 the mountpoint of $ROOT_TESTFS
+# 4. Verify only creator can create descendent dataset on
+# $ROOT_TESTFS/$user.
+#
+
+verify_runnable "both"
+
+log_assert "Verify option '-c' will be granted locally to the creator."
+log_onexit restore_root_datasets
+
+eval set -A dataset $DATASETS
+typeset perms="snapshot,reservation,compression,checksum,userprop"
+
+log_must zfs allow -l everyone create,mount $ROOT_TESTFS
+log_must zfs allow -c $perms $ROOT_TESTFS
+
+mntpnt=$(get_prop mountpoint $ROOT_TESTFS)
+log_must chmod 777 $mntpnt
+
+for user in $EVERYONE; do
+ childfs=$ROOT_TESTFS/$user
+
+ user_run $user zfs create $childfs
+
+ for other in $EVERYONE; do
+ #
+ # Verify only the creator has the $perm time permissions.
+ #
+ if [[ $other == $user ]]; then
+ log_must verify_perm $childfs $perms $user
+ else
+ log_must verify_noperm $childfs $perms $other
+ fi
+ done
+done
+
+log_pass "Verify option '-c' will be granted locally to the creator passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh
new file mode 100755
index 000000000000..2fc05dee907a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_006_pos.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Changing permissions in a set will change what is allowed wherever the
+# set is used.
+#
+# STRATEGY:
+# 1. Set create as set @basic.
+# 2. Allow set @basic to $STAFF1 on $ROOT_TESTFS or $ROOT_TESTVOL
+# 3. Verify $STAFF1 has create permissions.
+# 4. Reset snapshot,allow to $basic
+# 5. Verify now $STAFF1 have create,allow,destroy permissions.
+#
+
+verify_runnable "both"
+
+log_assert "Changing permissions in a set will change what is allowed " \
+ "wherever the set is used."
+log_onexit restore_root_datasets
+
+fs1=$ROOT_TESTFS/fs1; fs2=$ROOT_TESTFS/fs2
+log_must zfs create $fs1
+log_must zfs create $fs2
+
+eval set -A dataset $DATASETS
+perms1="snapshot,checksum,reservation"
+
+for dtst in $DATASETS $fs1 $fs2; do
+ log_must zfs allow -s @basic $perms1 $dtst
+ log_must zfs allow $STAFF1 @basic $dtst
+ log_must verify_perm $dtst $perms1 $STAFF1
+done
+
+perms2="send,compression,userprop"
+for dtst in $DATASETS $fs1 $fs2; do
+ log_must zfs allow -s @basic $perms2 $dtst
+ log_must verify_perm $dtst ${perms1},${perms2} $STAFF1
+done
+
+log_pass "Changing permissions in a set will change what is allowed passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_007_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_007_pos.ksh
new file mode 100755
index 000000000000..f3213254b97a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_007_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify the permissions set will be masked on its descendent
+# datasets by same name set.
+#
+# STRATEGY:
+# 1. Create $ROOT_TESTFS/childfs
+# 2. Set permission $perms1 to @set on $ROOT_TESTFS
+# 3. Reset permission $perms2 to @set on $ROOT_TESTFS/childfs
+# 4. Allow @set to $STAFF1 on $ROOT_TESTFS/childfs
+# 5. Verify $perms2 is delegated on $ROOT_TESTFS/childfs and its
+# descendent.
+# 6. Allow @set to $STAFF1 on $ROOT_TESTFS
+# 7. Verify $perms1 is not appended to $STAFF1 on $ROOT_TESTFS/childfs and
+# its descendent since it is masked
+#
+
+verify_runnable "both"
+
+log_assert "Verify permission set can be masked on descendent dataset."
+log_onexit restore_root_datasets
+
+typeset perms1="snapshot,reservation,compression"
+eval set -A dataset $DATASETS
+typeset perms2="checksum,send,userprop"
+
+#
+# Define three level filesystems
+#
+childfs=$ROOT_TESTFS/childfs
+grandchild=$childfs/grandchild
+log_must zfs create $childfs
+log_must zfs create $grandchild
+
+#
+# Setting different permissions to the same set on two levels.
+# But only assign the user at one level.
+#
+log_must zfs allow -s @set $perms1 $ROOT_TESTFS
+log_must zfs allow -s @set $perms2 $childfs
+log_must zfs allow $STAFF1 @set $childfs
+
+#
+# Verify that the user only has the permissions that they were assigned
+# in each filesystem.
+#
+log_must verify_noperm $ROOT_TESTFS $perms1 $STAFF1
+for fs in $childfs $grandchild ; do
+ log_must verify_noperm $fs $perms1 $STAFF1
+ log_must verify_perm $fs $perms2 $STAFF1
+done
+
+#
+# Delegate @set to STAFF1 on ROOT_TESTFS, verify $perms1 will not be appended
+# to its descendent datasets since it is masked
+#
+log_must zfs allow $STAFF1 @set $ROOT_TESTFS
+log_must verify_perm $ROOT_TESTFS $perms1 $STAFF1
+for fs in $childfs $grandchild ; do
+ log_must verify_noperm $fs $perms1 $STAFF1
+ log_must verify_perm $fs $perms2 $STAFF1
+done
+
+# Remove the mask, $perms1 will be allowed to its descendent datasets
+log_must zfs unallow -s @set $childfs
+for fs in $childfs $grandchild ; do
+ log_must verify_noperm $fs $perms2 $STAFF1
+ log_must verify_perm $fs $perms1 $STAFF1
+done
+
+log_pass "Verify permission set can be masked on descendent dataset pass."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_008_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_008_pos.ksh
new file mode 100755
index 000000000000..b0e1df32a64d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_008_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# A non-root user can use 'zfs allow' to delegate permissions that
+# they have, if they also have the 'allow' permission.
+#
+# STRATEGY:
+# 1. Set two set permissions to two datasets locally.
+# 2. Verify the non-root user can use 'zfs allow' if they have
+# 'allow' permission.
+#
+
+verify_runnable "both"
+
+log_assert "Verify non-root user can allow permissions."
+log_onexit restore_root_datasets
+
+perms1="snapshot,reservation"
+perms2="send,compression,checksum,userprop"
+childfs=$ROOT_TESTFS/childfs
+
+log_must zfs create $childfs
+
+for dtst in $DATASETS ; do
+ # Delegate local permission to $STAFF1
+ log_must zfs allow -l $STAFF1 $perms1 $dtst
+ log_must zfs allow -l $STAFF1 allow $dtst
+
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must zfs allow -l $STAFF1 $perms2 $childfs
+ # $perms1 is local permission in $ROOT_TESTFS
+ log_mustnot user_run $STAFF1 zfs allow $OTHER1 $perms1 $childfs
+ log_must verify_noperm $childfs $perms1 $OTHER1
+ fi
+
+ # Verify 'allow' give non-privilege user delegated permission.
+ log_must user_run $STAFF1 zfs allow -l $OTHER1 $perms1 $dtst
+ log_must verify_perm $dtst $perms1 $OTHER1
+
+ # $perms2 was not allowed to $STAFF1, so they do not have
+ # permission to delegate permission to other users.
+ log_mustnot user_run $STAFF1 zfs allow $OTHER1 $perms2 $dtst
+ log_must verify_noperm $dtst $perms2 $OTHER1
+done
+
+log_pass "Verify non-root user can allow permissions passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_009_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_009_neg.ksh
new file mode 100755
index 000000000000..a6f12244ce2f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_009_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs allow can deal with invalid arguments.(Invalid options or combination)
+#
+# STRATEGY:
+# 1. Verify invalid arguments will cause error.
+# 2. Verify non-optional argument was missing will cause error.
+# 3. Verify invalid options cause error.
+#
+
+verify_runnable "both"
+
+log_assert "Verify invalid arguments are handled correctly."
+log_onexit restore_root_datasets
+
+# Permission sets are limited to 64 characters in length.
+longset="set123456789012345678901234567890123456789012345678901234567890123"
+for dtst in $DATASETS ; do
+ log_mustnot eval "zfs allow -s @$longset $dtst"
+ # Create non-existent permission set
+ log_mustnot zfs allow -s @non-existent $dtst
+ log_mustnot zfs allow $STAFF "atime,created,mounted" $dtst
+ log_mustnot zfs allow $dtst $TESTPOOL
+ log_mustnot zfs allow -c $dtst
+ log_mustnot zfs allow -u $STAFF1 $dtst
+ log_mustnot zfs allow -u $STAFF1 -g $STAFF_GROUP "create,destroy" $dtst
+ log_mustnot zfs allow -u $STAFF1 -e "mountpoint" $dtst
+done
+
+log_pass "Invalid arguments are handled correctly."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh
new file mode 100755
index 000000000000..3a8ef5e6251b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_010_pos.ksh
@@ -0,0 +1,194 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Scan the following permissions one by one to verify privileged user
+# has correct permission delegation in datasets.
+#
+# STRATEGY:
+# 1. Delegate all the permission one by one to user on dataset.
+# 2. Verify privileged user has correct permission without any other
+# permissions allowed.
+#
+
+verify_runnable "both"
+
+log_assert "Verify privileged user has correct permissions once which was "\
+ "delegated to him in datasets"
+log_onexit restore_root_datasets
+
+if is_linux; then
+#
+# Results in Results in
+# Permission Filesystem Volume
+#
+# Removed for Linux:
+# - mount - mount(8) does not permit non-superuser mounts
+# - mountpoint - mount(8) does not permit non-superuser mounts
+# - canmount - mount(8) does not permit non-superuser mounts
+# - rename - mount(8) does not permit non-superuser mounts
+# - zoned - zones are not supported
+# - destroy - umount(8) does not permit non-superuser umounts
+# - sharenfs - sharing requires superuser privileges
+# - share - sharing requires superuser privileges
+# - readonly - mount(8) does not permit non-superuser remounts
+#
+set -A perms create true false \
+ snapshot true true \
+ send true true \
+ allow true true \
+ quota true false \
+ reservation true true \
+ dnodesize true false \
+ recordsize true false \
+ checksum true true \
+ compression true true \
+ atime true false \
+ devices true false \
+ exec true false \
+ volsize false true \
+ setuid true false \
+ snapdir true false \
+ userprop true true \
+ aclinherit true false \
+ rollback true true \
+ clone true true \
+ promote true true \
+ xattr true false \
+ receive true false
+
+elif is_freebsd; then
+# Results in Results in
+# Permission Filesystem Volume
+#
+# Removed for FreeBSD
+# - jailed - jailing requires superuser privileges
+# - sharenfs - sharing requires superuser privileges
+# - share - sharing requires superuser privileges
+# - xattr - Not supported on FreeBSD
+#
+set -A perms create true false \
+ snapshot true true \
+ mount true false \
+ send true true \
+ allow true true \
+ quota true false \
+ reservation true true \
+ dnodesize true false \
+ recordsize true false \
+ mountpoint true false \
+ checksum true true \
+ compression true true \
+ canmount true false \
+ atime true false \
+ devices true false \
+ exec true false \
+ volsize false true \
+ setuid true false \
+ readonly true true \
+ snapdir true false \
+ userprop true true \
+ aclmode true false \
+ aclinherit true false \
+ rollback true true \
+ clone true true \
+ rename true true \
+ promote true true \
+ receive true false \
+ destroy true true
+
+else
+
+set -A perms create true false \
+ snapshot true true \
+ mount true false \
+ send true true \
+ allow true true \
+ quota true false \
+ reservation true true \
+ dnodesize true false \
+ recordsize true false \
+ mountpoint true false \
+ checksum true true \
+ compression true true \
+ canmount true false \
+ atime true false \
+ devices true false \
+ exec true false \
+ volsize false true \
+ setuid true false \
+ readonly true true \
+ snapdir true false \
+ userprop true true \
+ aclmode true false \
+ aclinherit true false \
+ rollback true true \
+ clone true true \
+ rename true true \
+ promote true true \
+ zoned true false \
+ xattr true false \
+ receive true false \
+ destroy true true
+
+if is_global_zone; then
+ typeset -i n=${#perms[@]}
+ perms[((n))]="sharenfs"; perms[((n+1))]="true"; perms[((n+2))]="false"
+ perms[((n+3))]="share"; perms[((n+4))]="true"; perms[((n+5))]="false"
+fi
+fi
+
+for dtst in $DATASETS; do
+ typeset -i k=1
+ typeset type=$(get_prop type $dtst)
+ [[ $type == "volume" ]] && k=2
+
+ typeset -i i=0
+ while (( i < ${#perms[@]} )); do
+ log_must zfs allow $STAFF1 ${perms[$i]} $dtst
+
+ if [[ ${perms[((i+k))]} == "true" ]]; then
+ log_must verify_perm $dtst ${perms[$i]} $STAFF1
+ else
+ log_must verify_noperm $dtst ${perms[$i]} $STAFF1
+ fi
+
+ log_must restore_root_datasets
+
+ ((i += 3))
+ done
+done
+
+log_pass "Verify privileged user has correct permissions " \
+ "in datasets passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_011_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_011_neg.ksh
new file mode 100755
index 000000000000..d4203a814341
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_011_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify zpool subcmds and system readonly properties can't be delegated.
+#
+# STRATEGY:
+# 1. Loop all the zpool subcmds and readonly properties, except permission
+# 'create' & 'destroy'.
+# 2. Verify those subcmd or properties can't be delegated.
+#
+
+verify_runnable "both"
+
+log_assert "Verify zpool subcmds and system readonly properties can't be " \
+ "delegated."
+log_onexit restore_root_datasets
+
+set -A invalid_perms \
+ add remove list iostat \
+ status offline online clear \
+ attach detach replace scrub \
+ export import upgrade \
+ type creation used available \
+ referenced compressratio mounted
+
+for dtst in $DATASETS ; do
+ typeset -i i=0
+
+ while ((i < ${#invalid_perms[@]})); do
+ log_mustnot zfs allow $STAFF1 ${invalid_perms[$i]} $dtst
+
+ ((i += 1))
+ done
+done
+
+log_pass "Verify zpool subcmds and system readonly properties passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.ksh
new file mode 100755
index 000000000000..fd95db92e049
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_allow_012_neg.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Scan all permissions one by one to verify privileged user
+# can not use permissions properly when delegation property is set off
+#
+# STRATEGY:
+# 1. Delegate all the permission one by one to user on dataset.
+# 2. Verify privileged user can not use permissions properly when
+# delegation property is off
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must zpool set delegation=on $TESTPOOL
+ log_must restore_root_datasets
+}
+
+log_assert "Verify privileged user can not use permissions properly when " \
+ "delegation property is set off"
+log_onexit cleanup
+
+
+if is_linux; then
+set -A perms create snapshot mount send allow quota reservation \
+ recordsize mountpoint checksum compression canmount atime \
+ devices exec volsize setuid readonly snapdir userprop \
+ rollback clone rename promote dnodesize \
+ zoned xattr receive destroy
+elif is_freebsd; then
+set -A perms create snapshot mount send allow quota reservation \
+ recordsize mountpoint checksum compression canmount atime \
+ devices exec volsize setuid readonly snapdir userprop \
+ aclmode aclinherit rollback clone rename promote dnodesize \
+ jailed receive destroy
+else
+set -A perms create snapshot mount send allow quota reservation \
+ recordsize mountpoint checksum compression canmount atime \
+ devices exec volsize setuid readonly snapdir userprop \
+ aclmode aclinherit rollback clone rename promote dnodesize \
+ zoned xattr receive destroy sharenfs share
+fi
+
+log_must zpool set delegation=off $TESTPOOL
+
+for dtst in $DATASETS; do
+ typeset -i i=0
+ while (( i < ${#perms[@]} )); do
+
+ log_must zfs allow $STAFF1 ${perms[$i]} $dtst
+ log_must verify_noperm $dtst ${perms[$i]} $STAFF1
+
+ log_must restore_root_datasets
+ ((i += 1))
+ done
+done
+
+log_pass "Verify privileged user can not use permissions properly when " \
+ "delegation property is set off"
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_001_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_001_pos.ksh
new file mode 100755
index 000000000000..178d250ca529
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_001_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify '-l' only removed the local permissions.
+#
+# STRATEGY:
+# 1. Set up unallow test model.
+# 2. Implement unallow -l to $ROOT_TESTFS or $TESTVOL
+# 3. Verify '-l' only remove the local permissions.
+#
+
+verify_runnable "both"
+
+log_assert "Verify '-l' only removed the local permissions."
+log_onexit restore_root_datasets
+
+log_must setup_unallow_testenv
+
+for dtst in $DATASETS ; do
+ log_must zfs unallow -l $STAFF1 $dtst
+ log_must verify_noperm $dtst $LOCAL_SET $STAFF1
+
+ log_must zfs unallow -l $OTHER1 $dtst
+ log_must verify_noperm $dtst $LOCAL_DESC_SET $OTHER1
+
+ log_must verify_perm $dtst $LOCAL_DESC_SET $OTHER2
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER1 $OTHER2
+ log_must verify_perm $SUBFS $DESC_SET $STAFF2
+ fi
+done
+
+log_pass "Verify '-l' only removed the local permissions passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_002_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_002_pos.ksh
new file mode 100755
index 000000000000..ea1de97614f3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_002_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify '-d' only remove the permissions on descendent filesystem.
+#
+# STRATEGY:
+# 1. Set up unallow test model.
+# 2. Implement unallow -d to $ROOT_TESTFS
+# 3. Verify '-d' only remove the permissions on descendent filesystem.
+#
+
+verify_runnable "both"
+
+log_assert "Verify '-d' only removed the descendent permissions."
+log_onexit restore_root_datasets
+
+log_must setup_unallow_testenv
+
+log_must zfs unallow -d $STAFF2 $ROOT_TESTFS
+log_must verify_noperm $SUBFS $DESC_SET $STAFF2
+
+log_must zfs unallow -d $OTHER1 $ROOT_TESTFS
+log_must verify_noperm $SUBFS $LOCAL_DESC_SET $OTHER1
+log_must verify_perm $ROOT_TESTFS $LOCAL_DESC_SET $OTHER1
+
+log_must verify_perm $ROOT_TESTFS $LOCAL_DESC_SET $OTHER2
+log_must verify_perm $SUBFS $LOCAL_DESC_SET $OTHER2
+
+log_pass "Verify '-d' only removed the descendent permissions passed"
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_003_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_003_pos.ksh
new file mode 100755
index 000000000000..35eb9a961ebc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify options '-r' or '-l' + '-d' will unallow permission to this
+# dataset and the descendent datasets.
+#
+# STRATEGY:
+# 1. Set up unallow test model.
+# 2. Implement unallow -l -d to $ROOT_TESTFS or $ROOT_TESTVOL without
+# options.
+# 3. Verify '-l' + '-d' will unallow local + descendent permission.
+# 4. Verify '-r' will unallow local + descendent permission.
+#
+
+verify_runnable "both"
+
+log_assert "Verify options '-r' and '-l'+'-d' will unallow permission to " \
+ "this dataset and the descendent datasets."
+log_onexit restore_root_datasets
+
+log_must setup_unallow_testenv
+
+for dtst in $DATASETS ; do
+ log_must zfs unallow $STAFF1 $dtst
+ log_must zfs unallow -l -d $STAFF2 $dtst
+ log_must verify_noperm $dtst $LOCAL_SET $STAFF1
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must verify_noperm $SUBFS $DESC_SET $STAFF2
+ fi
+
+ log_must zfs unallow -l -d $OTHER1 $dtst
+ log_must zfs unallow -r $OTHER2 $dtst
+ log_must verify_noperm $dtst $LOCAL_DESC_SET $OTHER1 $OTHER2
+ if [[ $dtst == $ROOT_TESTFS ]]; then
+ log_must verify_noperm $SUBFS $LOCAL_DESC_SET $OTHER1 $OTHER2
+ fi
+done
+
+log_pass "Verify options '-r' and '-l'+'-d' function passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_004_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_004_pos.ksh
new file mode 100755
index 000000000000..d41d76bd0950
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_004_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.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify '-s' will remove permissions from the named set.
+#
+# STRATEGY:
+# 1. Set @basic set to $ROOT_TESTFS or $ROOT_TESTVOL and allow @basic
+# to $STAFF1
+# 2. Verify $STAFF1 have @basic permissions.
+# 3. Verify '-s' will remove permission from the named set.
+#
+
+verify_runnable "both"
+
+log_assert "Verify '-s' will remove permissions from the named set."
+log_onexit restore_root_datasets
+
+for dtst in $DATASETS ; do
+ log_must zfs allow -s @basic $LOCAL_DESC_SET $dtst
+ log_must zfs allow -u $STAFF1 @basic $dtst
+
+ log_must verify_perm $dtst $LOCAL_DESC_SET $STAFF1
+ log_must zfs unallow -s @basic $LOCAL_DESC_SET $dtst
+ log_must verify_noperm $dtst $LOCAL_DESC_SET $STAFF1
+done
+
+log_pass "Verify '-s' will remove permissions from the named set passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_005_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_005_pos.ksh
new file mode 100755
index 000000000000..a97f500ea98e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify option '-c' will remove the created permission set.
+#
+# STRATEGY:
+# 1. Set created time set to $ROOT_TESTFS.
+# 2. Allow permission create to $STAFF1 on $ROOT_TESTFS.
+# 3. Create $SUBFS and verify $STAFF1 have created time permissions.
+# 4. Verify $STAFF1 has created time permission.
+# 5. Unallow created time permission with option '-c'.
+# 6. Created $SUBFS and verify $STAFF1 have not created time permissions.
+#
+
+verify_runnable "both"
+
+log_assert "Verify option '-c' will remove the created permission set."
+log_onexit restore_root_datasets
+
+log_must zfs allow -c $LOCAL_SET $ROOT_TESTFS
+log_must zfs allow -l $STAFF1 create,mount $ROOT_TESTFS
+
+# Create $SUBFS and verify $SUBFS has created time permissions.
+user_run $STAFF1 zfs create $SUBFS
+if ! datasetexists $SUBFS ; then
+ log_fail "ERROR: ($STAFF1): zfs create $SUBFS"
+fi
+log_must verify_perm $SUBFS $LOCAL_SET $STAFF1
+
+#
+# After unallow -c, create $SUBFS2 and verify $SUBFS2 has not created time
+# permissions any more.
+#
+log_must zfs unallow -c $LOCAL_SET $ROOT_TESTFS
+user_run $STAFF1 zfs create $SUBFS2
+if ! datasetexists $SUBFS2 ; then
+ log_fail "ERROR: ($STAFF1): zfs create $SUBFS2"
+fi
+log_must verify_noperm $SUBFS2 $LOCAL_SET $STAFF1
+
+log_pass "Verify option '-c' will remove the created permission set passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_006_pos.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_006_pos.ksh
new file mode 100755
index 000000000000..2bba43de9d14
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify option '-u', '-g' and '-e' only removed the specified type
+# permissions set.
+#
+# STRATEGY:
+# 1. Allow '-u' '-g' & '-e' to $STAFF1 on ROOT_TESTFS or $ROOT_TESTVOL.
+# 2. Unallow '-u' '-g' & '-e' on $ROOT_TESTFS or $ROOT_TESTVOL separately.
+# 3. Verify permissions on $ROOT_TESTFS or $ROOT_TESTVOL separately.
+#
+
+verify_runnable "both"
+
+log_assert "Verify option '-u', '-g' and '-e' only removed the specified type "\
+ "permissions set."
+log_onexit restore_root_datasets
+
+for dtst in $DATASETS ; do
+ log_must zfs allow -u $STAFF1 $LOCAL_DESC_SET $dtst
+ log_must zfs allow -g $STAFF_GROUP $LOCAL_DESC_SET $dtst
+ log_must zfs allow -e $LOCAL_DESC_SET $dtst
+
+ log_must verify_perm $dtst $LOCAL_DESC_SET \
+ $STAFF1 $STAFF2 $OTHER1 $OTHER2
+
+ log_must zfs unallow -e $dtst
+ log_must verify_perm $dtst $LOCAL_DESC_SET $STAFF1 $STAFF2
+ log_must verify_noperm $dtst $LOCAL_DESC_SET $OTHER1 $OTHER2
+
+ log_must zfs unallow -g $STAFF_GROUP $dtst
+ log_must verify_perm $dtst $LOCAL_DESC_SET $STAFF1
+ log_must verify_noperm $dtst $LOCAL_DESC_SET $STAFF2
+
+ log_must zfs unallow -u $STAFF1 $dtst
+ log_must verify_noperm $dtst $LOCAL_DESC_SET $STAFF1
+done
+
+log_pass "Verify option '-u', '-g' and '-e' passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_007_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_007_neg.ksh
new file mode 100755
index 000000000000..b1a221be0bd9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs unallow will not remove those permissions which inherited from
+# its parent filesystem.
+#
+# STRATEGY:
+# 1. Assign perm1 to $ROOT_TESTFS
+# 2. Create $SUBFS and assign perm2 to it.
+# 3. Verify unallow can not affect perm1 on $SUBFS
+#
+
+verify_runnable "both"
+
+log_assert "zfs unallow won't remove those permissions which inherited from " \
+ "its parent dataset."
+log_onexit restore_root_datasets
+
+perm1="atime,devices"; perm2="compression,checksum"
+log_must zfs create $SUBFS
+log_must zfs allow $STAFF1 $perm1 $ROOT_TESTFS
+log_must zfs allow $STAFF1 $perm2 $SUBFS
+
+log_must verify_perm $SUBFS ${perm1},${perm2} $STAFF1
+#
+# Athrough unallow the permissions which don't exists on the specific dataset
+# return 0, the inherited permissions can't be removed in fact.
+#
+log_must zfs unallow -u $STAFF1 $perm1 $SUBFS
+log_must verify_perm $SUBFS ${perm1},${perm2} $STAFF1
+
+log_pass "Verify zfs unallow won't remove inherited permissions passed."
diff --git a/tests/zfs-tests/tests/functional/delegate/zfs_unallow_008_neg.ksh b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_008_neg.ksh
new file mode 100755
index 000000000000..a8bd5ebcb6b4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/delegate/zfs_unallow_008_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs unallow can handle invalid arguments.
+#
+# STRATEGY:
+# 1. Set up basic test environment.
+# 2. Verify zfs unallow handle invalid arguments correctly.
+#
+
+verify_runnable "both"
+
+log_assert "zfs unallow can handle invalid arguments."
+log_onexit restore_root_datasets
+
+function neg_test
+{
+ log_mustnot eval "$@ >/dev/null 2>&1"
+}
+
+# Options that cause this test to fail:
+# "-r"
+set -A badopts "everyone -e" "everyone -u $STAFF1" "everyone everyone" \
+ "-c -l" "-c -d" "-c -e" "-c -s" "-u -e" "-s -e" "-s -l -d" \
+ "-s @non-exist-set -l" "-s @non-existen-set -d" \
+ "-s @non-existen-set -e" "-r -u $STAFF1 $STAFF1" \
+ "-u $STAFF1 -g $STAFF_GROUP" "-u $STAFF1 -e"
+
+log_must setup_unallow_testenv
+
+#
+# The GNU getopt(3) implementation will reorder these arguments such the
+# the parser can handle them and the test doesn't fail. POSIXLY_CORRECT
+# is set to disable the reordering so the original test cases will fail.
+#
+export POSIXLY_CORRECT=1
+
+for dtst in $DATASETS ; do
+ log_must zfs allow -c create $dtst
+
+ typeset -i i=0
+ while ((i < ${#badopts[@]})); do
+ neg_test zfs unallow ${badopts[$i]} $dtst
+ ((i += 1))
+ done
+
+ # Causes test failure: neg_test user_run $STAFF1 zfs unallow $dtst
+done
+
+unset POSIXLY_CORRECT
+
+log_pass "zfs unallow can handle invalid arguments passed."
diff --git a/tests/zfs-tests/tests/functional/devices/Makefile.am b/tests/zfs-tests/tests/functional/devices/Makefile.am
new file mode 100644
index 000000000000..42f59428d4ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/devices/Makefile.am
@@ -0,0 +1,11 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/devices
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ devices_001_pos.ksh \
+ devices_002_neg.ksh \
+ devices_003_pos.ksh
+
+dist_pkgdata_DATA = \
+ devices.cfg \
+ devices_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/devices/cleanup.ksh b/tests/zfs-tests/tests/functional/devices/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/devices/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/devices/devices.cfg b/tests/zfs-tests/tests/functional/devices/devices.cfg
new file mode 100644
index 000000000000..ba3c36ae8c4a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/devices/devices.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export TESTFILE1=testfile1$$
+export TESTFILE2=testfile2$$
diff --git a/tests/zfs-tests/tests/functional/devices/devices_001_pos.ksh b/tests/zfs-tests/tests/functional/devices/devices_001_pos.ksh
new file mode 100755
index 000000000000..2f2802bc65a3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/devices/devices_001_pos.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/devices/devices.cfg
+. $STF_SUITE/tests/functional/devices/devices_common.kshlib
+
+#
+# DESCRIPTION:
+# When set property devices=on on file system, devices files can be used in
+# this file system.
+#
+# STRATEGY:
+# 1. Create pool and file system.
+# 2. Set devices=on on this file system.
+# 3. Separately create block device file and character file.
+# 4. Separately read and write from those two device files.
+# 5. Check the return value, and make sure it succeeds.
+#
+
+verify_runnable "global"
+
+log_assert "Setting devices=on on file system, the devices files in this file" \
+ "system can be used."
+log_onexit cleanup
+
+log_must zfs set devices=on $TESTPOOL/$TESTFS
+
+#
+# Create block device file backed by a ZFS volume.
+# Verify it can be opened, written, and read.
+#
+create_dev_file b $TESTDIR/$TESTFILE1 $ZVOL_DEVDIR/$TESTPOOL/$TESTVOL
+log_must dd if=/dev/urandom of=$TESTDIR/$TESTFILE1.out1 count=1 bs=128k
+log_must dd if=$TESTDIR/$TESTFILE1.out1 of=$TESTDIR/$TESTFILE1 count=1 bs=128k
+log_must dd if=$TESTDIR/$TESTFILE1 of=$TESTDIR/$TESTFILE1.out2 count=1 bs=128k
+log_must cmp $TESTDIR/$TESTFILE1.out1 $TESTDIR/$TESTFILE1.out2
+
+# Create character device file backed by /dev/null
+# Verify it can be opened and written.
+create_dev_file c $TESTDIR/$TESTFILE2
+log_must dd if=/dev/urandom of=$TESTDIR/$TESTFILE2 count=1 bs=128k
+
+log_pass "Setting devices=on on file system and testing it pass."
diff --git a/tests/zfs-tests/tests/functional/devices/devices_002_neg.ksh b/tests/zfs-tests/tests/functional/devices/devices_002_neg.ksh
new file mode 100755
index 000000000000..a768c4aa6b34
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/devices/devices_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/devices/devices.cfg
+. $STF_SUITE/tests/functional/devices/devices_common.kshlib
+
+#
+# DESCRIPTION:
+# When set property devices=off on file system, device files cannot be used
+# in this file system.
+#
+# STRATEGY:
+# 1. Create pool and file system.
+# 2. Set devices=off on this file system.
+# 3. Separately create block device file and character file.
+# 4. Separately read and write from those two device files.
+# 5. Check the return value, and make sure it failed.
+#
+
+verify_runnable "global"
+
+log_assert "Setting devices=off on file system, the devices files in this file"\
+ "system can not be used."
+log_onexit cleanup
+
+log_must zfs set devices=off $TESTPOOL/$TESTFS
+
+#
+# Create block device file backed by a ZFS volume.
+# Verify it cannot be opened, written, and read.
+#
+create_dev_file b $TESTDIR/$TESTFILE1 $ZVOL_DEVDIR/$TESTPOOL/$TESTVOL
+log_mustnot dd if=/dev/urandom of=$TESTDIR/$TESTFILE1 count=1 bs=128k
+log_mustnot dd if=$TESTDIR/$TESTFILE1 of=/dev/null count=1 bs=128k
+
+# Create character device file backed by /dev/null
+# Verify it cannot be opened and written.
+create_dev_file c $TESTDIR/$TESTFILE2
+log_mustnot dd if=/dev/urandom of=$TESTDIR/$TESTFILE2 count=1 bs=128k
+
+log_pass "Setting devices=off on file system and testing it pass."
diff --git a/tests/zfs-tests/tests/functional/devices/devices_003_pos.ksh b/tests/zfs-tests/tests/functional/devices/devices_003_pos.ksh
new file mode 100755
index 000000000000..1fcd67409c11
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/devices/devices_003_pos.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Writing random data into /dev/zfs should do no harm.
+#
+# STRATEGY:
+# 1. Write some random data into /dev/zfs
+# 2. Verify that this should fail.
+#
+#
+
+log_assert "Writing random data into /dev/zfs should do no harm."
+
+log_mustnot dd if=/dev/urandom of=/dev/zfs count=1024
+
+log_pass "Writing random data into /dev/zfs should do no harm."
diff --git a/tests/zfs-tests/tests/functional/devices/devices_common.kshlib b/tests/zfs-tests/tests/functional/devices/devices_common.kshlib
new file mode 100644
index 000000000000..fa7fdbecf5fd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/devices/devices_common.kshlib
@@ -0,0 +1,119 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/devices/devices.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# Create block file or character file according to parameter.
+#
+# $1 device file type
+# $2 file name
+# $3 device path (used for 'b' device type)
+#
+function create_dev_file
+{
+ typeset filetype=$1
+ typeset filename=$2
+ typeset devstr=$3
+
+ case $filetype in
+ b)
+ case $(uname) in
+ Linux)
+ #
+ # stat(1) --format=FORMAT tokens
+ # %t - major device type in hex
+ # %T - minor device type in hex
+ #
+ major=$(stat --dereference --format="%t" "$devstr")
+ minor=$(stat --dereference --format="%T" "$devstr")
+ log_must mknod $filename b "0x${major}" "0x${minor}"
+ ;;
+ *)
+ #
+ # Get the device file information. i.e:
+ # $devstr: block special (28/768)
+ #
+ devstr=$(file $devstr)
+ major=${devstr##*\(}
+ major=${major%%/*}
+ minor=${devstr##*/}
+ minor=${minor%\)}
+ log_must mknod $filename b $major $minor
+ ;;
+ esac
+ ;;
+ c)
+ #
+ # Create device file '/dev/null', $devstr is unused.
+ #
+ case $(uname) in
+ Linux)
+ #
+ # stat(1) --format=FORMAT tokens
+ # %t - major device type in hex
+ # %T - minor device type in hex
+ #
+ major=$(stat --format="%t" /dev/null)
+ minor=$(stat --format="%T" /dev/null)
+ log_must mknod $filename c "0x${major}" "0x${minor}"
+ ;;
+ FreeBSD)
+ #
+ # Create device file '/dev/null'
+ #
+ major=13
+ minor=2
+ log_must mknod $filename b $major $minor
+ ;;
+ *)
+ major=$(getmajor mm)
+ minor=2
+ log_must mknod $filename b $major $minor
+ ;;
+ esac
+ ;;
+ *)
+ log_fail "'$filetype' is wrong."
+ ;;
+ esac
+
+ return 0
+}
+
+function cleanup
+{
+ log_must zfs set devices=on $TESTPOOL/$TESTFS
+ log_must rm -f $TESTDIR/$TESTFILE1
+ log_must rm -f $TESTDIR/$TESTFILE2
+ log_must rm -f $TESTDIR/$TESTFILE1.out1
+ log_must rm -f $TESTDIR/$TESTFILE1.out2
+}
diff --git a/tests/zfs-tests/tests/functional/devices/setup.ksh b/tests/zfs-tests/tests/functional/devices/setup.ksh
new file mode 100755
index 000000000000..ee6cf83acb9e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/devices/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/events/Makefile.am b/tests/zfs-tests/tests/functional/events/Makefile.am
new file mode 100644
index 000000000000..e1fe490812b3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/Makefile.am
@@ -0,0 +1,11 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/events
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ events_001_pos.ksh \
+ events_002_pos.ksh \
+ zed_rc_filter.ksh
+
+dist_pkgdata_DATA = \
+ events.cfg \
+ events_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/events/cleanup.ksh b/tests/zfs-tests/tests/functional/events/cleanup.ksh
new file mode 100755
index 000000000000..4905342b713b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/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) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+zed_cleanup all-debug.sh all-syslog.sh
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/events/events.cfg b/tests/zfs-tests/tests/functional/events/events.cfg
new file mode 100644
index 000000000000..1405dab6f989
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/events.cfg
@@ -0,0 +1,38 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+export MPOOL=mpool.$$
+
+VDEV1=$TEST_BASE_DIR/vdev1
+VDEV2=$TEST_BASE_DIR/vdev2
+VDEV3=$TEST_BASE_DIR/vdev3
+VDEV4=$TEST_BASE_DIR/vdev4
+
+export TMP_EVENTS=$TEST_BASE_DIR/tmp_events.$$
+export TMP_EVENTS_FULL=$TEST_BASE_DIR/tmp_events_full.$$
+export TMP_EVENT_FULL=$TEST_BASE_DIR/tmp_event_full.$$
+export TMP_EVENTS_ZED=$TEST_BASE_DIR/tmp_events_zed.$$
+export TMP_EVENT_ZED=$TEST_BASE_DIR/tmp_event_zed.$$
diff --git a/tests/zfs-tests/tests/functional/events/events_001_pos.ksh b/tests/zfs-tests/tests/functional/events/events_001_pos.ksh
new file mode 100755
index 000000000000..5121f66b78b0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/events_001_pos.ksh
@@ -0,0 +1,153 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+# DESCRIPTION:
+# Verify zpool events command logs events.
+#
+# STRATEGY:
+# 1. Execute zpool sub-commands on a pool.
+# 2. Verify the expected events are logged in 'zpool events'.
+# 3. Verify the expected events are logged by the ZED.
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/events/events_common.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ if poolexists $MPOOL; then
+ destroy_pool $MPOOL
+ fi
+
+ for file in $VDEV1 $VDEV2 $VDEV3 $VDEV4; do
+ [[ -f $file ]] && rm -f $file
+ done
+
+ log_must zed_stop
+}
+
+log_assert "Verify zpool sub-commands generate expected events"
+log_onexit cleanup
+
+log_must truncate -s $MINVDEVSIZE $VDEV1 $VDEV2 $VDEV3 $VDEV4
+
+log_must zpool events -c
+log_must zed_start
+
+# Create a mirrored pool with two devices.
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.pool_create" \
+ -e "sysevent.fs.zfs.history_event" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool create $MPOOL mirror $VDEV1 $VDEV2"
+
+# Set a pool property.
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.history_event" \
+ "zpool set comment=string $MPOOL"
+
+# Add a cache device then remove it.
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.config_sync" \
+ -e "sysevent.fs.zfs.vdev_add" \
+ "zpool add -f $MPOOL spare $VDEV3"
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.vdev_remove_aux" \
+ "zpool remove $MPOOL $VDEV3"
+
+# Add a log device then remove it.
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.config_sync" \
+ -e "sysevent.fs.zfs.vdev_add" \
+ "zpool add -f $MPOOL log $VDEV3"
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.vdev_remove_dev" \
+ "zpool remove $MPOOL $VDEV3"
+
+# Offline then online a device.
+run_and_verify -p "$MPOOL"\
+ -e "resource.fs.zfs.statechange" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool offline $MPOOL $VDEV1"
+run_and_verify -p "$MPOOL" -d 10 \
+ -e "resource.fs.zfs.statechange" \
+ -e "sysevent.fs.zfs.vdev_online" \
+ -e "sysevent.fs.zfs.resilver_start" \
+ -e "sysevent.fs.zfs.resilver_finish" \
+ -e "sysevent.fs.zfs.history_event" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool online $MPOOL $VDEV1"
+
+# Attach then detach a device from the mirror.
+run_and_verify -p "$MPOOL" -d 10 \
+ -e "sysevent.fs.zfs.vdev_attach" \
+ -e "sysevent.fs.zfs.resilver_start" \
+ -e "sysevent.fs.zfs.resilver_finish" \
+ -e "sysevent.fs.zfs.history_event" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool attach $MPOOL $VDEV1 $VDEV4"
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.vdev_remove" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool detach $MPOOL $VDEV4"
+
+# Replace a device
+run_and_verify -p "$MPOOL" -d 10 \
+ -e "sysevent.fs.zfs.vdev_attach" \
+ -e "sysevent.fs.zfs.resilver_start" \
+ -e "sysevent.fs.zfs.resilver_finish" \
+ -e "sysevent.fs.zfs.vdev_remove" \
+ -e "sysevent.fs.zfs.history_event" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool replace -f $MPOOL $VDEV1 $VDEV4"
+
+# Scrub a pool.
+run_and_verify -p "$MPOOL" -d 10 \
+ -e "sysevent.fs.zfs.scrub_start" \
+ -e "sysevent.fs.zfs.scrub_finish" \
+ -e "sysevent.fs.zfs.history_event" \
+ "zpool scrub $MPOOL"
+
+# Export then import a pool
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.pool_export" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool export $MPOOL"
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.pool_import" \
+ -e "sysevent.fs.zfs.history_event" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool import -d $TEST_BASE_DIR $MPOOL"
+
+# Destroy the pool
+run_and_verify -p "$MPOOL" \
+ -e "sysevent.fs.zfs.pool_destroy" \
+ -e "sysevent.fs.zfs.config_sync" \
+ "zpool destroy $MPOOL"
+
+log_pass "Verify zpool sub-commands generate expected events"
diff --git a/tests/zfs-tests/tests/functional/events/events_002_pos.ksh b/tests/zfs-tests/tests/functional/events/events_002_pos.ksh
new file mode 100755
index 000000000000..76ad6237fc23
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/events_002_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 (c) 2017 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+# DESCRIPTION:
+# Verify ZED handles missed events from a pool when starting.
+#
+# STRATEGY:
+# 1. Clear the events and create a pool to generate some events.
+# 2. Start the ZED and verify it handles missed events.
+# 3. Stop the ZED
+# 4. Generate additional events.
+# 5. Start the ZED and verify it only handles the new missed events.
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/events/events_common.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ if poolexists $MPOOL; then
+ destroy_pool $MPOOL
+ fi
+
+ for file in $VDEV1 $VDEV2; do
+ [[ -f $file ]] && rm -f $file
+ done
+
+ log_must rm -f $TMP_EVENTS_ZED $TMP_EVENTS_ZED
+ log_must zed_stop
+}
+
+log_assert "Verify ZED handles missed events on when starting"
+log_onexit cleanup
+
+log_must truncate -s $MINVDEVSIZE $VDEV1 $VDEV2
+
+# 1. Create a pool and generate some events.
+log_must truncate -s 0 $ZED_DEBUG_LOG
+log_must zpool events -c
+log_must zpool create $MPOOL mirror $VDEV1 $VDEV2
+
+# 2. Start the ZED and verify it handles missed events.
+log_must zed_start
+log_must file_wait $ZED_DEBUG_LOG
+log_must cp $ZED_DEBUG_LOG $TMP_EVENTS_ZED
+
+awk -v event="sysevent.fs.zfs.pool_create" \
+ 'BEGIN{FS="\n"; RS=""} $0 ~ event { print $0 }' \
+ $TMP_EVENTS_ZED >$TMP_EVENT_ZED
+log_must grep -q "^ZEVENT_POOL=$MPOOL" $TMP_EVENT_ZED
+
+# 3. Stop the ZED
+zed_stop
+log_must truncate -s 0 $ZED_DEBUG_LOG
+
+# 4. Generate additional events.
+log_must zpool offline $MPOOL $VDEV1
+log_must zpool online $MPOOL $VDEV1
+log_must zpool wait -t resilver $MPOOL
+
+log_must zpool scrub $MPOOL
+
+# Wait for the scrub to wrap, or is_healthy will be wrong.
+while ! is_pool_scrubbed $MPOOL; do
+ sleep 1
+done
+
+# 5. Start the ZED and verify it only handled the new missed events.
+log_must zed_start
+log_must file_wait $ZED_DEBUG_LOG 15
+log_must cp $ZED_DEBUG_LOG $TMP_EVENTS_ZED
+
+log_mustnot grep -q "sysevent.fs.zfs.pool_create" $TMP_EVENTS_ZED
+log_must grep -q "sysevent.fs.zfs.vdev_online" $TMP_EVENTS_ZED
+log_must grep -q "sysevent.fs.zfs.resilver_start" $TMP_EVENTS_ZED
+log_must grep -q "sysevent.fs.zfs.resilver_finish" $TMP_EVENTS_ZED
+
+log_pass "Verify ZED handles missed events on when starting"
diff --git a/tests/zfs-tests/tests/functional/events/events_common.kshlib b/tests/zfs-tests/tests/functional/events/events_common.kshlib
new file mode 100644
index 000000000000..26afc109174f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/events_common.kshlib
@@ -0,0 +1,130 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/events/events.cfg
+
+#
+# Wait for up to 'timeout' seconds for the 'file' to settle, i.e.
+# not be updated for a period of 'delay' seconds.
+#
+function file_wait # file delay timeout
+{
+ file=$1
+ delay=${2:-3}
+ timeout=${3:-120}
+
+ SECONDS=0
+
+ while [ $(( $(date +%s) - $(stat -c %Y $file) )) -lt $delay ]; do
+ if [[ $SECONDS -gt $timeout ]]; then
+ return 1
+ fi
+
+ sleep 1
+ done
+
+ return 0;
+}
+
+function run_and_verify
+{
+ typeset delay event pool zedlog
+ set -A events
+
+ while getopts "d:e:p:z:" opt; do
+ case $opt in
+ d)
+ delay=$OPTARG
+ ;;
+ e)
+ events[${#events[*]}+1]=$OPTARG
+ ;;
+ p)
+ pool=$OPTARG
+ ;;
+ z)
+ zedlog=$OPTARG
+ ;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+
+ pool=${pool:-$TESTPOOL}
+ delay=${delay:-3}
+ zedlog=${zedlog:-$ZED_DEBUG_LOG}
+ fullcmd="$1"
+ cmd=$(echo $fullcmd | awk '{print $1}')
+
+ # If we aren't running zpool or zfs, something is wrong
+ [[ $cmd == "zpool" || $cmd == "zfs" ]] || \
+ log_fail "run_and_verify called with \"$cmd ($fullcmd)\""
+
+ log_note "Checking events for command: '$fullcmd'"
+
+ # Remove any previous events from the logs.
+ log_must zpool events -c
+ log_must truncate -s 0 $zedlog
+
+ # Run the command as provided.
+ log_must eval "$fullcmd"
+
+ # Collect the new events and verify there are some.
+ log_must zpool sync -f
+ log_must file_wait $zedlog $delay
+ log_must cp $zedlog $TMP_EVENTS_ZED
+ log_must eval "zpool events >$TMP_EVENTS 2>/dev/null"
+ log_must eval "zpool events -v > $TMP_EVENTS_FULL 2>/dev/null"
+
+ log_must test -s $TMP_EVENTS
+ log_must test -s $TMP_EVENTS_FULL
+ log_must test -s $TMP_EVENTS_ZED
+
+ log_note "Events generated:"
+ cat $TMP_EVENTS
+
+ # Verify all the expected events appear in the log.
+ for event in ${events[*]}; do
+
+ # Verify the event is in in the short output.
+ log_must grep -q "$event" $TMP_EVENTS
+
+ # Verify the event is in the verbose output with pool name.
+ awk -v event="$event" \
+ 'BEGIN{FS="\n"; RS=""} $0 ~ event { print $0 }' \
+ $TMP_EVENTS_FULL >$TMP_EVENT_FULL
+ log_must grep -q "pool = \"$pool\"" $TMP_EVENT_FULL
+
+ # Verify the event was received by the ZED and logged.
+ awk -v event="$event" \
+ 'BEGIN{FS="\n"; RS=""} $0 ~ event { print $0 }' \
+ $TMP_EVENTS_ZED >$TMP_EVENT_ZED
+ log_must grep -q "^ZEVENT_POOL=$pool" $TMP_EVENT_ZED
+ done
+
+ rm -f $TMP_EVENTS $TMP_EVENTS_FULL $TMP_EVENT_FULL \
+ $TMP_EVENTS_ZED $TMP_EVENT_ZED
+}
diff --git a/tests/zfs-tests/tests/functional/events/setup.ksh b/tests/zfs-tests/tests/functional/events/setup.ksh
new file mode 100755
index 000000000000..2f81d16b1814
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/setup.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 (c) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+zed_setup all-debug.sh all-syslog.sh
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/events/zed_rc_filter.ksh b/tests/zfs-tests/tests/functional/events/zed_rc_filter.ksh
new file mode 100755
index 000000000000..44652ee4cf12
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/events/zed_rc_filter.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 (c) 2018 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+# DESCRIPTION:
+# Verify zed.rc ZED_SYSLOG_SUBCLASS_INCLUDE/EXCLUDE event filtering works.
+#
+# STRATEGY:
+# 1. Execute zpool sub-commands on a pool.
+# 2. Test different combinations of ZED_SYSLOG_SUBCLASS_INCLUDE filtering.
+# 3. Execute zpool sub-commands on a pool.
+# 4. Test different combinations of ZED_SYSLOG_SUBCLASS_EXCLUDE filtering.
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/events/events_common.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zed_stop
+ zed_rc_restore $zedrc_backup
+}
+
+log_assert "Verify zpool sub-commands generate expected events"
+log_onexit cleanup
+
+log_must zpool events -c
+log_must zed_start
+
+# Backup our zed.rc
+zedrc_backup=$(zed_rc_backup)
+
+log_note "Include a single event type"
+zed_rc_set ZED_SYSLOG_SUBCLASS_INCLUDE history_event
+run_and_verify -p "$TESTPOOL" -e "sysevent.fs.zfs.history_event" \
+ "zfs set compression=off $TESTPOOL/$TESTFS"
+
+log_note "Include a single event type with wildcards"
+zed_rc_set ZED_SYSLOG_SUBCLASS_INCLUDE '*history_event*'
+run_and_verify -p "$TESTPOOL" -e "sysevent.fs.zfs.history_event" \
+ "zfs set compression=off $TESTPOOL/$TESTFS"
+
+log_note "Test a filter of a non-match and a match"
+zed_rc_set ZED_SYSLOG_SUBCLASS_INCLUDE 'foobar|*history_event*'
+run_and_verify -p "$TESTPOOL" -e "sysevent.fs.zfs.history_event" \
+ "zfs set compression=off $TESTPOOL/$TESTFS"
+
+log_note "Include multiple events"
+zed_rc_set ZED_SYSLOG_SUBCLASS_INCLUDE 'scrub_start|scrub_finish'
+run_and_verify -p "$TESTPOOL" -e "sysevent.fs.zfs.scrub_start" \
+ -e "sysevent.fs.zfs.scrub_finish" \
+ "zpool scrub $TESTPOOL && wait_scrubbed $TESTPOOL"
+
+# We can't use run_and_verify() for exclusions, so run the rest of the tests
+# manually.
+log_note "Test one exclusion"
+zed_rc_set ZED_SYSLOG_SUBCLASS_EXCLUDE 'history_event'
+truncate -s 0 $ZED_DEBUG_LOG
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+log_must file_wait $ZED_DEBUG_LOG 3
+log_mustnot grep -q history_event $ZED_DEBUG_LOG
+
+log_note "Test one exclusion with wildcards"
+zed_rc_set ZED_SYSLOG_SUBCLASS_EXCLUDE '*history_event*'
+truncate -s 0 $ZED_DEBUG_LOG
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+log_must file_wait $ZED_DEBUG_LOG 3
+log_mustnot grep -q history_event $ZED_DEBUG_LOG
+
+log_note "Test one inclusion and one exclusion"
+zed_rc_set ZED_SYSLOG_SUBCLASS_INCLUDE 'scrub_start'
+zed_rc_set ZED_SYSLOG_SUBCLASS_EXCLUDE 'scrub_finish'
+truncate -s 0 $ZED_DEBUG_LOG
+zpool scrub $TESTPOOL
+wait_scrubbed $TESTPOOL
+log_must file_wait $ZED_DEBUG_LOG 3
+log_must grep -q scrub_start $ZED_DEBUG_LOG
+log_mustnot grep -q scrub_finish $ZED_DEBUG_LOG
+
+log_pass "zed.rc event filtering works correctly."
diff --git a/tests/zfs-tests/tests/functional/exec/.gitignore b/tests/zfs-tests/tests/functional/exec/.gitignore
new file mode 100644
index 000000000000..63a68bbc681e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/exec/.gitignore
@@ -0,0 +1 @@
+/mmap_exec
diff --git a/tests/zfs-tests/tests/functional/exec/Makefile.am b/tests/zfs-tests/tests/functional/exec/Makefile.am
new file mode 100644
index 000000000000..524bf2734f73
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/exec/Makefile.am
@@ -0,0 +1,9 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/exec
+
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ exec_001_pos.ksh \
+ exec_002_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/exec/cleanup.ksh b/tests/zfs-tests/tests/functional/exec/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/exec/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/exec/exec_001_pos.ksh b/tests/zfs-tests/tests/functional/exec/exec_001_pos.ksh
new file mode 100755
index 000000000000..5de8a79ea30f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/exec/exec_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 2007 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
+
+#
+# DESCRIPTION:
+# When set property exec=on on a filesystem, processes can be executed from
+# this filesystem.
+#
+# STRATEGY:
+# 1. Create pool and file system.
+# 2. Copy '$STF_PATH/ls' to the ZFS file system.
+# 3. Setting exec=on on this file system.
+# 4. Make sure '$STF_PATH/ls' can work in this ZFS file system.
+# 5. Make sure mmap which is using the PROT_EXEC calls succeed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must rm $TESTDIR/myls
+}
+
+log_assert "Setting exec=on on a filesystem, processes can be executed from " \
+ "this file system."
+log_onexit cleanup
+
+log_must cp $STF_PATH/ls $TESTDIR/myls
+log_must zfs set exec=on $TESTPOOL/$TESTFS
+log_must $TESTDIR/myls
+log_must mmap_exec $TESTDIR/myls
+
+log_pass "Setting exec=on on filesystem testing passed."
diff --git a/tests/zfs-tests/tests/functional/exec/exec_002_neg.ksh b/tests/zfs-tests/tests/functional/exec/exec_002_neg.ksh
new file mode 100755
index 000000000000..c11bf8442bcd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/exec/exec_002_neg.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 2007 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
+
+#
+# DESCRIPTION:
+# When set property exec=off on a filesystem, processes can not be executed from
+# this filesystem.
+#
+# STRATEGY:
+# 1. Create pool and file system.
+# 2. Copy '/usr/bin/ls' to the ZFS file system.
+# 3. Setting exec=off on this file system.
+# 4. Make sure '/usr/bin/ls' can not work in this ZFS file system.
+# 5. Make sure mmap which is using the PROT_EXEC calls failed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must rm $TESTDIR/myls
+}
+
+#
+# Execute and check if the return value is equal to expected.
+#
+# $1 expected value
+# $2..$n executed item
+#
+function exec_n_check
+{
+ typeset expect_value=$1
+
+ shift
+ $@
+ ret=$?
+ if [[ $ret != $expect_value ]]; then
+ log_fail "Unexpected return code: '$ret'"
+ fi
+
+ return 0
+}
+
+log_assert "Setting exec=off on a filesystem, processes can not be executed " \
+ "from this file system."
+log_onexit cleanup
+
+log_must cp $STF_PATH/ls $TESTDIR/myls
+log_must zfs set exec=off $TESTPOOL/$TESTFS
+
+if is_linux; then
+ log_must exec_n_check 126 $TESTDIR/myls
+ log_must exec_n_check 1 mmap_exec $TESTDIR/myls # EPERM
+else
+ log_must exec_n_check 126 $TESTDIR/myls
+ log_must exec_n_check 13 mmap_exec $TESTDIR/myls # EACCES
+fi
+
+log_pass "Setting exec=off on filesystem testing passed."
diff --git a/tests/zfs-tests/tests/functional/exec/setup.ksh b/tests/zfs-tests/tests/functional/exec/setup.ksh
new file mode 100755
index 000000000000..fc5cec3063a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/exec/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/fallocate/Makefile.am b/tests/zfs-tests/tests/functional/fallocate/Makefile.am
new file mode 100644
index 000000000000..5ff366d2482c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fallocate/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/fallocate
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ fallocate_prealloc.ksh \
+ fallocate_punch-hole.ksh
diff --git a/tests/zfs-tests/tests/functional/fallocate/cleanup.ksh b/tests/zfs-tests/tests/functional/fallocate/cleanup.ksh
new file mode 100755
index 000000000000..bdfa6147117b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fallocate/cleanup.ksh
@@ -0,0 +1,27 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.ksh b/tests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.ksh
new file mode 100755
index 000000000000..7bb020fe5c19
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fallocate/fallocate_prealloc.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) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test fallocate(2) preallocation.
+#
+# STRATEGY:
+# 1. Verify mode 0 fallocate is supported.
+# 2. Verify default 10% reserve space is honored by setting a quota.
+#
+
+verify_runnable "global"
+
+FILE=$TESTDIR/$TESTFILE0
+
+function cleanup
+{
+ log_must zfs set quota=none $TESTPOOL
+
+ [[ -e $TESTDIR ]] && log_must rm -Rf $TESTDIR/*
+}
+
+log_assert "Ensure sparse files can be preallocated"
+
+log_onexit cleanup
+
+# Pre-allocate a sparse 1GB file.
+log_must fallocate -l $((1024 * 1024 * 1024)) $FILE
+log_must rm -Rf $TESTDIR/*
+
+# Verify that an additional ~10% reserve space is required.
+log_must zfs set quota=100M $TESTPOOL
+log_mustnot fallocate -l $((150 * 1024 * 1024)) $FILE
+log_mustnot fallocate -l $((110 * 1024 * 1024)) $FILE
+log_must fallocate -l $((90 * 1024 * 1024)) $FILE
+
+log_pass "Ensure sparse files can be preallocated"
diff --git a/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh b/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.ksh
new file mode 100755
index 000000000000..6a8faa48704d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fallocate/fallocate_punch-hole.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 (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test `fallocate --punch-hole`
+#
+# STRATEGY:
+# 1. Create a dense file
+# 2. Punch an assortment of holes in the file and verify the result.
+#
+
+verify_runnable "global"
+
+FILE=$TESTDIR/$TESTFILE0
+BLKSZ=$(get_prop recordsize $TESTPOOL)
+
+function cleanup
+{
+ [[ -e $TESTDIR ]] && log_must rm -f $FILE
+}
+
+function check_disk_size
+{
+ typeset expected_size=$1
+
+ disk_size=$(du $TESTDIR/file | awk '{print $1}')
+ if [ $disk_size -ne $expected_size ]; then
+ log_fail "Incorrect size: $disk_size != $expected_size"
+ fi
+}
+
+function check_apparent_size
+{
+ typeset expected_size=$1
+
+ apparent_size=$(stat_size)
+ if [ $apparent_size -ne $expected_size ]; then
+ log_fail "Incorrect size: $apparent_size != $expected_size"
+ fi
+}
+
+log_assert "Ensure holes can be punched in files making them sparse"
+
+log_onexit cleanup
+
+# Create a dense file and check it is the correct size.
+log_must file_write -o create -f $FILE -b $BLKSZ -c 8
+log_must check_disk_size $((131072 * 8))
+
+# Punch a hole for the first full block.
+log_must fallocate --punch-hole --offset 0 --length $BLKSZ $FILE
+log_must check_disk_size $((131072 * 7))
+
+# Partially punch a hole in the second block.
+log_must fallocate --punch-hole --offset $BLKSZ --length $((BLKSZ / 2)) $FILE
+log_must check_disk_size $((131072 * 7))
+
+# Punch a hole which overlaps the third and forth block.
+log_must fallocate --punch-hole --offset $(((BLKSZ * 2) + (BLKSZ / 2))) \
+ --length $((BLKSZ)) $FILE
+log_must check_disk_size $((131072 * 7))
+
+# Punch a hole from the fifth block past the end of file. The apparent
+# file size should not change since --keep-size is implied.
+apparent_size=$(stat_size $FILE)
+log_must fallocate --punch-hole --offset $((BLKSZ * 4)) \
+ --length $((BLKSZ * 10)) $FILE
+log_must check_disk_size $((131072 * 4))
+log_must check_apparent_size $apparent_size
+
+log_pass "Ensure holes can be punched in files making them sparse"
diff --git a/tests/zfs-tests/tests/functional/fallocate/setup.ksh b/tests/zfs-tests/tests/functional/fallocate/setup.ksh
new file mode 100755
index 000000000000..32334d396865
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fallocate/setup.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 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/fault/Makefile.am b/tests/zfs-tests/tests/functional/fault/Makefile.am
new file mode 100644
index 000000000000..f2fc06877d3b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/Makefile.am
@@ -0,0 +1,19 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/fault
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ auto_offline_001_pos.ksh \
+ auto_online_001_pos.ksh \
+ auto_replace_001_pos.ksh \
+ auto_spare_001_pos.ksh \
+ auto_spare_002_pos.ksh \
+ auto_spare_ashift.ksh \
+ auto_spare_multiple.ksh \
+ auto_spare_shared.ksh \
+ decrypt_fault.ksh \
+ decompress_fault.ksh \
+ scrub_after_resilver.ksh \
+ zpool_status_-s.ksh
+
+dist_pkgdata_DATA = \
+ fault.cfg
diff --git a/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh
new file mode 100755
index 000000000000..1bf54b1a86d4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_offline_001_pos.ksh
@@ -0,0 +1,191 @@
+#!/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
+. $STF_SUITE/tests/functional/events/events_common.kshlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Testing Fault Management Agent ZED Logic - Physically removed device is
+# made unavail and onlined when reattached
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Simulate physical removal of one device
+# 3. Verify the device is unvailable
+# 4. Reattach the device
+# 5. Verify the device is onlined
+# 6. Repeat the same tests with a spare device:
+# zed will use the spare to handle the removed data device
+# 7. Repeat the same tests again with a faulted spare device:
+# the removed data device should be unavailable
+#
+# NOTE: the use of 'block_device_wait' throughout the test helps avoid race
+# conditions caused by mixing creation/removal events from partitioning the
+# disk (zpool create) and events from physically removing it (remove_disk).
+#
+# NOTE: the test relies on 'zpool sync' to prompt the kmods to transition a
+# vdev to the unavailable state. The ZED does receive a removal notification
+# but only relies on it to activate a hot spare. Additional work is planned
+# to extend an existing ioctl interface to allow the ZED to transition the
+# vdev in to a removed state.
+#
+verify_runnable "both"
+
+if is_linux; then
+ # Add one 512b scsi_debug device (4Kn would generate IO errors)
+ # 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
+ rm -f $filedev1
+ rm -f $filedev2
+ rm -f $filedev3
+ rm -f $sparedev
+ unload_scsi_debug
+}
+
+log_assert "ZED detects physically removed devices"
+
+log_onexit cleanup
+
+filedev1="$TEST_BASE_DIR/file-vdev-1"
+filedev2="$TEST_BASE_DIR/file-vdev-2"
+filedev3="$TEST_BASE_DIR/file-vdev-3"
+sparedev="$TEST_BASE_DIR/file-vdev-spare"
+removedev=$(get_debug_device)
+
+typeset poolconfs=(
+ "mirror $filedev1 $removedev"
+ "raidz3 $filedev1 $filedev2 $filedev3 $removedev"
+ "mirror $filedev1 $filedev2 special mirror $filedev3 $removedev"
+)
+
+log_must truncate -s $SPA_MINDEVSIZE $filedev1
+log_must truncate -s $SPA_MINDEVSIZE $filedev2
+log_must truncate -s $SPA_MINDEVSIZE $filedev3
+log_must truncate -s $SPA_MINDEVSIZE $sparedev
+
+for conf in "${poolconfs[@]}"
+do
+ # 1. Create a pool
+ log_must zpool create -f $TESTPOOL $conf
+ block_device_wait ${DEV_DSKDIR}/${removedev}
+
+ mntpnt=$(get_prop mountpoint /$TESTPOOL) ||
+ log_fail "get_prop mountpoint /$TESTPOOL"
+
+ # 2. Simulate physical removal of one device
+ remove_disk $removedev
+ log_must mkfile 1m $mntpnt/file
+ log_must zpool sync $TESTPOOL
+
+ # 3. Verify the device is unvailable.
+ log_must wait_vdev_state $TESTPOOL $removedev "UNAVAIL"
+
+ # 4. Reattach the device
+ insert_disk $removedev
+
+ # 5. Verify the device is onlined
+ log_must wait_vdev_state $TESTPOOL $removedev "ONLINE"
+
+ # cleanup
+ destroy_pool $TESTPOOL
+ log_must parted "${DEV_DSKDIR}/${removedev}" -s -- mklabel msdos
+ block_device_wait ${DEV_DSKDIR}/${removedev}
+done
+
+# 6. Repeat the same tests with a spare device: zed will use the spare to handle
+# the removed data device
+for conf in "${poolconfs[@]}"
+do
+ # 1. Create a pool with a spare
+ log_must zpool create -f $TESTPOOL $conf
+ block_device_wait ${DEV_DSKDIR}/${removedev}
+ log_must zpool add $TESTPOOL spare $sparedev
+
+ mntpnt=$(get_prop mountpoint /$TESTPOOL) ||
+ log_fail "get_prop mountpoint /$TESTPOOL"
+
+ # 2. Simulate physical removal of one device
+ remove_disk $removedev
+ log_must mkfile 1m $mntpnt/file
+ log_must zpool sync $TESTPOOL
+
+ # 3. Verify the device is handled by the spare.
+ log_must wait_hotspare_state $TESTPOOL $sparedev "INUSE"
+ log_must wait_vdev_state $TESTPOOL $removedev "UNAVAIL"
+
+ # 4. Reattach the device
+ insert_disk $removedev
+
+ # 5. Verify the device is onlined
+ log_must wait_vdev_state $TESTPOOL $removedev "ONLINE"
+
+ # cleanup
+ destroy_pool $TESTPOOL
+ log_must parted "${DEV_DSKDIR}/${removedev}" -s -- mklabel msdos
+ block_device_wait ${DEV_DSKDIR}/${removedev}
+done
+
+# 7. Repeat the same tests again with a faulted spare device: zed should offline
+# the removed data device if no spare is available
+for conf in "${poolconfs[@]}"
+do
+ # 1. Create a pool with a spare
+ log_must zpool create -f $TESTPOOL $conf
+ block_device_wait ${DEV_DSKDIR}/${removedev}
+ log_must zpool add $TESTPOOL spare $sparedev
+
+ mntpnt=$(get_prop mountpoint /$TESTPOOL) ||
+ log_fail "get_prop mountpoint /$TESTPOOL"
+
+ # 2. Fault the spare device making it unavailable
+ log_must zpool offline -f $TESTPOOL $sparedev
+ log_must wait_hotspare_state $TESTPOOL $sparedev "FAULTED"
+
+ # 3. Simulate physical removal of one device
+ remove_disk $removedev
+ log_must mkfile 1m $mntpnt/file
+ log_must zpool sync $TESTPOOL
+
+ # 4. Verify the device is unavailable
+ log_must wait_vdev_state $TESTPOOL $removedev "UNAVAIL"
+
+ # 5. Reattach the device
+ insert_disk $removedev
+
+ # 6. Verify the device is onlined
+ log_must wait_vdev_state $TESTPOOL $removedev "ONLINE"
+
+ # cleanup
+ destroy_pool $TESTPOOL
+ log_must parted "${DEV_DSKDIR}/${removedev}" -s -- mklabel msdos
+ block_device_wait ${DEV_DSKDIR}/${removedev}
+done
+
+log_pass "ZED detects physically removed devices"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_online_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_online_001_pos.ksh
new file mode 100755
index 000000000000..03fc15a8a7cb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_online_001_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 (c) 2016, 2017 by Intel Corporation. All rights reserved.
+# Copyright (c) 2019 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Testing Fault Management Agent ZED Logic - Automated Auto-Online Test.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Export a pool
+# 3. Offline disk
+# 4. Import pool with missing disk
+# 5. Online disk
+# 6. ZED polls for an event change for online disk to be automatically
+# added back to the pool.
+#
+# Creates a raidz1 zpool using persistent disk path names
+# (ie not /dev/sdc).
+#
+# If loop devices are used, then a scsi_debug device is added to the pool.
+# otherwise just an sd device is used as the auto-online device.
+# Auto-online matches by devid.
+#
+verify_runnable "both"
+
+if ! is_physical_device $DISKS; then
+ log_unsupported "Unsupported disks for this test."
+fi
+
+function cleanup
+{
+ typeset disk
+
+ # Replace any disk that may have been removed at failure time.
+ for disk in $DISK1 $DISK2 $DISK3; do
+ # Skip loop devices and devices that currently exist.
+ is_loop_device $disk && continue
+ is_real_device $disk && continue
+ insert_disk $disk $(get_scsi_host $disk)
+ done
+ destroy_pool $TESTPOOL
+ unload_scsi_debug
+}
+
+log_assert "Testing automated auto-online FMA test"
+
+log_onexit cleanup
+
+# If using the default loop devices, need a scsi_debug device for auto-online
+if is_loop_device $DISK1; then
+ load_scsi_debug $SDSIZE $SDHOSTS $SDTGTS $SDLUNS '512b'
+ SDDEVICE=$(get_debug_device)
+ SDDEVICE_ID=$(get_persistent_disk_name $SDDEVICE)
+ autoonline_disks="$SDDEVICE"
+else
+ autoonline_disks="$DISK1 $DISK2 $DISK3"
+fi
+
+# Clear disk labels
+for i in {0..2}
+do
+ zpool labelclear -f /dev/disk/by-id/"${devs_id[i]}"
+done
+
+if is_loop_device $DISK1; then
+ # create a pool with one scsi_debug device and 3 loop devices
+ log_must zpool create -f $TESTPOOL raidz1 $SDDEVICE_ID $DISK1 \
+ $DISK2 $DISK3
+elif ( is_real_device $DISK1 || is_mpath_device $DISK1 ); then
+ # else use the persistent names for sd devices
+ log_must zpool create -f $TESTPOOL raidz1 ${devs_id[0]} \
+ ${devs_id[1]} ${devs_id[2]}
+else
+ log_fail "Disks are not supported for this test"
+fi
+
+# Add some data to the pool
+log_must mkfile $FSIZE /$TESTPOOL/data
+
+for offline_disk in $autoonline_disks
+do
+ log_must zpool export -F $TESTPOOL
+
+ host=$(get_scsi_host $offline_disk)
+
+ # Offline disk
+ remove_disk $offline_disk
+
+ # Reimport pool with drive missing
+ log_must zpool import $TESTPOOL
+ check_state $TESTPOOL "" "degraded"
+ if (($? != 0)); then
+ log_fail "$TESTPOOL is not degraded"
+ fi
+
+ # Clear zpool events
+ log_must zpool events -c
+
+ # Online disk
+ insert_disk $offline_disk $host
+
+ log_note "Delay for ZED auto-online"
+ typeset -i timeout=0
+ while true; do
+ if ((timeout == $MAXTIMEOUT)); then
+ log_fail "Timeout occurred"
+ fi
+ ((timeout++))
+
+ sleep 1
+ zpool events $TESTPOOL \
+ | egrep sysevent.fs.zfs.resilver_finish > /dev/null
+ if (($? == 0)); then
+ log_note "Auto-online of $offline_disk is complete"
+ sleep 1
+ break
+ fi
+ done
+
+ # Validate auto-online was successful
+ check_state $TESTPOOL "" "online"
+ if (($? != 0)); then
+ log_fail "$TESTPOOL is not back online"
+ fi
+ sleep 2
+done
+log_must zpool destroy $TESTPOOL
+
+log_pass "Auto-online test successful"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh
new file mode 100755
index 000000000000..0302c45373fa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_replace_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 (c) 2017 by Intel Corporation. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Testing Fault Management Agent ZED Logic - Automated Auto-Replace Test.
+#
+# STRATEGY:
+# 1. Update /etc/zfs/vdev_id.conf with scsidebug alias for a persistent path.
+# This creates keys ID_VDEV and ID_VDEV_PATH and set phys_path="scsidebug".
+# 2. Create a pool and set autoreplace=on (auto-replace is opt-in)
+# 3. Export a pool
+# 4. Wipe and offline the scsi_debug disk
+# 5. Import pool with missing disk
+# 6. Re-online the wiped scsi_debug disk
+# 7. Verify the ZED detects the new unused disk and adds it back to the pool
+#
+# Creates a raidz1 zpool using persistent disk path names
+# (ie not /dev/sdc)
+#
+# Auto-replace is opt in, and matches by phys_path.
+#
+
+verify_runnable "both"
+
+if ! is_physical_device $DISKS; then
+ log_unsupported "Unsupported disks for this test."
+fi
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ sed -i '/alias scsidebug/d' $VDEVID_CONF
+ unload_scsi_debug
+}
+
+log_assert "Testing automated auto-replace FMA test"
+log_onexit cleanup
+
+load_scsi_debug $SDSIZE $SDHOSTS $SDTGTS $SDLUNS '512b'
+SD=$(get_debug_device)
+SD_DEVICE_ID=$(get_persistent_disk_name $SD)
+SD_HOST=$(get_scsi_host $SD)
+
+# Register vdev_id alias for scsi_debug device to create a persistent path
+echo "alias scsidebug /dev/disk/by-id/$SD_DEVICE_ID" >>$VDEVID_CONF
+block_device_wait
+
+SD_DEVICE=$(udevadm info -q all -n $DEV_DSKDIR/$SD | \
+ awk -F'=' '/ID_VDEV=/{print $2; exit}')
+[[ -z $SD_DEVICE ]] && log_fail "vdev rule was not registered properly"
+
+log_must zpool events -c
+log_must zpool create -f $TESTPOOL raidz1 $SD_DEVICE $DISK1 $DISK2 $DISK3
+
+# Auto-replace is opt-in so need to set property
+log_must zpool set autoreplace=on $TESTPOOL
+
+# Add some data to the pool
+log_must mkfile $FSIZE /$TESTPOOL/data
+log_must zpool export $TESTPOOL
+
+# Wipe and offline the disk
+log_must dd if=/dev/zero of=/dev/disk/by-id/$SD_DEVICE_ID bs=1M count=$SDSIZE
+remove_disk $SD
+block_device_wait
+
+# Re-import pool with drive missing
+log_must zpool import $TESTPOOL
+log_must check_state $TESTPOOL "" "DEGRADED"
+block_device_wait
+
+# Online an empty disk in the same physical location
+insert_disk $SD $SD_HOST
+
+# Wait for the new disk to be online and replaced
+log_must wait_vdev_state $TESTPOOL "scsidebug" "ONLINE" $MAXTIMEOUT
+log_must wait_replacing $TESTPOOL
+
+# Validate auto-replace was successful
+log_must check_state $TESTPOOL "" "ONLINE"
+
+log_pass "Auto-replace test successful"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_spare_001_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_spare_001_pos.ksh
new file mode 100755
index 000000000000..b6af1a3f40f8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_spare_001_pos.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 by Intel Corporation. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Testing Fault Management Agent ZED Logic - Automated Auto-Spare Test when
+# drive is faulted due to IO ERRORS.
+#
+# STRATEGY:
+# 1. Create a pool with hot spares
+# 2. Create a filesystem with the primary cache disable to force reads
+# 3. Write a file to the pool to be read back
+# 4. Inject IO ERRORS on read with a zinject error handler
+# 5. Verify the ZED kicks in a hot spare and expected pool/device status
+# 6. Clear the fault
+# 7. Verify the hot spare is available and expected pool/device status
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+ destroy_pool $TESTPOOL
+ rm -f $VDEV_FILES $SPARE_FILE
+}
+
+log_assert "Testing automated auto-spare FMA test"
+
+log_onexit cleanup
+
+# Clear events from previous runs
+zed_events_drain
+
+TESTFILE="/$TESTPOOL/$TESTFS/testfile"
+
+for type in "mirror" "raidz" "raidz2"; do
+ # 1. Create a pool with hot spares
+ truncate -s $SPA_MINDEVSIZE $VDEV_FILES $SPARE_FILE
+ log_must zpool create -f $TESTPOOL $type $VDEV_FILES spare $SPARE_FILE
+
+ # 2. Create a filesystem with the primary cache disable to force reads
+ log_must zfs create -o primarycache=none $TESTPOOL/$TESTFS
+ log_must zfs set recordsize=16k $TESTPOOL/$TESTFS
+
+ # 3. Write a file to the pool to be read back
+ log_must dd if=/dev/urandom of=$TESTFILE bs=1M count=16
+
+ # 4. Inject IO ERRORS on read with a zinject error handler
+ log_must zinject -d $FAULT_FILE -e io -T read $TESTPOOL
+ log_must cp $TESTFILE /dev/null
+
+ # 5. Verify the ZED kicks in a hot spare and expected pool/device status
+ log_note "Wait for ZED to auto-spare"
+ log_must wait_vdev_state $TESTPOOL $FAULT_FILE "FAULTED" 60
+ log_must wait_vdev_state $TESTPOOL $SPARE_FILE "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $SPARE_FILE "INUSE"
+ log_must check_state $TESTPOOL "" "DEGRADED"
+
+ # 6. Clear the fault
+ log_must zinject -c all
+ log_must zpool clear $TESTPOOL $FAULT_FILE
+
+ # 7. Verify the hot spare is available and expected pool/device status
+ log_must wait_vdev_state $TESTPOOL $FAULT_FILE "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $SPARE_FILE "AVAIL"
+ log_must is_pool_resilvered $TESTPOOL
+ log_must check_state $TESTPOOL "" "ONLINE"
+
+ cleanup
+done
+
+log_pass "Auto-spare test successful"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_spare_002_pos.ksh b/tests/zfs-tests/tests/functional/fault/auto_spare_002_pos.ksh
new file mode 100755
index 000000000000..f6d720a01bf6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_spare_002_pos.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 by Intel Corporation. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Testing Fault Management Agent ZED Logic - Automated Auto-Spare Test when
+# drive is faulted due to CHECKSUM ERRORS.
+#
+# STRATEGY:
+# 1. Create a pool with hot spares
+# 2. Create a filesystem with the primary cache disable to force reads
+# 3. Write a file to the pool to be read back
+# 4. Inject CHECKSUM ERRORS on read with a zinject error handler
+# 5. Verify the ZED kicks in a hot spare and expected pool/device status
+# 6. Clear the fault
+# 7. Verify the hot spare is available and expected pool/device status
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+ destroy_pool $TESTPOOL
+ rm -f $VDEV_FILES $SPARE_FILE
+}
+
+log_assert "Testing automated auto-spare FMA test"
+
+log_onexit cleanup
+
+# Events not supported on FreeBSD
+if ! is_freebsd; then
+ # Clear events from previous runs
+ zed_events_drain
+fi
+
+TESTFILE="/$TESTPOOL/$TESTFS/testfile"
+
+for type in "mirror" "raidz" "raidz2"; do
+ # 1. Create a pool with hot spares
+ truncate -s $SPA_MINDEVSIZE $VDEV_FILES $SPARE_FILE
+ log_must zpool create -f $TESTPOOL $type $VDEV_FILES spare $SPARE_FILE
+
+ # 2. Create a filesystem with the primary cache disable to force reads
+ log_must zfs create -o primarycache=none $TESTPOOL/$TESTFS
+ log_must zfs set recordsize=16k $TESTPOOL/$TESTFS
+
+ # 3. Write a file to the pool to be read back
+ log_must dd if=/dev/urandom of=$TESTFILE bs=1M count=16
+
+ # 4. Inject CHECKSUM ERRORS on read with a zinject error handler
+ log_must zinject -d $FAULT_FILE -e corrupt -f 50 -T read $TESTPOOL
+ log_must cp $TESTFILE /dev/null
+
+ # 5. Verify the ZED kicks in a hot spare and expected pool/device status
+ log_note "Wait for ZED to auto-spare"
+ log_must wait_vdev_state $TESTPOOL $FAULT_FILE "DEGRADED" 60
+ log_must wait_vdev_state $TESTPOOL $SPARE_FILE "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $SPARE_FILE "INUSE"
+ log_must check_state $TESTPOOL "" "DEGRADED"
+
+ # 6. Clear the fault
+ log_must zinject -c all
+ log_must zpool clear $TESTPOOL $FAULT_FILE
+
+ # 7. Verify the hot spare is available and expected pool/device status
+ log_must wait_vdev_state $TESTPOOL $FAULT_FILE "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $SPARE_FILE "AVAIL"
+ log_must check_state $TESTPOOL "" "ONLINE"
+
+ cleanup
+done
+
+log_pass "Auto-spare test successful"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_spare_ashift.ksh b/tests/zfs-tests/tests/functional/fault/auto_spare_ashift.ksh
new file mode 100755
index 000000000000..e9857518ed8a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_spare_ashift.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 by Intel Corporation. All rights reserved.
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Testing Fault Management Agent ZED Logic - Automated Auto-Spare Test when
+# drive is faulted and a custom ashift value needs to be provided to replace it.
+#
+# STRATEGY:
+# 1. Create a pool from 512b devices and set "ashift" pool property accordingly
+# 2. Add one 512e spare device (4Kn would generate IO errors on replace)
+# 3. Inject IO errors with a zinject error handler
+# 4. Start a scrub
+# 5. Verify the ZED kicks in the hot spare and expected pool/device status
+# 6. Clear the fault
+# 7. Verify the hot spare is available and expected pool/device status
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+ destroy_pool $TESTPOOL
+ unload_scsi_debug
+ rm -f $SAFE_DEVICE $FAIL_DEVICE
+}
+
+log_assert "ZED should replace a device using the configured ashift property"
+log_onexit cleanup
+
+# Clear events from previous runs
+zed_events_drain
+
+SAFE_DEVICE="$TEST_BASE_DIR/safe-dev"
+FAIL_DEVICE="$TEST_BASE_DIR/fail-dev"
+
+# 1. Create a pool from 512b devices and set "ashift" pool property accordingly
+for vdev in $SAFE_DEVICE $FAIL_DEVICE; do
+ truncate -s $SPA_MINDEVSIZE $vdev
+done
+log_must zpool create -f $TESTPOOL mirror $SAFE_DEVICE $FAIL_DEVICE
+# NOTE: file VDEVs should be added as 512b devices, verify this "just in case"
+for vdev in $SAFE_DEVICE $FAIL_DEVICE; do
+ verify_eq "9" "$(zdb -e -l $vdev | awk '/ashift: /{print $2}')" "ashift"
+done
+log_must zpool set ashift=9 $TESTPOOL
+
+# 2. Add one 512e spare device (4Kn would generate IO errors on replace)
+# NOTE: must be larger than the existing 512b devices, add 32m of fudge
+load_scsi_debug $(($SPA_MINDEVSIZE/1024/1024+32)) $SDHOSTS $SDTGTS $SDLUNS '512e'
+SPARE_DEVICE=$(get_debug_device)
+log_must_busy zpool add $TESTPOOL spare $SPARE_DEVICE
+
+# 3. Inject IO errors with a zinject error handler
+log_must zinject -d $FAIL_DEVICE -e io -T all -f 100 $TESTPOOL
+
+# 4. Start a scrub
+log_must zpool scrub $TESTPOOL
+
+# 5. Verify the ZED kicks in a hot spare and expected pool/device status
+log_note "Wait for ZED to auto-spare"
+log_must wait_vdev_state $TESTPOOL $FAIL_DEVICE "FAULTED" 60
+log_must wait_vdev_state $TESTPOOL $SPARE_DEVICE "ONLINE" 60
+log_must wait_hotspare_state $TESTPOOL $SPARE_DEVICE "INUSE"
+log_must check_state $TESTPOOL "" "DEGRADED"
+
+# 6. Clear the fault
+log_must zinject -c all
+log_must zpool clear $TESTPOOL $FAIL_DEVICE
+
+# 7. Verify the hot spare is available and expected pool/device status
+log_must wait_vdev_state $TESTPOOL $FAIL_DEVICE "ONLINE" 60
+log_must wait_hotspare_state $TESTPOOL $SPARE_DEVICE "AVAIL"
+log_must is_pool_resilvered $TESTPOOL
+log_must check_state $TESTPOOL "" "ONLINE"
+
+log_pass "ZED successfully replaces a device using the configured ashift property"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_spare_multiple.ksh b/tests/zfs-tests/tests/functional/fault/auto_spare_multiple.ksh
new file mode 100755
index 000000000000..bec41352752b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_spare_multiple.ksh
@@ -0,0 +1,155 @@
+#!/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 Intel Corporation. All rights reserved.
+# Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Testing Fault Management Agent ZED Logic - Automated Auto-Spare Test when
+# multiple drives are faulted.
+#
+# STRATEGY:
+# 1. Create a pool with two hot spares
+# 2. Inject IO ERRORS with a zinject error handler on the first device
+# 3. Start a scrub
+# 4. Verify the ZED kicks in a hot spare and expected pool/device status
+# 5. Inject IO ERRORS on a second device
+# 6. Start a scrub
+# 7. Verify the ZED kicks in a second hot spare
+# 8. Clear the fault on both devices
+# 9. Verify the hot spares are available and expected pool/device status
+# 10. Rinse and repeat, this time faulting both devices at the same time
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+ destroy_pool $TESTPOOL
+ rm -f $DATA_DEVS $SPARE_DEVS
+}
+
+log_assert "ZED should be able to handle multiple faulted devices"
+log_onexit cleanup
+
+# Events not supported on FreeBSD
+if ! is_freebsd; then
+ # Clear events from previous runs
+ zed_events_drain
+fi
+
+FAULT_DEV1="$TEST_BASE_DIR/fault-dev1"
+FAULT_DEV2="$TEST_BASE_DIR/fault-dev2"
+SAFE_DEV1="$TEST_BASE_DIR/safe-dev1"
+SAFE_DEV2="$TEST_BASE_DIR/safe-dev2"
+DATA_DEVS="$FAULT_DEV1 $FAULT_DEV2 $SAFE_DEV1 $SAFE_DEV2"
+SPARE_DEV1="$TEST_BASE_DIR/spare-dev1"
+SPARE_DEV2="$TEST_BASE_DIR/spare-dev2"
+SPARE_DEVS="$SPARE_DEV1 $SPARE_DEV2"
+
+for type in "mirror" "raidz" "raidz2" "raidz3"; do
+ # 1. Create a pool with two hot spares
+ truncate -s $SPA_MINDEVSIZE $DATA_DEVS $SPARE_DEVS
+ log_must zpool create -f $TESTPOOL $type $DATA_DEVS spare $SPARE_DEVS
+
+ # 2. Inject IO ERRORS with a zinject error handler on the first device
+ log_must zinject -d $FAULT_DEV1 -e io -T all -f 100 $TESTPOOL
+
+ # 3. Start a scrub
+ log_must zpool scrub $TESTPOOL
+
+ # 4. Verify the ZED kicks in a hot spare and expected pool/device status
+ log_note "Wait for ZED to auto-spare"
+ log_must wait_vdev_state $TESTPOOL $FAULT_DEV1 "FAULTED" 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"
+
+ # 5. Inject IO ERRORS on a second device
+ log_must zinject -d $FAULT_DEV2 -e io -T all -f 100 $TESTPOOL
+
+ # 6. Start a scrub
+ while is_pool_scrubbing $TESTPOOL || is_pool_resilvering $TESTPOOL; do
+ sleep 1
+ done
+ log_must zpool scrub $TESTPOOL
+
+ # 7. Verify the ZED kicks in a second hot spare
+ log_note "Wait for ZED to auto-spare"
+ log_must wait_vdev_state $TESTPOOL $FAULT_DEV2 "FAULTED" 60
+ log_must wait_vdev_state $TESTPOOL $SPARE_DEV2 "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $SPARE_DEV2 "INUSE"
+ log_must check_state $TESTPOOL "" "DEGRADED"
+
+ # 8. Clear the fault on both devices
+ log_must zinject -c all
+ log_must zpool clear $TESTPOOL $FAULT_DEV1
+ log_must zpool clear $TESTPOOL $FAULT_DEV2
+
+ # 9. Verify the hot spares are available and expected pool/device status
+ log_must wait_vdev_state $TESTPOOL $FAULT_DEV1 "ONLINE" 60
+ log_must wait_vdev_state $TESTPOOL $FAULT_DEV2 "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $SPARE_DEV1 "AVAIL"
+ log_must wait_hotspare_state $TESTPOOL $SPARE_DEV2 "AVAIL"
+ log_must check_state $TESTPOOL "" "ONLINE"
+
+ # Cleanup
+ cleanup
+done
+
+# Rinse and repeat, this time faulting both devices at the same time
+# NOTE: "raidz" is excluded since it cannot survive 2 faulted devices
+# NOTE: "mirror" is a 4-way mirror here and should survive this test
+for type in "mirror" "raidz2" "raidz3"; do
+ # 1. Create a pool with two hot spares
+ truncate -s $SPA_MINDEVSIZE $DATA_DEVS $SPARE_DEVS
+ log_must zpool create -f $TESTPOOL $type $DATA_DEVS spare $SPARE_DEVS
+
+ # 2. Inject IO ERRORS with a zinject error handler on two devices
+ log_must eval "zinject -d $FAULT_DEV1 -e io -T all -f 100 $TESTPOOL &"
+ log_must eval "zinject -d $FAULT_DEV2 -e io -T all -f 100 $TESTPOOL &"
+
+ # 3. Start a scrub
+ log_must zpool scrub $TESTPOOL
+
+ # 4. Verify the ZED kicks in two hot spares and expected pool/device status
+ log_note "Wait for ZED to auto-spare"
+ log_must wait_vdev_state $TESTPOOL $FAULT_DEV1 "FAULTED" 60
+ log_must wait_vdev_state $TESTPOOL $FAULT_DEV2 "FAULTED" 60
+ log_must wait_vdev_state $TESTPOOL $SPARE_DEV1 "ONLINE" 60
+ log_must wait_vdev_state $TESTPOOL $SPARE_DEV2 "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $SPARE_DEV1 "INUSE"
+ log_must wait_hotspare_state $TESTPOOL $SPARE_DEV2 "INUSE"
+ log_must check_state $TESTPOOL "" "DEGRADED"
+
+ # 5. Clear the fault on both devices
+ log_must zinject -c all
+ log_must zpool clear $TESTPOOL $FAULT_DEV1
+ log_must zpool clear $TESTPOOL $FAULT_DEV2
+
+ # Cleanup
+ cleanup
+done
+
+log_pass "ZED successfully handles multiple faulted devices"
diff --git a/tests/zfs-tests/tests/functional/fault/auto_spare_shared.ksh b/tests/zfs-tests/tests/functional/fault/auto_spare_shared.ksh
new file mode 100755
index 000000000000..467161359df4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/auto_spare_shared.ksh
@@ -0,0 +1,119 @@
+#!/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
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Spare devices (both files and disks) can be shared among different ZFS pools.
+#
+# STRATEGY:
+# 1. Create two pools
+# 2. Add the same spare device to different pools
+# 3. Inject IO errors with a zinject error handler
+# 4. Start a scrub
+# 5. Verify the ZED kicks in a hot spare and check pool/device status
+# 6. Clear the fault
+# 7. Verify the hot spare is available and check pool/device status
+#
+
+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
+{
+ log_must zinject -c all
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL1
+ unload_scsi_debug
+ rm -f $SAFE_FILEDEVPOOL1 $SAFE_FILEDEVPOOL2 $FAIL_FILEDEVPOOL1 \
+ $FAIL_FILEDEVPOOL2 $SPARE_FILEDEV
+}
+
+log_assert "Spare devices can be shared among different ZFS pools"
+log_onexit cleanup
+
+# Clear events from previous runs
+zed_events_drain
+
+SAFE_FILEDEVPOOL1="$TEST_BASE_DIR/file-safe-dev1"
+FAIL_FILEDEVPOOL1="$TEST_BASE_DIR/file-fail-dev1"
+SAFE_FILEDEVPOOL2="$TEST_BASE_DIR/file-safe-dev2"
+FAIL_FILEDEVPOOL2="$TEST_BASE_DIR/file-fail-dev2"
+SPARE_FILEDEV="$TEST_BASE_DIR/file-spare-dev"
+SPARE_DISKDEV="$(get_debug_device)"
+
+for vdev in $SAFE_FILEDEVPOOL1 $SAFE_FILEDEVPOOL2 $FAIL_FILEDEVPOOL1 \
+ $FAIL_FILEDEVPOOL2 $SPARE_FILEDEV; do
+ log_must truncate -s $SPA_MINDEVSIZE $vdev
+done
+
+for spare in $SPARE_FILEDEV $SPARE_DISKDEV; do
+ # 1. Create two pools
+ log_must zpool create -f $TESTPOOL mirror $SAFE_FILEDEVPOOL1 $FAIL_FILEDEVPOOL1
+ log_must zpool create -f $TESTPOOL1 mirror $SAFE_FILEDEVPOOL2 $FAIL_FILEDEVPOOL2
+
+ # 2. Add the same spare device to different pools
+ log_must_busy zpool add $TESTPOOL spare $spare
+ log_must_busy zpool add $TESTPOOL1 spare $spare
+ log_must wait_hotspare_state $TESTPOOL $spare "AVAIL"
+ log_must wait_hotspare_state $TESTPOOL1 $spare "AVAIL"
+
+ # 3. Inject IO errors with a zinject error handler
+ log_must zinject -d $FAIL_FILEDEVPOOL1 -e io -T all -f 100 $TESTPOOL
+ log_must zinject -d $FAIL_FILEDEVPOOL2 -e io -T all -f 100 $TESTPOOL1
+
+ # 4. Start a scrub
+ log_must zpool scrub $TESTPOOL
+ log_must zpool scrub $TESTPOOL1
+
+ # 5. Verify the ZED kicks in a hot spare and check pool/device status
+ log_note "Wait for ZED to auto-spare"
+ log_must wait_vdev_state $TESTPOOL $FAIL_FILEDEVPOOL1 "FAULTED" 60
+ log_must wait_vdev_state $TESTPOOL $spare "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $spare "INUSE"
+ log_must check_state $TESTPOOL "" "DEGRADED"
+
+ # 6. Clear the fault
+ log_must zinject -c all
+ log_must zpool clear $TESTPOOL $FAIL_FILEDEVPOOL1
+
+ # 7. Verify the hot spare is available and check pool/device status
+ log_must wait_vdev_state $TESTPOOL $FAIL_FILEDEVPOOL1 "ONLINE" 60
+ log_must wait_hotspare_state $TESTPOOL $spare "AVAIL"
+ log_must is_pool_resilvered $TESTPOOL
+ log_must check_state $TESTPOOL "" "ONLINE"
+
+ # Cleanup
+ destroy_pool $TESTPOOL
+ destroy_pool $TESTPOOL1
+done
+
+log_pass "Spare devices can be shared among different ZFS pools"
diff --git a/tests/zfs-tests/tests/functional/fault/cleanup.ksh b/tests/zfs-tests/tests/functional/fault/cleanup.ksh
new file mode 100755
index 000000000000..45b94723a543
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/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 (c) 2016, 2017 by Intel Corporation. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+verify_runnable "global"
+
+cleanup_devices $DISKS
+
+zed_stop
+zed_cleanup resilver_finish-start-scrub.sh
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/fault/decompress_fault.ksh b/tests/zfs-tests/tests/functional/fault/decompress_fault.ksh
new file mode 100755
index 000000000000..81eab5666627
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/decompress_fault.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 (c) 2018 by Datto Inc.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Test that injected decompression errors are handled correctly.
+#
+# STRATEGY:
+# 1. Create an compressed dataset with a test file
+# 2. Inject decompression errors on the file 20% of the time
+# 3. Read the file to confirm that errors are handled correctly
+# 4. Confirm that the decompression injection was added to the ZED logs
+#
+
+log_assert "Testing that injected decompression errors are handled correctly"
+
+function cleanup
+{
+ log_must set_tunable64 COMPRESSED_ARC_ENABLED 1
+ log_must zinject -c all
+ default_cleanup_noexit
+}
+
+log_onexit cleanup
+
+default_mirror_setup_noexit $DISK1 $DISK2
+log_must set_tunable64 COMPRESSED_ARC_ENABLED 0
+log_must zfs create -o compression=on $TESTPOOL/fs
+mntpt=$(get_prop mountpoint $TESTPOOL/fs)
+write_compressible $mntpt 32m 1 1024k "testfile"
+log_must sync
+log_must zfs umount $TESTPOOL/fs
+log_must zfs mount $TESTPOOL/fs
+log_must zinject -a -t data -e decompress -f 20 $mntpt/testfile.0
+log_mustnot eval "cat $mntpt/testfile.0 > /dev/null"
+if ! is_freebsd; then
+ # Events are not supported on FreeBSD
+ log_must eval "zpool events $TESTPOOL | grep -q 'data'"
+fi
+
+log_pass "Injected decompression errors are handled correctly"
diff --git a/tests/zfs-tests/tests/functional/fault/decrypt_fault.ksh b/tests/zfs-tests/tests/functional/fault/decrypt_fault.ksh
new file mode 100755
index 000000000000..d81c4b2bd2f2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/decrypt_fault.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 (c) 2018 by Datto Inc.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Test that injected decryption errors are handled correctly.
+#
+# STRATEGY:
+# 1. Create an encrypted dataset with a test file
+# 2. Inject decryption errors on the file 20% of the time
+# 3. Read the file to confirm that errors are handled correctly
+# 4. Confirm that the decryption injection was added to the ZED logs
+#
+
+log_assert "Testing that injected decryption errors are handled correctly"
+
+function cleanup
+{
+ log_must zinject -c all
+ default_cleanup_noexit
+}
+
+log_onexit cleanup
+
+default_mirror_setup_noexit $DISK1 $DISK2
+log_must eval "echo 'password' | zfs create -o encryption=on \
+ -o keyformat=passphrase -o keylocation=prompt $TESTPOOL/fs"
+mntpt=$(get_prop mountpoint $TESTPOOL/fs)
+log_must mkfile 32M $mntpt/file1
+
+log_must zinject -a -t data -e decrypt -f 20 $mntpt/file1
+log_must zfs umount $TESTPOOL/fs
+log_must zfs mount $TESTPOOL/fs
+
+log_mustnot eval "cat $mntpt/file1 > /dev/null"
+# Events are not supported on FreeBSD
+if ! is_freebsd; then
+ log_must eval "zpool events $TESTPOOL | grep -q 'authentication'"
+fi
+
+log_pass "Injected decryption errors are handled correctly"
diff --git a/tests/zfs-tests/tests/functional/fault/fault.cfg b/tests/zfs-tests/tests/functional/fault/fault.cfg
new file mode 100644
index 000000000000..839330ed47dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/fault.cfg
@@ -0,0 +1,55 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2017 by Intel Corporation. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+export DISKSARRAY=$DISKS
+export FSIZE=10M
+export MAXTIMEOUT=30
+
+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
+
+export VDEV_FILES="$TEST_BASE_DIR/file-1 $TEST_BASE_DIR/file-2 \
+ $TEST_BASE_DIR/file-3 $TEST_BASE_DIR/file-4"
+export SPARE_FILE="$TEST_BASE_DIR/spare-1"
+export FAULT_FILE="$TEST_BASE_DIR/file-1"
diff --git a/tests/zfs-tests/tests/functional/fault/scrub_after_resilver.ksh b/tests/zfs-tests/tests/functional/fault/scrub_after_resilver.ksh
new file mode 100755
index 000000000000..db4a4ad55ef1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/scrub_after_resilver.ksh
@@ -0,0 +1,65 @@
+#!/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.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+#
+# DESCRIPTION:
+# Test the scrub after resilver zedlet
+#
+# STRATEGY:
+# 1. Create a mirrored pool
+# 2. Fault a disk
+# 3. Replace the disk, starting a resilver
+# 4. Verify that a scrub happens after the resilver finishes
+#
+
+log_assert "Testing the scrub after resilver zedlet"
+
+# Backup our zed.rc
+zedrc_backup=$(zed_rc_backup)
+
+# Enable ZED_SCRUB_AFTER_RESILVER in zed.rc
+zed_rc_set ZED_SCRUB_AFTER_RESILVER 1
+
+function cleanup
+{
+ # Restore our zed.rc
+ log_must zed_rc_restore $zedrc_backup
+ default_cleanup_noexit
+ log_must zpool labelclear -f $DISK1
+}
+
+log_onexit cleanup
+
+verify_disk_count "$DISKS" 3
+default_mirror_setup_noexit $DISK1 $DISK2
+
+log_must zpool offline -f $TESTPOOL $DISK1
+
+# Write to our degraded pool so we have some data to resilver
+log_must mkfile 16M $TESTDIR/file1
+
+# Replace the failed disks, forcing a resilver
+log_must zpool replace $TESTPOOL $DISK1 $DISK3
+
+# Wait for the resilver to finish, and then the subsequent scrub to finish.
+# Waiting for the scrub has the effect of waiting for both. Timeout after 10
+# seconds if nothing is happening.
+log_must wait_scrubbed $TESTPOOL
+log_pass "Successfully ran the scrub after resilver zedlet"
diff --git a/tests/zfs-tests/tests/functional/fault/setup.ksh b/tests/zfs-tests/tests/functional/fault/setup.ksh
new file mode 100755
index 000000000000..b78ee8ccdc98
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/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 (c) 2016, 2017 by Intel Corporation. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/fault/fault.cfg
+
+verify_runnable "global"
+
+zed_setup resilver_finish-start-scrub.sh
+zed_start
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/fault/zpool_status_-s.ksh b/tests/zfs-tests/tests/functional/fault/zpool_status_-s.ksh
new file mode 100755
index 000000000000..85f0083a0eb6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/fault/zpool_status_-s.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) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify zpool status -s (slow IOs) works
+#
+# STRATEGY:
+# 1. Create a file
+# 2. Inject slow IOs into the pool
+# 3. Verify we can see the slow IOs with "zpool status -s".
+# 4. Verify we can see delay events.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/zpool_script.shlib
+
+DISK=${DISKS%% *}
+
+verify_runnable "both"
+
+default_mirror_setup_noexit $DISKS
+
+function cleanup
+{
+ log_must zinject -c all
+ log_must set_tunable64 ZIO_SLOW_IO_MS $OLD_SLOW_IO
+ log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND $OLD_SLOW_IO_EVENTS
+ default_cleanup_noexit
+}
+
+log_onexit cleanup
+
+log_must zpool events -c
+
+# Mark any IOs greater than 10ms as slow IOs
+OLD_SLOW_IO=$(get_tunable ZIO_SLOW_IO_MS)
+OLD_SLOW_IO_EVENTS=$(get_tunable SLOW_IO_EVENTS_PER_SECOND)
+log_must set_tunable64 ZIO_SLOW_IO_MS 10
+log_must set_tunable64 SLOW_IO_EVENTS_PER_SECOND 1000
+
+# Create 20ms IOs
+log_must zinject -d $DISK -D20:100 $TESTPOOL
+log_must mkfile 1048576 /$TESTPOOL/testfile
+log_must zpool sync $TESTPOOL
+
+log_must zinject -c all
+SLOW_IOS=$(zpool status -sp | grep "$DISK" | awk '{print $6}')
+DELAY_EVENTS=$(zpool events | grep delay | wc -l)
+
+if [ $SLOW_IOS -gt 0 ] && [ $DELAY_EVENTS -gt 0 ] ; then
+ log_pass "Correctly saw $SLOW_IOS slow IOs and $DELAY_EVENTS delay events"
+else
+ log_fail "Only saw $SLOW_IOS slow IOs and $DELAY_EVENTS delay events"
+fi
diff --git a/tests/zfs-tests/tests/functional/features/Makefile.am b/tests/zfs-tests/tests/functional/features/Makefile.am
new file mode 100644
index 000000000000..3657461e6604
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/Makefile.am
@@ -0,0 +1,3 @@
+SUBDIRS = \
+ async_destroy \
+ large_dnode
diff --git a/tests/zfs-tests/tests/functional/features/async_destroy/Makefile.am b/tests/zfs-tests/tests/functional/features/async_destroy/Makefile.am
new file mode 100644
index 000000000000..4c777878d689
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/async_destroy/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/features/async_destroy
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ async_destroy_001_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_pos.ksh b/tests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_pos.ksh
new file mode 100755
index 000000000000..23fb16d6ed5a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/async_destroy/async_destroy_001_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 (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Exercise the traversal suspend/resume code in async_destroy by
+# destroying a file system that has more blocks than we can free
+# in a single txg.
+#
+# STRATEGY:
+# 1. Create a file system
+# 2. Set recordsize to 512 to create the maximum number of blocks
+# 3. Set compression to off to force zero-ed blocks to be written
+# 4. dd a lot of data from /dev/zero to the file system
+# 5. Destroy the file system
+# 6. Wait for the freeing property to go to 0
+# 7. Use zdb to check for leaked blocks
+#
+
+TEST_FS=$TESTPOOL/async_destroy
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TEST_FS && log_must zfs destroy $TEST_FS
+ log_must set_tunable64 ASYNC_BLOCK_MAX_BLOCKS 100000
+}
+
+log_onexit cleanup
+log_assert "async_destroy can suspend and resume traversal"
+
+log_must zfs create -o recordsize=1k -o compression=off $TEST_FS
+
+# Fill with 128,000 blocks.
+log_must dd bs=1024k count=128 if=/dev/zero of=/$TEST_FS/file
+
+#
+# Decrease the max blocks to free each txg, so that freeing takes
+# long enough that we can observe it.
+#
+log_must set_tunable64 ASYNC_BLOCK_MAX_BLOCKS 100
+
+log_must sync
+log_must zfs destroy $TEST_FS
+
+#
+# We monitor the freeing property, to verify we can see blocks being
+# freed while the suspend/resume code is exercised.
+#
+t0=$SECONDS
+count=0
+while [[ $((SECONDS - t0)) -lt 10 ]]; do
+ [[ "0" != "$(zpool list -Ho freeing $TESTPOOL)" ]] && ((count++))
+ [[ $count -gt 1 ]] && break
+ sleep 1
+done
+
+[[ $count -eq 0 ]] && log_fail "Freeing property remained empty"
+
+#
+# After a bit, go back to allowing an unlimited amount of freeing
+# per txg.
+#
+sleep 10
+log_must set_tunable64 ASYNC_BLOCK_MAX_BLOCKS 100000
+
+# Wait for everything to be freed.
+while [[ "0" != "$(zpool list -Ho freeing $TESTPOOL)" ]]; do
+ [[ $((SECONDS - t0)) -gt 180 ]] && \
+ log_fail "Timed out waiting for freeing to drop to zero"
+done
+
+# Check for leaked blocks.
+log_must zdb -b $TESTPOOL
+
+log_pass "async_destroy can suspend and resume traversal"
diff --git a/tests/zfs-tests/tests/functional/features/async_destroy/cleanup.ksh b/tests/zfs-tests/tests/functional/features/async_destroy/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/async_destroy/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/features/async_destroy/setup.ksh b/tests/zfs-tests/tests/functional/features/async_destroy/setup.ksh
new file mode 100755
index 000000000000..d275e063b13a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/async_destroy/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/Makefile.am b/tests/zfs-tests/tests/functional/features/large_dnode/Makefile.am
new file mode 100644
index 000000000000..13ba3ab33d9e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/Makefile.am
@@ -0,0 +1,13 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/features/large_dnode
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ large_dnode_001_pos.ksh \
+ large_dnode_002_pos.ksh \
+ large_dnode_003_pos.ksh \
+ large_dnode_004_neg.ksh \
+ large_dnode_005_pos.ksh \
+ large_dnode_006_pos.ksh \
+ large_dnode_007_neg.ksh \
+ large_dnode_008_pos.ksh \
+ large_dnode_009_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/cleanup.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/cleanup.ksh
new file mode 100755
index 000000000000..60e481d998a2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/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 (c) 2016 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_pos.ksh
new file mode 100755
index 000000000000..d3530292e81a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_001_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 (c) 2016 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that the dnode sizes of newly created files are consistent
+# with the dnodesize dataset property.
+#
+# STRATEGY:
+# 1. Create a file system
+# 2. Set dnodesize to a legal literal value
+# 3. Create a file
+# 4. Repeat 2-3 for all legal literal values of dnodesize values
+# 5. Unmount the file system
+# 6. Use zdb to check expected dnode sizes
+#
+
+TEST_FS=$TESTPOOL/large_dnode
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TEST_FS && log_must zfs destroy $TEST_FS
+}
+
+log_onexit cleanup
+log_assert "dnode sizes are consistent with dnodesize dataset property"
+
+log_must zfs create $TEST_FS
+
+set -A dnsizes "512" "1k" "2k" "4k" "8k" "16k"
+set -A inodes
+
+for ((i=0; i < ${#dnsizes[*]}; i++)) ; do
+ size=${dnsizes[$i]}
+ if [[ $size == "512" ]] ; then
+ size="legacy"
+ fi
+ file=/$TEST_FS/file.$size
+ log_must zfs set dnsize=$size $TEST_FS
+ touch $file
+ inodes[$i]=$(ls -li $file | awk '{print $1}')
+done
+
+log_must zfs umount $TEST_FS
+
+for ((i=0; i < ${#dnsizes[*]}; i++)) ; do
+ dnsize=$(zdb -dddd $TEST_FS ${inodes[$i]} |
+ awk '/ZFS plain file/ {print $6}' | tr K k)
+ if [[ "$dnsize" != "${dnsizes[$i]}" ]]; then
+ log_fail "dnode size is $dnsize (expected ${dnsizes[$i]})"
+ fi
+done
+
+log_pass "dnode sizes are consistent with dnodesize dataset property"
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_pos.ksh
new file mode 100755
index 000000000000..c2b32ad66217
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_002_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 (c) 2016 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that extended attributes can use extra bonus space of a large
+# dnode without kicking in a spill block.
+#
+# STRATEGY:
+# 1. Create a file system with xattr=sa
+# 2. Set dnodesize to a legal literal value
+# 3. Create a file
+# 4 Store an xattr that fits within the dnode size
+# 4. Repeat 2-3 for all legal literal values of dnodesize values
+# 5. Unmount the file system
+# 6. Use zdb to check for missing SPILL_BLKPTR flag
+#
+
+TEST_FS=$TESTPOOL/large_dnode
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TEST_FS && log_must zfs destroy $TEST_FS
+}
+
+log_onexit cleanup
+log_assert "extended attributes use extra bonus space of a large dnode"
+
+log_must zfs create -o xattr=sa $TEST_FS
+
+# Store dnode size minus 512 in an xattr
+set -A xattr_sizes "512" "1536" "3584" "7680" "15872"
+set -A prop_values "1k" "2k" "4k" "8k" "16k"
+set -A inodes
+
+for ((i=0; i < ${#prop_values[*]}; i++)) ; do
+ prop_val=${prop_values[$i]}
+ file=/$TEST_FS/file.$prop_val
+ log_must zfs set dnsize=$prop_val $TEST_FS
+ touch $file
+ xattr_size=${xattr_sizes[$i]}
+ xattr_name=user.foo
+ xattr_val=$(dd if=/dev/urandom bs=1 count=$xattr_size |
+ openssl enc -a -A)
+ log_must setfattr -n $xattr_name -v 0s$xattr_val $file
+ inodes[$i]=$(ls -li $file | awk '{print $1}')
+done
+
+log_must zfs umount $TEST_FS
+
+for ((i=0; i < ${#inodes[*]}; i++)) ; do
+ log_mustnot eval "zdb -dddd $TEST_FS ${inodes[$i]} | grep SPILL_BLKPTR"
+done
+
+log_pass "extended attributes use extra bonus space of a large dnode"
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_003_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_003_pos.ksh
new file mode 100755
index 000000000000..20989e1d7741
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_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) 2016 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $LDNPOOL ; then
+ log_must zpool destroy -f $LDNPOOL
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "feature correctly switches between enabled and active"
+
+LDNPOOL=ldnpool
+LDNFS=$LDNPOOL/large_dnode
+log_must mkfile 64M $TESTDIR/$LDNPOOL
+log_must zpool create $LDNPOOL $TESTDIR/$LDNPOOL
+
+
+state=$(zpool list -Ho feature@large_dnode $LDNPOOL)
+if [[ "$state" != "enabled" ]]; then
+ log_fail "large_dnode has state $state (expected enabled)"
+fi
+
+log_must zfs create -o dnodesize=1k $LDNFS
+log_must touch /$LDNFS/foo
+log_must zfs unmount $LDNFS
+
+state=$(zpool list -Ho feature@large_dnode $LDNPOOL)
+if [[ "$state" != "active" ]]; then
+ log_fail "large_dnode has state $state (expected active)"
+fi
+
+log_must zfs destroy $LDNFS
+
+state=$(zpool list -Ho feature@large_dnode $LDNPOOL)
+if [[ "$state" != "enabled" ]]; then
+ log_fail "large_dnode has state $state (expected enabled)"
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_neg.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_neg.ksh
new file mode 100755
index 000000000000..3fa1cabe063a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_004_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 (c) 2016 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+#
+# Copyright 2007 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
+
+verify_runnable "both"
+
+TEST_FS=$TESTPOOL/large_dnode
+TEST_SNAP=$TESTPOOL/large_dnode@ldnsnap
+TEST_STREAM=$TESTDIR/ldnsnap
+
+function cleanup
+{
+ if datasetexists $TEST_FS ; then
+ log_must zfs destroy -r $TEST_FS
+ fi
+
+ if datasetexists $LGCYPOOL ; then
+ log_must zpool destroy -f $LGCYPOOL
+ fi
+
+ rm -f $TEST_STREAM
+}
+
+log_onexit cleanup
+log_assert "zfs send stream with large dnodes not accepted by legacy pool"
+
+log_must zfs create -o dnodesize=1k $TEST_FS
+log_must touch /$TEST_FS/foo
+log_must zfs umount $TEST_FS
+log_must zfs snap $TEST_SNAP
+log_must eval "zfs send $TEST_SNAP > $TEST_STREAM"
+
+LGCYPOOL=ldnpool
+LGCYFS=$LGCYPOOL/legacy
+log_must mkfile 64M $TESTDIR/$LGCYPOOL
+log_must zpool create -d $LGCYPOOL $TESTDIR/$LGCYPOOL
+log_mustnot eval "zfs recv $LGCYFS < $TEST_STREAM"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_pos.ksh
new file mode 100755
index 000000000000..a2d92673b180
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_005_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 (c) 2016 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+TEST_SEND_FS=$TESTPOOL/send_large_dnode
+TEST_RECV_FS=$TESTPOOL/recv_large_dnode
+TEST_SNAP=$TEST_SEND_FS@ldnsnap
+TEST_SNAPINCR=$TEST_SEND_FS@ldnsnap_incr
+TEST_STREAM=$TESTDIR/ldnsnap
+TEST_STREAMINCR=$TESTDIR/ldnsnap_incr
+TEST_FILE=foo
+TEST_FILEINCR=bar
+
+function cleanup
+{
+ if datasetexists $TEST_SEND_FS ; then
+ log_must zfs destroy -r $TEST_SEND_FS
+ fi
+
+ if datasetexists $TEST_RECV_FS ; then
+ log_must zfs destroy -r $TEST_RECV_FS
+ fi
+
+ rm -f $TEST_STREAM
+ rm -f $TEST_STREAMINCR
+}
+
+log_onexit cleanup
+
+log_assert "zfs send stream with large dnodes accepted by new pool"
+
+log_must zfs create -o dnodesize=1k $TEST_SEND_FS
+log_must touch /$TEST_SEND_FS/$TEST_FILE
+log_must zfs snap $TEST_SNAP
+log_must zfs send $TEST_SNAP > $TEST_STREAM
+log_must rm -f /$TEST_SEND_FS/$TEST_FILE
+log_must touch /$TEST_SEND_FS/$TEST_FILEINCR
+log_must zfs snap $TEST_SNAPINCR
+log_must zfs send -i $TEST_SNAP $TEST_SNAPINCR > $TEST_STREAMINCR
+
+log_must eval "zfs recv $TEST_RECV_FS < $TEST_STREAM"
+inode=$(ls -li /$TEST_RECV_FS/$TEST_FILE | awk '{print $1}')
+dnsize=$(zdb -dddd $TEST_RECV_FS $inode | awk '/ZFS plain file/ {print $6}')
+if [[ "$dnsize" != "1K" ]]; then
+ log_fail "dnode size is $dnsize (expected 1K)"
+fi
+
+log_must eval "zfs recv -F $TEST_RECV_FS < $TEST_STREAMINCR"
+log_must diff -r /$TEST_SEND_FS /$TEST_RECV_FS
+log_must zfs umount $TEST_SEND_FS
+log_must zfs umount $TEST_RECV_FS
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh
new file mode 100755
index 000000000000..38b4ac52e5d6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_006_pos.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+#
+# Copyright 2007 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
+
+#
+# DESCRIPTION:
+# Run xattrtest on a dataset with large dnodes and xattr=sa
+# to stress xattr usage of the extra bonus space and verify
+# contents
+#
+
+TEST_FS=$TESTPOOL/large_dnode
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TEST_FS && log_must zfs destroy $TEST_FS
+}
+
+log_onexit cleanup
+log_assert "xattrtest runs cleanly on dataset with large dnodes"
+
+log_must zfs create $TEST_FS
+
+set -A xattr_sizes "512" "1536" "3584" "7680" "15872"
+set -A prop_values "1k" "2k" "4k" "8k" "16k"
+
+for ((i=0; i < ${#prop_values[*]}; i++)) ; do
+ prop_val=${prop_values[$i]}
+ dir=/$TEST_FS/$prop_val
+ xattr_size=${xattr_sizes[$i]}
+ log_must zfs set dnsize=$prop_val $TEST_FS
+ log_must mkdir $dir
+ log_must xattrtest -R -y -s $xattr_size -f 1024 -p $dir
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_neg.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_neg.ksh
new file mode 100755
index 000000000000..59364574b165
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_007_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 (c) 2016 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+#
+# Copyright 2007 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
+
+#
+# DESCRIPTION:
+# Verify that the dnodesize dataset property won't accept a value
+# other than "legacy" if the large_dnode feature is not enabled.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $LGCYPOOL ; then
+ log_must zpool destroy -f $LGCYPOOL
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "values other than dnodesize=legacy rejected by legacy pool"
+
+set -A prop_vals "auto" "1k" "2k" "4k" "8k" "16k"
+
+LGCYPOOL=lgcypool
+LGCYFS=$LGCYPOOL/legacy
+log_must mkfile 64M $TESTDIR/$LGCYPOOL
+log_must zpool create -d $LGCYPOOL $TESTDIR/$LGCYPOOL
+log_must zfs create $LGCYFS
+
+for val in ${prop_vals[@]} ; do
+ log_mustnot zfs set dnodesize=$val $LGCYFS
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_pos.ksh
new file mode 100755
index 000000000000..71e175171322
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_008_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 (c) 2017 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Run many xattrtests on a dataset with large dnodes and xattr=sa to
+# stress concurrent allocation of large dnodes.
+#
+
+TEST_FS=$TESTPOOL/large_dnode
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TEST_FS && destroy_dataset $TEST_FS
+}
+
+function verify_dnode_packing
+{
+ zdb -dd $TEST_FS | grep -A 3 'Dnode slots' | awk '
+ /Total used:/ {total_used=$NF}
+ /Max used:/ {max_used=$NF}
+ /Percent empty:/ {print total_used, max_used, int($NF)}
+ ' | while read total_used max_used pct_empty
+ do
+ log_note "total_used $total_used max_used $max_used pct_empty $pct_empty"
+ if [ $pct_empty -gt 5 ]; then
+ log_fail "Holes in dnode array: pct empty $pct_empty > 5"
+ fi
+ done
+}
+
+log_onexit cleanup
+log_assert "xattrtest runs concurrently on dataset with large dnodes"
+
+log_must zfs create $TEST_FS
+log_must zfs set dnsize=auto $TEST_FS
+log_must zfs set xattr=sa $TEST_FS
+
+for ((i=0; i < 100; i++)); do
+ dir="/$TEST_FS/dir.$i"
+ log_must mkdir "$dir"
+ log_must eval "xattrtest -R -r -y -x 1 -f 1024 -k -p $dir >/dev/null 2>&1 &"
+done
+
+log_must wait
+sync_pool $TESTPOOL
+
+verify_dnode_packing
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_pos.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_pos.ksh
new file mode 100755
index 000000000000..fa746c52e5c5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/large_dnode_009_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) 2017 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Run many xattrtests on a dataset with large dnodes and xattr=sa to
+# stress concurrent allocation of large dnodes.
+#
+
+TEST_FS=$TESTPOOL/large_dnode
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TEST_FS && log_must zfs destroy $TEST_FS
+}
+
+log_onexit cleanup
+log_assert "xattrtest runs concurrently on dataset with large dnodes"
+
+log_must zfs create $TEST_FS
+log_must zfs set dnsize=auto $TEST_FS
+log_must zfs set xattr=sa $TEST_FS
+
+for ((i=0; i < 100; i++)); do
+ dir="/$TEST_FS/dir.$i"
+ log_must mkdir "$dir"
+
+ do_unlink=""
+ if [ $((RANDOM % 2)) -eq 0 ]; then
+ do_unlink="-k -f 1024"
+ else
+ do_unlink="-f $((RANDOM % 1024))"
+ fi
+ log_must eval "xattrtest -R -r -y -x 1 $do_unlink -p $dir >/dev/null 2>&1 &"
+done
+
+log_must wait
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+log_must ls -lR "/$TEST_FS/" >/dev/null 2>&1
+log_must zdb -d $TESTPOOL
+log_pass
diff --git a/tests/zfs-tests/tests/functional/features/large_dnode/setup.ksh b/tests/zfs-tests/tests/functional/features/large_dnode/setup.ksh
new file mode 100755
index 000000000000..a9425cca9857
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/features/large_dnode/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 (c) 2016 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/grow/Makefile.am b/tests/zfs-tests/tests/functional/grow/Makefile.am
new file mode 100644
index 000000000000..807610a067d8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/grow/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/grow
+dist_pkgdata_SCRIPTS = \
+ grow_pool_001_pos.ksh \
+ grow_replicas_001_pos.ksh
+
+dist_pkgdata_DATA = \
+ grow.cfg
diff --git a/tests/zfs-tests/tests/functional/grow/grow.cfg b/tests/zfs-tests/tests/functional/grow/grow.cfg
new file mode 100644
index 000000000000..10d15d7546c1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/grow/grow.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export DEVICE1="$TEST_BASE_DIR/device-1"
+export DEVICE2="$TEST_BASE_DIR/device-2"
+export DEVICE3="$TEST_BASE_DIR/device-3"
+export DEVICE4="$TEST_BASE_DIR/device-4"
+
+export BLOCK_SIZE=131072
+export TESTFILE1=file$$.1
+export SMALL_WRITE_COUNT=100
+export WRITE_COUNT=4096000
diff --git a/tests/zfs-tests/tests/functional/grow/grow_pool_001_pos.ksh b/tests/zfs-tests/tests/functional/grow/grow_pool_001_pos.ksh
new file mode 100755
index 000000000000..9c047223ab39
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/grow/grow_pool_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/grow/grow.cfg
+
+#
+# DESCRIPTION:
+# A ZFS file system is limited by the amount of disk space
+# available to the pool. Growing the pool by adding a disk
+# increases the amount of space.
+#
+# STRATEGY:
+# 1) Fill a ZFS filesystem until ENOSPC by creating a large file
+# 2) Grow the pool by adding a disk
+# 3) Verify that more data can now be written to the file system
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ rm -f $DEVICE1 $DEVICE2 $DEVICE3
+}
+
+log_assert "A zpool may be increased in capacity by adding a disk"
+
+log_onexit cleanup
+
+truncate -s $SPA_MINDEVSIZE $DEVICE1 $DEVICE2
+create_pool $TESTPOOL $pooltype $DEVICE1 $DEVICE2
+
+log_must zfs create $TESTPOOL/$TESTFS
+log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+
+file_write -o create -f $TESTDIR/$TESTFILE1 \
+ -b $BLOCK_SIZE -c $WRITE_COUNT -d 0
+
+typeset -i zret=$?
+readonly ENOSPC=28
+
+if [[ $zret -ne $ENOSPC ]]; then
+ log_fail "file_write completed w/o ENOSPC, aborting!!!"
+fi
+
+if [[ ! -s $TESTDIR/$TESTFILE1 ]]; then
+ log_fail "$TESTDIR/$TESTFILE1 was not created"
+fi
+
+truncate -s $SPA_MINDEVSIZE $DEVICE3
+log_must zpool add $TESTPOOL $DEVICE3
+
+log_must file_write -o append -f $TESTDIR/$TESTFILE1 \
+ -b $BLOCK_SIZE -c $SMALL_WRITE_COUNT -d 0
+
+log_must zfs inherit compression $TESTPOOL/$TESTFS
+
+log_must destroy_pool $TESTPOOL
+rm -f $DEVICE1 $DEVICE2 $DEVICE3
+
+log_pass "TESTPOOL successfully grown"
diff --git a/tests/zfs-tests/tests/functional/grow/grow_replicas_001_pos.ksh b/tests/zfs-tests/tests/functional/grow/grow_replicas_001_pos.ksh
new file mode 100755
index 000000000000..44b38291f0a9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/grow/grow_replicas_001_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) 2013, 2016 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/grow/grow.cfg
+
+# DESCRIPTION:
+# A ZFS filesystem is limited by the amount of disk space
+# available to the pool. Growing the pool by adding a disk
+# increases the amount of space.
+#
+# STRATEGY:
+# 1. Fill the filesystem on mirror/raidz pool by writing a file until ENOSPC.
+# 2. Grow the mirror/raidz pool by adding another mirror/raidz vdev.
+# 3. Verify that more data can now be written to the filesystem.
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ rm -f $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4
+}
+
+log_assert "mirror/raidz pool may be increased in capacity by adding a disk"
+
+log_onexit cleanup
+
+readonly ENOSPC=28
+
+for pooltype in "mirror" "raidz"; do
+ log_note "Creating pool type: $pooltype"
+
+ truncate -s $SPA_MINDEVSIZE $DEVICE1 $DEVICE2
+ create_pool $TESTPOOL $pooltype $DEVICE1 $DEVICE2
+
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+ log_must zfs set compression=off $TESTPOOL/$TESTFS
+
+ file_write -o create -f $TESTDIR/$TESTFILE1 \
+ -b $BLOCK_SIZE -c $WRITE_COUNT -d 0
+
+ [[ $? -ne $ENOSPC ]] && \
+ log_fail "file_write completed w/o ENOSPC"
+
+ [[ ! -s $TESTDIR/$TESTFILE1 ]] && \
+ log_fail "$TESTDIR/$TESTFILE1 was not created"
+
+ truncate -s $SPA_MINDEVSIZE $DEVICE3 $DEVICE4
+ log_must zpool add $TESTPOOL $pooltype $DEVICE3 $DEVICE4
+
+ log_must file_write -o append -f $TESTDIR/$TESTFILE1 \
+ -b $BLOCK_SIZE -c $SMALL_WRITE_COUNT -d 0
+
+ log_must destroy_pool $TESTPOOL
+ rm -f $DEVICE1 $DEVICE2 $DEVICE3 $DEVICE4
+done
+
+log_pass "mirror/raidz pool successfully grown"
diff --git a/tests/zfs-tests/tests/functional/history/Makefile.am b/tests/zfs-tests/tests/functional/history/Makefile.am
new file mode 100644
index 000000000000..b865a319a430
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/Makefile.am
@@ -0,0 +1,23 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/history
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ history_001_pos.ksh \
+ history_002_pos.ksh \
+ history_003_pos.ksh \
+ history_004_pos.ksh \
+ history_005_neg.ksh \
+ history_006_neg.ksh \
+ history_007_pos.ksh \
+ history_008_pos.ksh \
+ history_009_pos.ksh \
+ history_010_pos.ksh
+
+dist_pkgdata_DATA = \
+ history.cfg \
+ history_common.kshlib \
+ i386.migratedpool.DAT.Z \
+ i386.orig_history.txt \
+ sparc.migratedpool.DAT.Z \
+ sparc.orig_history.txt \
+ zfs-pool-v4.dat.Z
diff --git a/tests/zfs-tests/tests/functional/history/cleanup.ksh b/tests/zfs-tests/tests/functional/history/cleanup.ksh
new file mode 100755
index 000000000000..32ed921ffe76
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/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 2007 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
+
+rm -f $TEST_BASE_DIR/{old,tmp,new}_history.*
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/history/history.cfg b/tests/zfs-tests/tests/functional/history/history.cfg
new file mode 100644
index 000000000000..e9200a2b5098
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history.cfg
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+export ZFSROOT=
+
+export MPOOL=mpool.$$
+
+export OLD_HISTORY=$TEST_BASE_DIR/old_history.$$
+export TMP_HISTORY=$TEST_BASE_DIR/tmp_history.$$
+export NEW_HISTORY=$TEST_BASE_DIR/new_history.$$
+
+export MIGRATEDPOOLNAME=${MIGRATEDPOOLNAME:-history_pool}
+if is_freebsd; then
+ export TIMEZONE=${TIMEZONE:-America/Denver}
+else
+ export TIMEZONE=${TIMEZONE:-US/Mountain}
+fi
+
+export HIST_USER="huser"
+export HIST_GROUP="hgroup"
+
+export TESTVOL=testvol.$$
diff --git a/tests/zfs-tests/tests/functional/history/history_001_pos.ksh b/tests/zfs-tests/tests/functional/history/history_001_pos.ksh
new file mode 100755
index 000000000000..f33265185d5c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_001_pos.ksh
@@ -0,0 +1,122 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/history/history_common.kshlib
+
+#
+# DESCRIPTION:
+# Create a scenario to verify the following zpool subcommands are logged.
+# create, destroy, add, remove, offline, online, attach, detach, replace,
+# scrub, export, import, clear, upgrade.
+#
+# STRATEGY:
+# 1. Create three virtual disk files and create a mirror.
+# 2. Run and verify pool commands, with special casing for destroy/export.
+# 3. Import a pool and upgrade it, verifying 'upgrade' was logged.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $MPOOL
+ destroy_pool $upgrade_pool
+
+ [[ -d $import_dir ]] && rm -rf $import_dir
+ for file in $VDEV1 $VDEV2 $VDEV3 $VDEV4; do
+ [[ -f $file ]] && rm -f $file
+ done
+}
+
+log_assert "Verify zpool sub-commands which modify state are logged."
+log_onexit cleanup
+
+mntpnt=$(get_prop mountpoint $TESTPOOL)
+(( $? != 0)) && log_fail "get_prop($TESTPOOL mountpoint)"
+VDEV1=$mntpnt/vdev1; VDEV2=$mntpnt/vdev2;
+VDEV3=$mntpnt/vdev3; VDEV4=$mntpnt/vdev4;
+
+log_must mkfile $MINVDEVSIZE $VDEV1 $VDEV2 $VDEV3
+log_must mkfile $(($MINVDEVSIZE * 2)) $VDEV4
+
+run_and_verify -p "$MPOOL" "zpool create $MPOOL mirror $VDEV1 $VDEV2"
+run_and_verify -p "$MPOOL" "zpool add -f $MPOOL spare $VDEV3"
+run_and_verify -p "$MPOOL" "zpool remove $MPOOL $VDEV3"
+run_and_verify -p "$MPOOL" "zpool offline $MPOOL $VDEV1"
+run_and_verify -p "$MPOOL" "zpool online $MPOOL $VDEV1"
+run_and_verify -p "$MPOOL" "zpool attach $MPOOL $VDEV1 $VDEV4"
+run_and_verify -p "$MPOOL" "zpool detach $MPOOL $VDEV4"
+run_and_verify -p "$MPOOL" "zpool replace -f $MPOOL $VDEV1 $VDEV4"
+run_and_verify -p "$MPOOL" "zpool scrub $MPOOL"
+run_and_verify -p "$MPOOL" "zpool clear $MPOOL"
+
+# For export and destroy, mimic the behavior of run_and_verify using two
+# commands since the history will be unavailable until the pool is imported
+# again.
+commands=("zpool export $MPOOL" "zpool import -d $mntpnt $MPOOL"
+ "zpool destroy $MPOOL" "zpool import -D -f -d $mntpnt $MPOOL")
+for i in 0 2; do
+ cmd1="${commands[$i]}"
+ cmd2="${commands[(($i + 1 ))]}"
+
+ zpool history $MPOOL > $OLD_HISTORY 2>/dev/null
+ log_must $cmd1
+ log_must $cmd2
+ zpool history $MPOOL > $TMP_HISTORY 2>/dev/null
+ diff $OLD_HISTORY $TMP_HISTORY | grep "^> " | sed 's/^> //g' > \
+ $NEW_HISTORY
+ if is_linux; then
+ grep "$(echo "$cmd1" | sed 's/^.*\/\(zpool .*\).*$/\1/')" \
+ $NEW_HISTORY >/dev/null 2>&1 || \
+ log_fail "Didn't find \"$cmd1\" in pool history"
+ grep "$(echo "$cmd2" | sed 's/^.*\/\(zpool .*\).*$/\1/')" \
+ $NEW_HISTORY >/dev/null 2>&1 || \
+ log_fail "Didn't find \"$cmd2\" in pool history"
+ else
+ grep "$(echo "$cmd1" | sed 's/\/usr\/sbin\///g')" \
+ $NEW_HISTORY >/dev/null 2>&1 || \
+ log_fail "Didn't find \"$cmd1\" in pool history"
+ grep "$(echo "$cmd2" | sed 's/\/usr\/sbin\///g')" \
+ $NEW_HISTORY >/dev/null 2>&1 || \
+ log_fail "Didn't find \"$cmd2\" in pool history"
+ fi
+done
+
+run_and_verify -p "$MPOOL" "zpool split $MPOOL ${MPOOL}_split"
+
+import_dir=$TEST_BASE_DIR/import_dir.$$
+log_must mkdir $import_dir
+log_must cp $STF_SUITE/tests/functional/history/zfs-pool-v4.dat.Z $import_dir
+log_must uncompress $import_dir/zfs-pool-v4.dat.Z
+upgrade_pool=$(zpool import -d $import_dir | awk '/pool:/ { print $2 }')
+log_must zpool import -d $import_dir $upgrade_pool
+run_and_verify -p "$upgrade_pool" "zpool upgrade $upgrade_pool"
+
+log_pass "zpool sub-commands which modify state are logged passed. "
diff --git a/tests/zfs-tests/tests/functional/history/history_002_pos.ksh b/tests/zfs-tests/tests/functional/history/history_002_pos.ksh
new file mode 100755
index 000000000000..33fa33a4f516
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_002_pos.ksh
@@ -0,0 +1,198 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/history/history_common.kshlib
+
+#
+# DESCRIPTION:
+# Create a scenario to verify the following zfs subcommands are logged.
+# create, destroy, clone, rename, snapshot, rollback, set, inherit,
+# receive, promote, hold and release.
+#
+# STRATEGY:
+# 1. Verify that all the zfs commands listed (barring send) produce an
+# entry in the pool history.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+
+ [[ -f $tmpfile ]] && rm -f $tmpfile
+ [[ -f $tmpfile2 ]] && rm -f $tmpfile2
+ for dataset in $fs $newfs $fsclone $vol $newvol $volclone; do
+ datasetexists $dataset && zfs destroy -Rf $dataset
+ done
+ rm -rf /history.$$
+}
+
+log_assert "Verify zfs sub-commands which modify state are logged."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS1; newfs=$TESTPOOL/newfs; fsclone=$TESTPOOL/clone
+vol=$TESTPOOL/$TESTVOL ; newvol=$TESTPOOL/newvol; volclone=$TESTPOOL/volclone
+fssnap=$fs@fssnap; fssnap2=$fs@fssnap2
+volsnap=$vol@volsnap; volsnap2=$vol@volsnap2
+tmpfile=$TEST_BASE_DIR/tmpfile.$$ ; tmpfile2=$TEST_BASE_DIR/tmpfile2.$$
+
+if is_linux; then
+# property value property value
+#
+props=(
+ quota 64M recordsize 512
+ reservation 32M reservation none
+ mountpoint /history.$$ mountpoint legacy
+ mountpoint none compression lz4
+ compression on compression off
+ compression lzjb acltype noacl
+ acltype posixacl xattr sa
+ atime on atime off
+ devices on devices off
+ exec on exec off
+ setuid on setuid off
+ readonly on readonly off
+ zoned on zoned off
+ snapdir hidden snapdir visible
+ aclinherit discard aclinherit noallow
+ aclinherit secure aclinherit passthrough
+ canmount off canmount on
+ xattr on xattr off
+ compression gzip compression gzip-$((RANDOM%9 + 1))
+ compression zstd compression zstd-$((RANDOM%9 + 1))
+ compression zstd-fast copies $((RANDOM%3 + 1))
+ compression zstd-fast-$((RANDOM%9 + 1))
+)
+elif is_freebsd; then
+# property value property value
+#
+props=(
+ quota 64M recordsize 512
+ reservation 32M reservation none
+ mountpoint /history.$$ mountpoint legacy
+ mountpoint none sharenfs on
+ sharenfs off
+ compression on compression off
+ compression lzjb aclmode discard
+ aclmode groupmask aclmode passthrough
+ atime on atime off
+ devices on devices off
+ exec on exec off
+ setuid on setuid off
+ readonly on readonly off
+ jailed on jailed off
+ snapdir hidden snapdir visible
+ aclinherit discard aclinherit noallow
+ aclinherit secure aclinherit passthrough
+ canmount off canmount on
+ compression gzip compression gzip-$((RANDOM%9 + 1))
+ compression zstd compression zstd-$((RANDOM%9 + 1))
+ compression zstd-fast copies $((RANDOM%3 + 1))
+ compression zstd-fast-$((RANDOM%9 + 1))
+)
+else
+# property value property value
+#
+props=(
+ quota 64M recordsize 512
+ reservation 32M reservation none
+ mountpoint /history.$$ mountpoint legacy
+ mountpoint none sharenfs on
+ sharenfs off
+ compression on compression off
+ compression lzjb aclmode discard
+ aclmode groupmask aclmode passthrough
+ atime on atime off
+ devices on devices off
+ exec on exec off
+ setuid on setuid off
+ readonly on readonly off
+ zoned on zoned off
+ snapdir hidden snapdir visible
+ aclinherit discard aclinherit noallow
+ aclinherit secure aclinherit passthrough
+ canmount off canmount on
+ xattr on xattr off
+ compression gzip compression gzip-$((RANDOM%9 + 1))
+ copies $((RANDOM%3 + 1))
+)
+fi
+
+run_and_verify "zfs create $fs"
+# Set all the property for filesystem
+typeset -i i=0
+while ((i < ${#props[@]})) ; do
+ run_and_verify "zfs set ${props[$i]}=${props[((i+1))]} $fs"
+
+ # quota, reservation, canmount can not be inherited.
+ #
+ if [[ ${props[$i]} != "quota" && ${props[$i]} != "reservation" && \
+ ${props[$i]} != "canmount" ]];
+ then
+ run_and_verify "zfs inherit ${props[$i]} $fs"
+ fi
+
+ ((i += 2))
+done
+
+run_and_verify "zfs create -V 64M $vol"
+run_and_verify "zfs set volsize=32M $vol"
+run_and_verify "zfs snapshot $fssnap"
+run_and_verify "zfs hold tag $fssnap"
+run_and_verify "zfs release tag $fssnap"
+run_and_verify "zfs snapshot $volsnap"
+run_and_verify "zfs snapshot $fssnap2"
+run_and_verify "zfs snapshot $volsnap2"
+
+# Send isn't logged...
+log_must eval "zfs send -i $fssnap $fssnap2 > $tmpfile"
+log_must eval "zfs send -i $volsnap $volsnap2 > $tmpfile2"
+# Verify that's true
+zpool history $TESTPOOL | grep 'zfs send' >/dev/null 2>&1 && \
+ log_fail "'zfs send' found in history of \"$TESTPOOL\""
+
+run_and_verify "zfs destroy $fssnap2"
+run_and_verify "zfs destroy $volsnap2"
+run_and_verify "zfs receive $fs < $tmpfile"
+run_and_verify "zfs receive $vol < $tmpfile2"
+run_and_verify "zfs rollback -r $fssnap"
+run_and_verify "zfs rollback -r $volsnap"
+run_and_verify "zfs clone $fssnap $fsclone"
+run_and_verify "zfs clone $volsnap $volclone"
+run_and_verify "zfs rename $fs $newfs"
+run_and_verify "zfs rename $vol $newvol"
+run_and_verify "zfs promote $fsclone"
+run_and_verify "zfs promote $volclone"
+run_and_verify "zfs destroy $newfs"
+run_and_verify "zfs destroy $newvol"
+run_and_verify "zfs destroy -rf $fsclone"
+run_and_verify "zfs destroy -rf $volclone"
+
+log_pass "zfs sub-commands which modify state are logged passed."
diff --git a/tests/zfs-tests/tests/functional/history/history_003_pos.ksh b/tests/zfs-tests/tests/functional/history/history_003_pos.ksh
new file mode 100755
index 000000000000..46af53f8af90
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_003_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zpool history will truncate on small pools, leaving pool creation intact
+#
+# STRATEGY:
+# 1. Create a test pool on a file.
+# 2. Loop 300 times to set and remove compression to test dataset.
+# 3. Make sure 'zpool history' output is truncated
+# 4. Verify that the initial pool creation is preserved.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $spool && log_must zpool destroy $spool
+ [[ -f $VDEV0 ]] && log_must rm -f $VDEV0
+ [[ -f $TMPFILE ]] && log_must rm -f $TMPFILE
+}
+
+log_assert "zpool history limitation test."
+log_onexit cleanup
+
+mntpnt=$(get_prop mountpoint $TESTPOOL)
+(( $? != 0 )) && log_fail "get_prop mountpoint $TESTPOOL"
+
+VDEV0=$mntpnt/vdev0
+log_must mkfile $MINVDEVSIZE $VDEV0
+
+spool=smallpool.$$; sfs=smallfs.$$
+log_must zpool create $spool $VDEV0
+log_must zfs create $spool/$sfs
+
+typeset -i orig_count=$(zpool history $spool | wc -l)
+typeset orig_md5=$(zpool history $spool | head -2 | md5digest)
+typeset -i i=0
+while ((i < 300)); do
+ zfs set compression=off $spool/$sfs
+ zfs set compression=on $spool/$sfs
+ zfs set compression=off $spool/$sfs
+ zfs set compression=on $spool/$sfs
+ zfs set compression=off $spool/$sfs
+
+ ((i += 1))
+done
+
+TMPFILE=$TEST_BASE_DIR/spool.$$
+zpool history $spool >$TMPFILE
+typeset -i entry_count=$(wc -l $TMPFILE | awk '{print $1}')
+typeset final_md5=$(head -2 $TMPFILE | md5digest)
+
+grep 'zpool create' $TMPFILE >/dev/null 2>&1 ||
+ log_fail "'zpool create' was not found in pool history"
+
+grep 'zfs create' $TMPFILE >/dev/null 2>&1 &&
+ log_fail "'zfs create' was found in pool history"
+
+grep 'zfs set compress' $TMPFILE >/dev/null 2>&1 ||
+ log_fail "'zfs set compress' was found in pool history"
+
+# Verify that the creation of the pool was preserved in the history.
+if [[ $orig_md5 != $final_md5 ]]; then
+ log_fail "zpool creation history was not preserved."
+fi
+
+log_pass "zpool history limitation test passed."
diff --git a/tests/zfs-tests/tests/functional/history/history_004_pos.ksh b/tests/zfs-tests/tests/functional/history/history_004_pos.ksh
new file mode 100755
index 000000000000..1b8e7dfe02ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_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 2007 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
+
+#
+# DESCRIPTION:
+# 'zpool history' can cope with simultaneous commands.
+#
+# STRATEGY:
+# 1. Create test pool and test fs.
+# 2. Loop 100 times, set properties to test fs simultaneously.
+# 3. Wait for all the command execution complete.
+# 4. Make sure all the commands was logged by 'zpool history'.
+#
+
+verify_runnable "global"
+
+log_assert "'zpool history' can cope with simultaneous commands."
+
+typeset -i orig_count=$(zpool history $spool | wc -l | awk '{print $1}')
+
+typeset -i i=0
+while ((i < 10)); do
+ zfs set compression=off $TESTPOOL/$TESTFS &
+ zfs set atime=off $TESTPOOL/$TESTFS &
+ zfs create $TESTPOOL/$TESTFS1 &
+ zfs create $TESTPOOL/$TESTFS2 &
+ zfs create $TESTPOOL/$TESTFS3 &
+
+ wait
+
+ zfs snapshot $TESTPOOL/$TESTFS1@snap &
+ zfs snapshot $TESTPOOL/$TESTFS2@snap &
+ zfs snapshot $TESTPOOL/$TESTFS3@snap &
+
+ wait
+
+ zfs clone $TESTPOOL/$TESTFS1@snap $TESTPOOL/clone1 &
+ zfs clone $TESTPOOL/$TESTFS2@snap $TESTPOOL/clone2 &
+ zfs clone $TESTPOOL/$TESTFS3@snap $TESTPOOL/clone3 &
+
+ wait
+
+ zfs promote $TESTPOOL/clone1 &
+ zfs promote $TESTPOOL/clone2 &
+ zfs promote $TESTPOOL/clone3 &
+
+ wait
+
+ zfs destroy $TESTPOOL/$TESTFS1 &
+ zfs destroy $TESTPOOL/$TESTFS2 &
+ zfs destroy $TESTPOOL/$TESTFS3 &
+
+ wait
+
+ zfs destroy -Rf $TESTPOOL/clone1 &
+ zfs destroy -Rf $TESTPOOL/clone2 &
+ zfs destroy -Rf $TESTPOOL/clone3 &
+
+ wait
+ ((i += 1))
+done
+
+typeset -i entry_count=$(zpool history $spool | wc -l | awk '{print $1}')
+
+if ((entry_count - orig_count != 200)); then
+ log_fail "The entries count error: entry_count=$entry_count " \
+ "orig_count = $orig_count"
+fi
+
+log_pass "'zpool history' can cope with simultaneous commands."
diff --git a/tests/zfs-tests/tests/functional/history/history_005_neg.ksh b/tests/zfs-tests/tests/functional/history/history_005_neg.ksh
new file mode 100755
index 000000000000..297a701cc567
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_005_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 2007 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/history/history_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify the following zpool subcommands are not logged.
+# zpool get
+# zpool history
+# zpool list
+# zpool status
+# zpool iostat
+#
+# STRATEGY:
+# 1. Create a test pool
+# 2. Separately invoke zpool list|status|iostat
+# 3. Verify they were not recorded in pool history
+#
+
+verify_runnable "global"
+
+log_assert "Verify 'zpool get|history|list|status|iostat' will not be logged."
+
+# Save initial TESTPOOL history
+log_must eval "zpool history $TESTPOOL >$OLD_HISTORY"
+
+log_must zpool get all $TESTPOOL >/dev/null
+log_must zpool list $TESTPOOL >/dev/null
+log_must zpool status $TESTPOOL >/dev/null
+log_must zpool iostat $TESTPOOL >/dev/null
+
+log_must eval "zpool history $TESTPOOL >$NEW_HISTORY"
+log_must diff $OLD_HISTORY $NEW_HISTORY
+
+log_pass "Verify 'zpool get|history|list|status|iostat' will not be logged."
diff --git a/tests/zfs-tests/tests/functional/history/history_006_neg.ksh b/tests/zfs-tests/tests/functional/history/history_006_neg.ksh
new file mode 100755
index 000000000000..e97adc4e3ce0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_006_neg.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/history/history_common.kshlib
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify the following zfs subcommands are not logged.
+# list, get, holds, mount, unmount, share, unshare, send
+#
+# STRATEGY:
+# 1. Create a test pool.
+# 2. Separately invoke zfs list|get|holds|mount|unmount|share|unshare|send
+# 3. Verify they were not recorded in pool history.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if datasetexists $fs ; then
+ log_must zfs destroy -rf $fs
+ fi
+ log_must zfs create $fs
+}
+
+log_assert "Verify 'zfs list|get|holds|mount|unmount|share|unshare|send' " \
+ "will not be logged."
+log_onexit cleanup
+
+# Create initial test environment
+fs=$TESTPOOL/$TESTFS; snap1=$fs@snap1; snap2=$fs@snap2
+if ! is_linux; then
+ log_must zfs set sharenfs=on $fs
+fi
+log_must zfs snapshot $snap1
+log_must zfs hold tag $snap1
+log_must zfs snapshot $snap2
+
+# Save initial TESTPOOL history
+log_must eval "zpool history $TESTPOOL > $OLD_HISTORY"
+
+log_must zfs list $fs > /dev/null
+log_must zfs get mountpoint $fs > /dev/null
+log_must zfs unmount $fs
+log_must zfs mount $fs
+if ! is_linux; then
+ log_must zfs share $fs
+ log_must zfs unshare $fs
+fi
+log_must zfs send -i $snap1 $snap2 > /dev/null
+log_must zfs holds $snap1
+
+log_must eval "zpool history $TESTPOOL > $NEW_HISTORY"
+log_must diff $OLD_HISTORY $NEW_HISTORY
+
+log_must zfs release tag $snap1
+
+log_pass "Verify 'zfs list|get|mount|unmount|share|unshare|send' passed."
diff --git a/tests/zfs-tests/tests/functional/history/history_007_pos.ksh b/tests/zfs-tests/tests/functional/history/history_007_pos.ksh
new file mode 100755
index 000000000000..0504e1765c63
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_007_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/history/history_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify command history moves with pool while pool being migrated
+#
+# STRATEGY:
+# 1. Import uniform platform and cross platform pools
+# 2. Contract the command history of the imported pool
+# 3. Compare imported history log with the previous log.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $migratedpoolname && \
+ log_must zpool destroy -f $migratedpoolname
+
+ [[ -d $import_dir ]] && rm -rf $import_dir
+}
+
+log_assert "Verify command history moves with migrated pool."
+log_onexit cleanup
+
+tst_dir=$STF_SUITE/tests/functional/history
+import_dir=$TESTDIR/importdir.$$
+migrated_cmds_f=$import_dir/migrated_history.$$
+migratedpoolname=$MIGRATEDPOOLNAME
+typeset -i RET=1
+typeset -i linenum=0
+
+[[ ! -d $import_dir ]] && log_must mkdir $import_dir
+
+# We test the migrations on both uniform platform and cross platform
+for arch in "i386" "sparc"; do
+ log_must cp $tst_dir/${arch}.orig_history.txt $import_dir
+ orig_cmds_f=$import_dir/${arch}.orig_history.txt
+ # remove blank line
+ orig_cmds_f1=$import_dir/${arch}.orig_history_1.txt
+ cat $orig_cmds_f | grep -v "^$" > $orig_cmds_f1
+
+ log_must cp $tst_dir/${arch}.migratedpool.DAT.Z $import_dir
+ log_must uncompress -f $import_dir/${arch}.migratedpool.DAT.Z
+
+ # destroy the pool with same name, so that import operation succeeds.
+ poolexists $migratedpoolname && \
+ log_must zpool destroy -f $migratedpoolname
+
+ log_must zpool import -d $import_dir $migratedpoolname
+ TZ=$TIMEZONE zpool history $migratedpoolname | grep -v "^$" \
+ >$migrated_cmds_f
+ RET=$?
+ (( $RET != 0 )) && log_fail "zpool history $migratedpoolname fails."
+
+ # The migrated history file should differ with original history file on
+ # two commands -- 'export' and 'import', which are included in migrated
+ # history file but not in original history file. so, check the two
+ # commands firstly in migrated history file and then delete them, and
+ # then compare this filtered file with the original history file. They
+ # should be identical at this time.
+ for subcmd in "export" "import"; do
+ grep "$subcmd" $migrated_cmds_f >/dev/null 2>&1
+ RET=$?
+ (( $RET != 0 )) && log_fail "zpool $subcmd is not logged for" \
+ "the imported pool $migratedpoolname."
+ done
+
+ tmpfile=$import_dir/cmds_tmp.$$
+ linenum=`cat $migrated_cmds_f | wc -l`
+ (( linenum = linenum - 2 ))
+ head -n $linenum $migrated_cmds_f > $tmpfile
+ log_must diff $tmpfile $orig_cmds_f1
+
+ # cleanup for next loop testing
+ log_must zpool destroy -f $migratedpoolname
+ log_must rm -f `ls $import_dir`
+done
+
+log_pass "Verify command history moves with migrated pool."
diff --git a/tests/zfs-tests/tests/functional/history/history_008_pos.ksh b/tests/zfs-tests/tests/functional/history/history_008_pos.ksh
new file mode 100755
index 000000000000..996c7658c32c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_008_pos.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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/history/history_common.kshlib
+
+#
+# DESCRIPTION:
+# Pool history records all recursive operations.
+#
+# STRATEGY:
+# 1. Create a filesystem and several sub-filesystems in it.
+# 2. Make a recursive snapshot.
+# 3. Verify pool history records all the recursive operations.
+# 4. Do the same verification for hold, release, inherit, rollback and
+# destroy.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if datasetexists $root_testfs; then
+ log_must zfs destroy -rf $root_testfs
+ fi
+ log_must zfs create $root_testfs
+}
+
+log_assert "Pool history records all recursive operations."
+log_onexit cleanup
+
+root_testfs=$TESTPOOL/$TESTFS
+fs1=$root_testfs/fs1; fs2=$root_testfs/fs2; fs3=$root_testfs/fs3
+for fs in $fs1 $fs2 $fs3; do
+ log_must zfs create $fs
+done
+
+run_and_verify "zfs snapshot -r $root_testfs@snap" "-i"
+run_and_verify "zfs hold -r tag $root_testfs@snap" "-i"
+run_and_verify "zfs release -r tag $root_testfs@snap" "-i"
+log_must zfs snapshot $root_testfs@snap2
+log_must zfs snapshot $root_testfs@snap3
+run_and_verify "zfs rollback -r $root_testfs@snap" "-i"
+run_and_verify "zfs inherit -r mountpoint $root_testfs" "-i"
+run_and_verify "zfs destroy -r $root_testfs" "-i"
+
+log_pass "Pool history records all recursive operations."
diff --git a/tests/zfs-tests/tests/functional/history/history_009_pos.ksh b/tests/zfs-tests/tests/functional/history/history_009_pos.ksh
new file mode 100755
index 000000000000..cf40df84ec83
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_009_pos.ksh
@@ -0,0 +1,114 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/history/history_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify the delegation internal history are correctly.
+#
+# STRATEGY:
+# 1. Create test group and user.
+# 2. Define permission sets and verify the internal history correctly.
+# 3. Separately verify the internal history above is correct.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ del_user $HIST_USER
+ del_group $HIST_GROUP
+}
+
+log_assert "Verify delegated commands are logged in the pool history."
+log_onexit cleanup
+
+testfs=$TESTPOOL/$TESTFS
+# Create history test group and user and get user id and group id
+add_group $HIST_GROUP
+add_user $HIST_GROUP $HIST_USER
+
+# subcmd allow_options
+array=( "allow" "-s @basic snapshot"
+ "allow" "-s @set @basic"
+ "allow" "-c create"
+ "unallow" "-c create"
+ "allow" "-c @set"
+ "unallow" "-c @set"
+ "allow" "-l -u $HIST_USER snapshot"
+ "allow" "-u $HIST_USER snapshot"
+ "unallow" "-u $HIST_USER snapshot"
+ "allow" "-l -u $HIST_USER @set"
+ "allow" "-u $HIST_USER @set"
+ "unallow" "-u $HIST_USER @set"
+ "allow" "-d -u $HIST_USER snapshot"
+ "allow" "-u $HIST_USER snapshot"
+ "unallow" "-u $HIST_USER snapshot"
+ "allow" "-d -u $HIST_USER @set"
+ "allow" "-u $HIST_USER @set"
+ "unallow" "-u $HIST_USER @set"
+ "allow" "-l -g $HIST_GROUP snapshot"
+ "allow" "-g $HIST_GROUP snapshot"
+ "unallow" "-g $HIST_GROUP snapshot"
+ "allow" "-l -g $HIST_GROUP @set"
+ "allow" "-g $HIST_GROUP @set"
+ "unallow" "-g $HIST_GROUP @set"
+ "allow" "-d -g $HIST_GROUP snapshot"
+ "allow" "-g $HIST_GROUP snapshot"
+ "unallow" "-g $HIST_GROUP snapshot"
+ "allow" "-d -g $HIST_GROUP @set"
+ "allow" "-g $HIST_GROUP @set"
+ "unallow" "-g $HIST_GROUP @set"
+ "allow" "-l -e snapshot"
+ "allow" "-e snapshot"
+ "unallow" "-e snapshot"
+ "allow" "-l -e @set"
+ "allow" "-e @set"
+ "unallow" "-e @set"
+ "allow" "-d -e snapshot"
+ "allow" "-e snapshot"
+ "unallow" "-e snapshot"
+ "allow" "-d -e @set"
+ "allow" "-e @set"
+ "unallow" "-e @set"
+)
+
+typeset -i i=0
+while ((i < ${#array[@]})); do
+ subcmd=${array[$i]}
+ options=${array[((i + 1))]}
+
+ run_and_verify "zfs $subcmd $options $testfs" "-i"
+ ((i += 2))
+done
+
+log_pass "Verify delegated commands are logged in the pool history."
diff --git a/tests/zfs-tests/tests/functional/history/history_010_pos.ksh b/tests/zfs-tests/tests/functional/history/history_010_pos.ksh
new file mode 100755
index 000000000000..31fe8ec54d0e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_010_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/history/history_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify internal long history information are correct.
+#
+# STRATEGY:
+# 1. Create non-root test user and group.
+# 2. Do some zfs operations as a root and non-root user.
+# 3. Verify the long history information is correct.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ del_user $HIST_USER
+ del_group $HIST_GROUP
+ datasetexists $root_testfs && log_must zfs destroy -rf $root_testfs
+}
+
+log_assert "Verify internal long history information are correct."
+log_onexit cleanup
+
+root_testfs=$TESTPOOL/$TESTFS1
+
+# Create history test group and user and get user id and group id
+add_group $HIST_GROUP
+add_user $HIST_GROUP $HIST_USER
+
+#
+# Verify the test user can execute the zfs utilities. This may not
+# be possible due to default permissions on the user home directory.
+# This can be resolved granting group read access.
+#
+# chmod 0750 $HOME
+#
+user_run $HIST_USER zfs list
+if [ $? -ne 0 ]; then
+ log_unsupported "Test user $HIST_USER cannot execute zfs utilities"
+fi
+
+run_and_verify "zfs create $root_testfs" "-l"
+run_and_verify "zfs allow $HIST_GROUP snapshot,mount $root_testfs" "-l"
+run_and_verify "zfs allow $HIST_USER destroy,mount $root_testfs" "-l"
+run_and_verify "zfs allow $HIST_USER reservation $root_testfs" "-l"
+run_and_verify "zfs allow $HIST_USER allow $root_testfs" "-l"
+run_and_verify -u "$HIST_USER" "zfs snapshot $root_testfs@snap" "-l"
+run_and_verify -u "$HIST_USER" "zfs destroy $root_testfs@snap" "-l"
+run_and_verify -u "$HIST_USER" "zfs set reservation=64M $root_testfs" "-l"
+run_and_verify -u "$HIST_USER" \
+ "zfs allow $HIST_USER reservation $root_testfs" "-l"
+run_and_verify "zfs unallow $HIST_USER create $root_testfs" "-l"
+run_and_verify "zfs unallow $HIST_GROUP snapshot $root_testfs" "-l"
+run_and_verify "zfs destroy -r $root_testfs" "-l"
+
+log_pass "Verify internal long history information pass."
diff --git a/tests/zfs-tests/tests/functional/history/history_common.kshlib b/tests/zfs-tests/tests/functional/history/history_common.kshlib
new file mode 100644
index 000000000000..8ac34b2de909
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/history_common.kshlib
@@ -0,0 +1,422 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/history/history.cfg
+
+function run_and_verify
+{
+ typeset user pool
+ while getopts "p:u:" opt; do
+ case $opt in
+ p)
+ pool=$OPTARG
+ ;;
+ u)
+ user=$OPTARG
+ ;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+
+ pool=${pool:-$TESTPOOL}
+ user=${user:-"root"}
+ fullcmd="$1"
+ flags="$2"
+
+ if is_illumos; then
+ histcmd=$(echo $fullcmd | sed 's/\/usr\/sbin\///g')
+ else
+ histcmd=$(echo $fullcmd | sed 's/^.*\/\(zpool .*\).*$/\1/')
+ histcmd=$(echo $histcmd | sed 's/^.*\/\(zfs .*\).*$/\1/')
+ fi
+
+ cmd=$(echo $histcmd | awk '{print $1}')
+ subcmd=$(echo $histcmd | awk '{print $2}')
+
+ # If we aren't running zpool or zfs, something is wrong
+ [[ $cmd == "zpool" || $cmd == "zfs" ]] || \
+ log_fail "run_and_verify called with \"$cmd ($fullcmd)\""
+
+ # If this is a 'zfs receive' truncate the stdin redirect
+ [[ $subcmd == "receive" || $subcmd == "recv" ]] && \
+ histcmd=${histcmd%% <*}
+
+ # Run the command as the specified user, and find the new history.
+ zpool history $flags $pool > $OLD_HISTORY 2>/dev/null
+ if [[ $user == "root" ]]; then
+ log_must eval "$fullcmd"
+ else
+ log_must user_run $user "$fullcmd"
+ fi
+ zpool history $flags $pool > $TMP_HISTORY 2>/dev/null
+ diff $OLD_HISTORY $TMP_HISTORY | grep "^> " | sed 's/^> //g' \
+ > $NEW_HISTORY
+
+ # Verify what's common to every case, regardless of zpool history flags.
+ grep "$histcmd" $NEW_HISTORY >/dev/null 2>&1 || \
+ log_fail "Didn't find \"$histcmd\" in pool history"
+
+ # If 'zpool history' was called without any flags, then we're done.
+ [[ -z $flags ]] && return
+
+ # Verify the new history in cases that are more interesting because
+ # additional information is logged with -i or -l.
+
+ [[ $flags =~ "i" ]] && log_must verify_$subcmd "$histcmd" "$subcmd" \
+ "$flags"
+ [[ $flags =~ "l" ]] && log_must verify_long "$histcmd" "$user" "$flags"
+}
+
+function verify_long
+{
+ typeset cmd=$1
+ typeset user=$2
+ typeset flags=$3
+
+ [[ $flags =~ "l" ]] || return 1
+
+ typeset uid=$(id -u $user)
+ typeset hname=$(hostname)
+ if ! is_global_zone; then
+ hname=$hname:$(zonename)
+ fi
+
+ typeset suffix=""
+ if is_linux; then
+ suffix=":linux"
+ elif is_freebsd; then
+ suffix=":freebsd"
+ fi
+
+ grep -q "$cmd \[user $uid ($user) on $hname$suffix\]" $NEW_HISTORY
+ if [[ $? != 0 ]]; then
+ log_note "Couldn't find long information for \"$cmd\""
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_hold
+{
+ typeset cmd=$1
+ typeset subcmd=$2
+ typeset flags=$3
+
+ [[ $flags =~ "i" ]] || return 1
+
+ typeset tag=$(echo $cmd | awk '{print $4}')
+ typeset fullname=${cmd##* }
+ typeset dsname=${fullname%%@*}
+ typeset snapname=${fullname##*@}
+
+ # This works whether or not the hold was recursive
+ for ds in $(zfs list -r -Ho name -t snapshot $dsname | \
+ grep "@$snapname"); do
+ grep "$subcmd $ds ([0-9]*) tag=$tag" $NEW_HISTORY \
+ >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Didn't find hold on $ds with $tag"
+ return 1
+ fi
+ done
+
+ return 0
+}
+
+function verify_release
+{
+ # hold and release formats only differ by the subcommand name, so
+ # simply reuse the hold function.
+ verify_hold "$1" "release" "$3"
+}
+
+function verify_rollback
+{
+ typeset cmd=$1
+ typeset flags=$3
+
+ [[ $flags =~ "i" ]] || return 1
+
+ typeset fullname=${cmd##* }
+ typeset dsname=${fullname%%@*}
+ typeset parent_fs=${dsname##*/}
+ typeset rb_fs=${dsname}/%rollback
+ typeset snapname=${fullname##*@}
+
+ grep "clone swap $rb_fs ([0-9]*) parent=$parent_fs" $NEW_HISTORY \
+ >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Didn't find rollback clone swap in pool history"
+ return 1
+ fi
+
+ grep "destroy $rb_fs" $NEW_HISTORY >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Didn't find rollback destroy in pool history"
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_inherit
+{
+ typeset cmd=$1
+ typeset flags=$3
+
+ [[ $flags =~ "i" ]] || return 1
+
+ typeset dsname=${cmd##* }
+ typeset prop=${cmd% *}
+ prop=${prop##* }
+
+ # This works whether or not the inherit was recursive
+ for ds in $(zfs list -r -Ho name -t filesystem $dsname); do
+ grep "$subcmd $ds ([0-9]*) ${prop}=" $NEW_HISTORY >/dev/null \
+ 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Didn't find inherit history for $ds"
+ return 1
+ fi
+ done
+
+ return 0
+}
+
+function verify_allow
+{
+ typeset cmd=$1
+ typeset subcmd=$2
+ typeset flags=$3
+
+ [[ $flags =~ "i" ]] || return 1
+ [[ $subcmd == "allow" ]] && subcmd="update"
+ [[ $subcmd == "unallow" ]] && subcmd="remove"
+ typeset is_set lflag dflag dsname gname gid uname uid opt str code tmp
+
+ #
+ # Here, we determine three things:
+ # - Whether we're operating on a set or an individual permission (which
+ # dictates the case of the first character in the code)
+ # - The name of the dataset we're operating on.
+ # - Whether the operation applies locally or to descendent datasets (or
+ # both)
+ #
+ echo $cmd | awk '{i = NF - 1; print $i}' | grep '@' >/dev/null \
+ 2>&1 && is_set=1
+ dsname=${cmd##* }
+ [[ $cmd =~ "-l " ]] && lflag=1
+ [[ $cmd =~ "-d " ]] && dflag=1
+ if [[ -z $lflag && -z $dflag ]]; then
+ lflag=1
+ dflag=1
+ fi
+
+ #
+ # For each of the five cases below, the operation is essentially the
+ # same. First, use the command passed in to determine what the code at
+ # the end of the pool history will be. The specifics of the code are
+ # described in a block comment at the top of dsl_deleg.c. Once that's
+ # been assembled, check for its presence in the history, and return
+ # success or failure accordingly.
+ #
+ if [[ $cmd =~ "-s " ]]; then
+ str="s-\$@"
+ [[ -n $is_set ]] && str="S-\$@"
+ tmp=${cmd#*@}
+ code="$str${tmp% *}"
+ grep "permission $subcmd $dsname ([0-9]*) $code" \
+ $NEW_HISTORY >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Couldn't find $code in $NEW_HISTORY"
+ return 1
+ fi
+ elif [[ $cmd =~ "-c " ]]; then
+ str="c-\$"
+ [[ -n $is_set ]] && str="C-\$"
+ tmp=${cmd#*-c}
+ code="$str${tmp% *}"
+ grep "permission $subcmd $dsname ([0-9]*) $code" \
+ $NEW_HISTORY >/dev/null 2>&1
+ if [ $? != 0 ]]; then
+ log_note "Couldn't find $code in $NEW_HISTORY"
+ return 1
+ fi
+ elif [[ $cmd =~ "-u " ]]; then
+ str="u"
+ [[ -n $is_set ]] && str="U"
+ tmp=${cmd##*-u }
+ opt=$(echo $tmp | awk '{print $2}')
+ uid=$(id -u ${tmp%% *})
+ if [[ -n $lflag ]]; then
+ code="${str}l\$$uid $opt"
+ grep "permission $subcmd $dsname ([0-9]*) $code" \
+ $NEW_HISTORY >/dev/null 2>&1
+ if [ $? != 0 ]]; then
+ log_note "Couldn't find $code in $NEW_HISTORY"
+ return 1
+ fi
+ fi
+ if [[ -n $dflag ]]; then
+ code="${str}d\$$uid $opt"
+ grep "permission $subcmd $dsname ([0-9]*) $code" \
+ $NEW_HISTORY >/dev/null 2>&1
+ if [ $? != 0 ]]; then
+ log_note "Couldn't find $code in $NEW_HISTORY"
+ return 1
+ fi
+ fi
+ elif [[ $cmd =~ "-g " ]]; then
+ str="g"
+ [[ -n $is_set ]] && str="G"
+ tmp=${cmd##*-g }
+ opt=$(echo $tmp | awk '{print $2}')
+ gid=$(awk -F: "/^${tmp%% *}:/ {print \$3}" /etc/group)
+ if [[ -n $lflag ]]; then
+ code="${str}l\$$gid $opt"
+ grep "permission $subcmd $dsname ([0-9]*) $code" \
+ $NEW_HISTORY >/dev/null 2>&1
+ if [ $? != 0 ]]; then
+ log_note "Couldn't find $code in $NEW_HISTORY"
+ return 1
+ fi
+ fi
+ if [[ -n $dflag ]]; then
+ code="${str}d\$$gid $opt"
+ grep "permission $subcmd $dsname ([0-9]*) $code" \
+ $NEW_HISTORY >/dev/null 2>&1
+ if [ $? != 0 ]]; then
+ log_note "Couldn't find $code in $NEW_HISTORY"
+ return 1
+ fi
+ fi
+ elif [[ $cmd =~ "-e " ]]; then
+ str="e"
+ [[ -n $is_set ]] && str="E"
+ opt=${cmd##*-e }
+ opt=${opt%% *}
+ if [[ -n $lflag ]]; then
+ code="${str}l\$ $opt"
+ grep "permission $subcmd $dsname ([0-9]*) $code" \
+ $NEW_HISTORY >/dev/null 2>&1
+ if [ $? != 0 ]]; then
+ log_note "Couldn't find $code in $NEW_HISTORY"
+ return 1
+ fi
+ fi
+ if [[ -n $dflag ]]; then
+ code="${str}d\$ $opt"
+ grep "permission $subcmd $dsname ([0-9]*) $code" \
+ $NEW_HISTORY >/dev/null 2>&1
+ if [ $? != 0 ]]; then
+ log_note "Couldn't find $code in $NEW_HISTORY"
+ return 1
+ fi
+ fi
+ else
+ log_note "Can't parse command \"$cmd\""
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_unallow
+{
+ #
+ # The unallow and allow history have the same format, except the former
+ # logs "permission removed" and the latter "permission updated" so
+ # simply reuse the allow function.
+ #
+ verify_allow "$1" "unallow" "$3"
+}
+
+function verify_destroy
+{
+ typeset cmd=$1
+ typeset flags=$3
+
+ # This function doesn't currently verify the zpool command.
+ [[ ${cmd%% *} == "zfs" ]] || return 1
+ [[ $flags =~ "i" ]] || return 1
+
+ typeset dsname=${cmd##* }
+ [[ $dsname =~ "@" ]] && typeset is_snap=1
+
+ if [[ -n $is_snap ]]; then
+ grep "ioctl destroy_snaps" $NEW_HISTORY >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Didn't find ioctl while destroying $dsname"
+ return 1
+ fi
+ fi
+
+ # This should be present for datasets and snapshots alike
+ grep "destroy $dsname" $NEW_HISTORY >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Didn't find \"destroy\" for $dsname"
+ return 1
+ fi
+
+ return 0
+}
+
+function verify_snapshot
+{
+ typeset cmd=$1
+ typeset flags=$3
+
+ [[ $flags =~ "i" ]] || return 1
+
+ typeset fullname=${cmd##* }
+ typeset dsname=${fullname%%@*}
+ typeset snapname=${fullname##*@}
+
+ grep "\[txg:[0-9]*\] $subcmd $fullname ([0-9]*)" $NEW_HISTORY \
+ >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Didn't find snapshot command for $fullname"
+ return 1
+ fi
+
+ # This works whether or not the snapshot was recursive
+ for ds in $(zfs list -r -Ho name -t snapshot $dsname | \
+ grep "@$snapname"); do
+ grep "^[ ]* $ds$" $NEW_HISTORY >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_note "Didn't find \"ioctl snapshot\" for $ds"
+ return 1
+ fi
+ done
+
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/history/i386.migratedpool.DAT.Z b/tests/zfs-tests/tests/functional/history/i386.migratedpool.DAT.Z
new file mode 100644
index 000000000000..21cd7fcf583a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/i386.migratedpool.DAT.Z
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/history/i386.orig_history.txt b/tests/zfs-tests/tests/functional/history/i386.orig_history.txt
new file mode 100644
index 000000000000..148b825c3ffb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/i386.orig_history.txt
@@ -0,0 +1,12 @@
+History for 'history_pool':
+2006-10-20.13:18:37 zpool create history_pool /var/tmp/i386.migratedpool.DAT
+2006-10-20.13:18:37 zfs create history_pool/fs
+2006-10-20.13:18:37 zfs set compression=on history_pool/fs
+2006-10-20.13:18:37 zfs set checksum=on history_pool
+2006-10-20.13:18:37 zfs snapshot history_pool/fs@snap
+2006-10-20.13:18:37 zfs clone history_pool/fs@snap history_pool/clone
+2006-10-20.13:18:37 zfs promote history_pool/clone
+2006-10-20.13:18:37 zfs promote history_pool/fs
+2006-10-20.13:18:37 zfs destroy -r -R history_pool/fs
+2006-10-20.13:18:37 zpool export history_pool
+2007-04-05.00:05:38 zpool upgrade history_pool
diff --git a/tests/zfs-tests/tests/functional/history/setup.ksh b/tests/zfs-tests/tests/functional/history/setup.ksh
new file mode 100755
index 000000000000..fc5cec3063a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/history/sparc.migratedpool.DAT.Z b/tests/zfs-tests/tests/functional/history/sparc.migratedpool.DAT.Z
new file mode 100644
index 000000000000..47a61ffd51a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/sparc.migratedpool.DAT.Z
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/history/sparc.orig_history.txt b/tests/zfs-tests/tests/functional/history/sparc.orig_history.txt
new file mode 100644
index 000000000000..2d0e3427cd00
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/sparc.orig_history.txt
@@ -0,0 +1,12 @@
+History for 'history_pool':
+2006-10-27.03:13:47 zpool create history_pool /var/tmp/sparc.migratedpool.DAT
+2006-10-27.03:13:48 zfs create history_pool/fs
+2006-10-27.03:13:48 zfs set compression=on history_pool/fs
+2006-10-27.03:13:48 zfs set checksum=on history_pool
+2006-10-27.03:13:48 zfs snapshot history_pool/fs@snap
+2006-10-27.03:13:48 zfs clone history_pool/fs@snap history_pool/clone
+2006-10-27.03:13:49 zfs promote history_pool/clone
+2006-10-27.03:13:49 zfs promote history_pool/fs
+2006-10-27.03:13:49 zfs destroy -r -R history_pool/fs
+2006-10-27.03:13:49 zpool export history_pool
+2007-04-05.00:41:55 zpool upgrade history_pool
diff --git a/tests/zfs-tests/tests/functional/history/zfs-pool-v4.dat.Z b/tests/zfs-tests/tests/functional/history/zfs-pool-v4.dat.Z
new file mode 100644
index 000000000000..bc32472f0084
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/history/zfs-pool-v4.dat.Z
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/hkdf/.gitignore b/tests/zfs-tests/tests/functional/hkdf/.gitignore
new file mode 100644
index 000000000000..828e33d84b4e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/hkdf/.gitignore
@@ -0,0 +1 @@
+hkdf_test
diff --git a/tests/zfs-tests/tests/functional/hkdf/Makefile.am b/tests/zfs-tests/tests/functional/hkdf/Makefile.am
new file mode 100644
index 000000000000..8ac9053223a4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/hkdf/Makefile.am
@@ -0,0 +1,17 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/hkdf
+
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ run_hkdf_test.ksh
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/hkdf
+
+pkgexec_PROGRAMS = \
+ hkdf_test
+
+hkdf_test_SOURCES = hkdf_test.c
+hkdf_test_LDADD = \
+ $(abs_top_builddir)/lib/libzpool/libzpool.la
diff --git a/tests/zfs-tests/tests/functional/hkdf/cleanup.ksh b/tests/zfs-tests/tests/functional/hkdf/cleanup.ksh
new file mode 100755
index 000000000000..2bdca1950d37
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/hkdf/cleanup.ksh
@@ -0,0 +1,22 @@
+#!/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 Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/hkdf/hkdf_test.c b/tests/zfs-tests/tests/functional/hkdf/hkdf_test.c
new file mode 100644
index 000000000000..dd23da332c9a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/hkdf/hkdf_test.c
@@ -0,0 +1,235 @@
+/*
+ * 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.
+ */
+
+#include <stdio.h>
+#include <strings.h>
+#include <sys/crypto/icp.h>
+#include <sys/sha2.h>
+#include <sys/hkdf.h>
+
+#define NELEMS(x) (sizeof (x) / sizeof ((x)[0]))
+
+/*
+ * Byte arrays are given as char pointers so that they
+ * can be specified as strings.
+ */
+typedef struct hkdf_tv {
+ /* test vector input values */
+ char *ikm;
+ uint_t ikm_len;
+ char *salt;
+ uint_t salt_len;
+ char *info;
+ uint_t info_len;
+ uint_t okm_len;
+
+ /* expected output */
+ char *okm;
+} hkdf_tv_t;
+
+/*
+ * XXX Neither NIST nor IETF has published official test
+ * vectors for testing HKDF with SHA512. The following
+ * vectors should be updated if these are ever published.
+ * The current vectors were taken from:
+ * https://www.kullo.net/blog/hkdf-sha-512-test-vectors/
+ */
+static hkdf_tv_t test_vectors[] = {
+ {
+ .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+ "\x0b\x0b\x0b\x0b\x0b\x0b",
+ .ikm_len = 22,
+ .salt = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c",
+ .salt_len = 13,
+ .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9",
+ .info_len = 10,
+ .okm_len = 42,
+ .okm = "\x83\x23\x90\x08\x6c\xda\x71\xfb"
+ "\x47\x62\x5b\xb5\xce\xb1\x68\xe4"
+ "\xc8\xe2\x6a\x1a\x16\xed\x34\xd9"
+ "\xfc\x7f\xe9\x2c\x14\x81\x57\x93"
+ "\x38\xda\x36\x2c\xb8\xd9\xf9\x25"
+ "\xd7\xcb",
+ },
+ {
+ .ikm = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
+ "\x10\x11\x12\x13\x14\x15\x16\x17"
+ "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f"
+ "\x20\x21\x22\x23\x24\x25\x26\x27"
+ "\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f"
+ "\x30\x31\x32\x33\x34\x35\x36\x37"
+ "\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f"
+ "\x40\x41\x42\x43\x44\x45\x46\x47"
+ "\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f",
+ .ikm_len = 80,
+ .salt = "\x60\x61\x62\x63\x64\x65\x66\x67"
+ "\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f"
+ "\x70\x71\x72\x73\x74\x75\x76\x77"
+ "\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f"
+ "\x80\x81\x82\x83\x84\x85\x86\x87"
+ "\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97"
+ "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
+ "\xa8\xa9\xaa\xab\xac\xad\xae\xaf",
+ .salt_len = 80,
+ .info = "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7"
+ "\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf"
+ "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7"
+ "\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf"
+ "\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+ "\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf"
+ "\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7"
+ "\xe8\xe9\xea\xeb\xec\xed\xee\xef"
+ "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff",
+ .info_len = 80,
+ .okm_len = 42,
+ .okm = "\xce\x6c\x97\x19\x28\x05\xb3\x46"
+ "\xe6\x16\x1e\x82\x1e\xd1\x65\x67"
+ "\x3b\x84\xf4\x00\xa2\xb5\x14\xb2"
+ "\xfe\x23\xd8\x4c\xd1\x89\xdd\xf1"
+ "\xb6\x95\xb4\x8c\xbd\x1c\x83\x88"
+ "\x44\x11\x37\xb3\xce\x28\xf1\x6a"
+ "\xa6\x4b\xa3\x3b\xa4\x66\xb2\x4d"
+ "\xf6\xcf\xcb\x02\x1e\xcf\xf2\x35"
+ "\xf6\xa2\x05\x6c\xe3\xaf\x1d\xe4"
+ "\x4d\x57\x20\x97\xa8\x50\x5d\x9e"
+ "\x7a\x93",
+ },
+ {
+ .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+ "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+ "\x0b\x0b\x0b\x0b\x0b\x0b",
+ .ikm_len = 22,
+ .salt = NULL,
+ .salt_len = 0,
+ .info = NULL,
+ .info_len = 0,
+ .okm_len = 42,
+ .okm = "\xf5\xfa\x02\xb1\x82\x98\xa7\x2a"
+ "\x8c\x23\x89\x8a\x87\x03\x47\x2c"
+ "\x6e\xb1\x79\xdc\x20\x4c\x03\x42"
+ "\x5c\x97\x0e\x3b\x16\x4b\xf9\x0f"
+ "\xff\x22\xd0\x48\x36\xd0\xe2\x34"
+ "\x3b\xac",
+ },
+ {
+ .ikm = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
+ "\x0b\x0b\x0b",
+ .ikm_len = 11,
+ .salt = "\x00\x01\x02\x03\x04\x05\x06\x07"
+ "\x08\x09\x0a\x0b\x0c",
+ .salt_len = 13,
+ .info = "\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7"
+ "\xf8\xf9",
+ .info_len = 10,
+ .okm_len = 42,
+ .okm = "\x74\x13\xe8\x99\x7e\x02\x06\x10"
+ "\xfb\xf6\x82\x3f\x2c\xe1\x4b\xff"
+ "\x01\x87\x5d\xb1\xca\x55\xf6\x8c"
+ "\xfc\xf3\x95\x4d\xc8\xaf\xf5\x35"
+ "\x59\xbd\x5e\x30\x28\xb0\x80\xf7"
+ "\xc0\x68",
+ },
+ {
+ .ikm = "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+ "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
+ "\x0c\x0c\x0c\x0c\x0c\x0c",
+ .ikm_len = 22,
+ .salt = NULL,
+ .salt_len = 0,
+ .info = NULL,
+ .info_len = 0,
+ .okm_len = 42,
+ .okm = "\x14\x07\xd4\x60\x13\xd9\x8b\xc6"
+ "\xde\xce\xfc\xfe\xe5\x5f\x0f\x90"
+ "\xb0\xc7\xf6\x3d\x68\xeb\x1a\x80"
+ "\xea\xf0\x7e\x95\x3c\xfc\x0a\x3a"
+ "\x52\x40\xa1\x55\xd6\xe4\xda\xa9"
+ "\x65\xbb",
+ },
+};
+
+static void
+hexdump(char *str, uint8_t *src, uint_t len)
+{
+ int i;
+
+ printf("\t%s\t", str);
+ for (i = 0; i < len; i++) {
+ printf("%02x", src[i] & 0xff);
+ }
+ printf("\n");
+}
+
+static int
+run_test(int i, hkdf_tv_t *tv)
+{
+ int ret;
+ uint8_t okey[SHA512_DIGEST_LENGTH];
+
+ printf("TEST %d:\t", i);
+
+ ret = hkdf_sha512((uint8_t *)tv->ikm, tv->ikm_len, (uint8_t *)tv->salt,
+ tv->salt_len, (uint8_t *)tv->info, tv->info_len, okey, tv->okm_len);
+ if (ret != 0) {
+ printf("HKDF failed with error code %d\n", ret);
+ return (ret);
+ }
+
+ if (bcmp(okey, tv->okm, tv->okm_len) != 0) {
+ printf("Output Mismatch\n");
+ hexdump("Expected:", (uint8_t *)tv->okm, tv->okm_len);
+ hexdump("Actual: ", okey, tv->okm_len);
+ return (1);
+ }
+
+ printf("Passed\n");
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ int ret, i;
+
+ icp_init();
+
+ for (i = 0; i < NELEMS(test_vectors); i++) {
+ ret = run_test(i, &test_vectors[i]);
+ if (ret != 0)
+ break;
+ }
+
+ icp_fini();
+
+ if (ret == 0) {
+ printf("All tests passed successfully.\n");
+ return (0);
+ } else {
+ printf("Test failed.\n");
+ return (1);
+ }
+}
diff --git a/tests/zfs-tests/tests/functional/hkdf/run_hkdf_test.ksh b/tests/zfs-tests/tests/functional/hkdf/run_hkdf_test.ksh
new file mode 100755
index 000000000000..5fde0b837d0f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/hkdf/run_hkdf_test.ksh
@@ -0,0 +1,30 @@
+#!/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 Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Call the hkdf_test tool to test ZFS's HKDF implementation against
+# a few test vectors.
+#
+
+log_assert "Run the tests for the HKDF algorithm."
+
+log_must $STF_SUITE/tests/functional/hkdf/hkdf_test
+
+log_pass "HKDF tests pass."
diff --git a/tests/zfs-tests/tests/functional/hkdf/setup.ksh b/tests/zfs-tests/tests/functional/hkdf/setup.ksh
new file mode 100755
index 000000000000..2bdca1950d37
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/hkdf/setup.ksh
@@ -0,0 +1,22 @@
+#!/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 Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/inheritance/Makefile.am b/tests/zfs-tests/tests/functional/inheritance/Makefile.am
new file mode 100644
index 000000000000..3c624621f28a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/Makefile.am
@@ -0,0 +1,57 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/inheritance
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ inherit_001_pos.ksh
+
+dist_pkgdata_DATA = \
+ README.config \
+ README.state \
+ inherit.kshlib \
+ config001.cfg \
+ config002.cfg \
+ config003.cfg \
+ config004.cfg \
+ config005.cfg \
+ config006.cfg \
+ config007.cfg \
+ config008.cfg \
+ config009.cfg \
+ config010.cfg \
+ config011.cfg \
+ config012.cfg \
+ config013.cfg \
+ config014.cfg \
+ config015.cfg \
+ config016.cfg \
+ config017.cfg \
+ config018.cfg \
+ config019.cfg \
+ config020.cfg \
+ config021.cfg \
+ config022.cfg \
+ config023.cfg \
+ config024.cfg \
+ state001.cfg \
+ state002.cfg \
+ state003.cfg \
+ state004.cfg \
+ state005.cfg \
+ state006.cfg \
+ state007.cfg \
+ state008.cfg \
+ state009.cfg \
+ state010.cfg \
+ state011.cfg \
+ state012.cfg \
+ state013.cfg \
+ state014.cfg \
+ state015.cfg \
+ state016.cfg \
+ state017.cfg \
+ state018.cfg \
+ state019.cfg \
+ state020.cfg \
+ state021.cfg \
+ state022.cfg \
+ state023.cfg \
+ state024.cfg
diff --git a/tests/zfs-tests/tests/functional/inheritance/README.config b/tests/zfs-tests/tests/functional/inheritance/README.config
new file mode 100644
index 000000000000..607f10a554ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/README.config
@@ -0,0 +1,67 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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.
+#
+# The configX.cfg files describe both the dataset hierarchy to
+# be created but also the initial source values for the datasets
+# properties, i.e. whether they should be left with their default values
+# or set locally.
+#
+# Format for this file is as follows:
+# <dataset name> <dataset type> <initial property setting>
+#
+# <dataset name> - must be the full dataset name
+#
+# <dataset type> - recognised types are POOL, CTR and FS
+#
+#
+# <initial property setting> - can have one of the following
+# values:
+#
+# default property values are left unchanged
+#
+# local property values are set locally
+#
+# - property values are left unchanged (has the
+# same effect as 'default' but is used to indicate
+# that the property 'source' field may be 'inherited
+# from..' depending on the actions further up the
+# dataset hierarchy.
+#
+#
+# The configuration below creates a three tier dataset layout, consisting
+# of a pool, container and filesystem.
+#
+# The top tier pool's properties being set locally, and the two
+# lower tier properties each inheriting their values from the next tier
+# up.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR -
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/README.state b/tests/zfs-tests/tests/functional/inheritance/README.state
new file mode 100644
index 000000000000..c1d3cc05d603
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/README.state
@@ -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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+# For every configX.cfg file there must be a corresponding stateX.cfg
+# file. The state file both drives the operations to be performed on the
+# dataset hierarchy which has been specified by the corresponding
+# configX.cfg file, and also specifies the expected state of the
+# properties after the operation has been completed.
+#
+# The format of the file is:
+# <target dataset>:<command>
+# <property source before command> <property src after command>
+# <property source before command> <property src after command>
+# .... ....
+# .... ....
+#
+# <target dataset> - dataset upon which the <command> is to be executed. Can
+# be any of the datasets specified in the corresponding
+# configX.cfg file. If no command is to be executed
+# then must be set to '-'
+#
+#
+# <command> - command to be executed upon the specified dataset.
+# Currently the only supported commands are 'inherit'
+# or 'inherit -r'. If no command is to be executed,
+# then must be set to '-'.
+#
+# <property src before command>
+# - the 'source' (as reported in 'zfs get') for the
+# the properties before <command> is executed. This
+# can be 'default', 'local' or the name of a dataset
+# from which the property is inherited. (The code
+# automatically adds in the 'inherited from..' part
+# of the string when doing the check.
+#
+# This field is for informational purposes only, to
+# aid the user in seeing how the changes trickle down
+# the data hierarchy.
+#
+# <property src after command>
+# - the expected value of the 'source' field after the
+# <command> has been executed on the <target dataset>.
+# As above can be 'default', 'local', or the dataset
+# from which the property is inherited.
+#
+# Two important things to note:
+# 1) there must be a <property src..> line corresponding to each dataset
+# line specified in the configX.cfg file.
+#
+#
+# 2) There can be as many <command>/<property src> blocks as desired, but
+# there must be at least one, and the effect of each block is cumulative
+# (i.e. the properties are not reset back to their default values between
+# each block. If that is desired then each block must be placed in its
+# own state file with its own corresponding configX.cfg file).
+#
+#
+# Below are two sample <command>/<property src> blocks.
+#
+# The first simply verifies that the properties on the top level dataset
+# were set locally, and that the middle and bottom datasets properties
+# were inherited from the top level pool (called TESTPOOL). Note the '-:-'
+# which means that no command is to be executed, but simply that the
+# properties settings are to be verified.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+-:-
+#
+local local
+TESTPOOL TESTPOOL
+TESTPOOL TESTPOOL
+#
+#
+# The block below describes the expected state of the properties after
+# an 'inherit -r' command has been run on the top level pool (called
+# TESTPOOL).
+#
+TESTPOOL:inherit -r
+#
+local default
+TESTPOOL default
+TESTPOOL default
diff --git a/tests/zfs-tests/tests/functional/inheritance/cleanup.ksh b/tests/zfs-tests/tests/functional/inheritance/cleanup.ksh
new file mode 100755
index 000000000000..daac5c18a345
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. ${STF_SUITE}/include/libtest.shlib
+
+rm -rf $TESTDIR.*
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/inheritance/config001.cfg b/tests/zfs-tests/tests/functional/inheritance/config001.cfg
new file mode 100644
index 000000000000..23616cbf3b7f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config001.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR -
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config002.cfg b/tests/zfs-tests/tests/functional/inheritance/config002.cfg
new file mode 100644
index 000000000000..31294110f6ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config002.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config003.cfg b/tests/zfs-tests/tests/functional/inheritance/config003.cfg
new file mode 100644
index 000000000000..57a73b95d433
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config003.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR default
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config004.cfg b/tests/zfs-tests/tests/functional/inheritance/config004.cfg
new file mode 100644
index 000000000000..1052526379f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config004.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config005.cfg b/tests/zfs-tests/tests/functional/inheritance/config005.cfg
new file mode 100644
index 000000000000..d15beb2c4ca8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config005.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config006.cfg b/tests/zfs-tests/tests/functional/inheritance/config006.cfg
new file mode 100644
index 000000000000..a059d17978f7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config006.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR -
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config007.cfg b/tests/zfs-tests/tests/functional/inheritance/config007.cfg
new file mode 100644
index 000000000000..b416c9f17d20
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config007.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config008.cfg b/tests/zfs-tests/tests/functional/inheritance/config008.cfg
new file mode 100644
index 000000000000..4f7e7b0ef7f8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config008.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR default
+TESTPOOL/TESTCTR/TESTFS1 FS default
diff --git a/tests/zfs-tests/tests/functional/inheritance/config009.cfg b/tests/zfs-tests/tests/functional/inheritance/config009.cfg
new file mode 100644
index 000000000000..4f7e7b0ef7f8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config009.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR default
+TESTPOOL/TESTCTR/TESTFS1 FS default
diff --git a/tests/zfs-tests/tests/functional/inheritance/config010.cfg b/tests/zfs-tests/tests/functional/inheritance/config010.cfg
new file mode 100644
index 000000000000..4f7e7b0ef7f8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config010.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR default
+TESTPOOL/TESTCTR/TESTFS1 FS default
diff --git a/tests/zfs-tests/tests/functional/inheritance/config011.cfg b/tests/zfs-tests/tests/functional/inheritance/config011.cfg
new file mode 100644
index 000000000000..57a73b95d433
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config011.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR default
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config012.cfg b/tests/zfs-tests/tests/functional/inheritance/config012.cfg
new file mode 100644
index 000000000000..57a73b95d433
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config012.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR default
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config013.cfg b/tests/zfs-tests/tests/functional/inheritance/config013.cfg
new file mode 100644
index 000000000000..1052526379f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config013.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config014.cfg b/tests/zfs-tests/tests/functional/inheritance/config014.cfg
new file mode 100644
index 000000000000..1052526379f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config014.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config015.cfg b/tests/zfs-tests/tests/functional/inheritance/config015.cfg
new file mode 100644
index 000000000000..31294110f6ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config015.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config016.cfg b/tests/zfs-tests/tests/functional/inheritance/config016.cfg
new file mode 100644
index 000000000000..31294110f6ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config016.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL default
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config017.cfg b/tests/zfs-tests/tests/functional/inheritance/config017.cfg
new file mode 100644
index 000000000000..d15beb2c4ca8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config017.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config018.cfg b/tests/zfs-tests/tests/functional/inheritance/config018.cfg
new file mode 100644
index 000000000000..d15beb2c4ca8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config018.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config019.cfg b/tests/zfs-tests/tests/functional/inheritance/config019.cfg
new file mode 100644
index 000000000000..23616cbf3b7f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config019.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR -
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config020.cfg b/tests/zfs-tests/tests/functional/inheritance/config020.cfg
new file mode 100644
index 000000000000..23616cbf3b7f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config020.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR -
+TESTPOOL/TESTCTR/TESTFS1 FS -
diff --git a/tests/zfs-tests/tests/functional/inheritance/config021.cfg b/tests/zfs-tests/tests/functional/inheritance/config021.cfg
new file mode 100644
index 000000000000..a059d17978f7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config021.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR -
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config022.cfg b/tests/zfs-tests/tests/functional/inheritance/config022.cfg
new file mode 100644
index 000000000000..a059d17978f7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config022.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR -
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config023.cfg b/tests/zfs-tests/tests/functional/inheritance/config023.cfg
new file mode 100644
index 000000000000..b416c9f17d20
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config023.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/config024.cfg b/tests/zfs-tests/tests/functional/inheritance/config024.cfg
new file mode 100644
index 000000000000..b416c9f17d20
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/config024.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) 2013 by Delphix. All rights reserved.
+#
+
+TESTPOOL POOL local
+TESTPOOL/TESTCTR CTR local
+TESTPOOL/TESTCTR/TESTFS1 FS local
diff --git a/tests/zfs-tests/tests/functional/inheritance/inherit.kshlib b/tests/zfs-tests/tests/functional/inheritance/inherit.kshlib
new file mode 100644
index 000000000000..cd6bd5c027ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/inherit.kshlib
@@ -0,0 +1,114 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+#
+# Simple function to get the source of the specified property.
+# If unable to get the property then exits.
+#
+function get_prop_src # property dataset
+{
+ typeset prop_val
+ typeset prop=$1
+ typeset dataset=$2
+
+ prop_val=`zfs get -H -o source $prop $dataset`
+
+ if [[ $? -ne 0 ]]; then
+ log_fail "Unable to determine the source of $prop " \
+ "property for dataset $dataset"
+ else
+ echo $prop_val
+ fi
+}
+
+#
+# Function to check the 'source' of a property. The source can
+# either be "default", "local", or "inherited from <parent dataset>".
+#
+# The 'expected src' argument must be either "default", "local", or
+# a dataset name.
+#
+# Returns 0 on success, 1 on failure.
+#
+function verify_prop_src # child_dataset property expected_src
+{
+ typeset target=$1
+ typeset prop=$2
+ typeset expected=$3
+
+ prop_src=`get_prop_src $prop $target`
+
+ #
+ # Rather than just checking if $prop_src == $expected
+ # we first determine what value $expected should have.
+ # This allows us to catch the case where a property
+ # has a source of "local" but we expected it to be
+ # "default"
+ #
+ if [[ $expected == "default" ]]; then
+ if [[ $prop_src != $expected ]]; then
+ log_note "Property $prop of $target has source"\
+ " $prop_src rather than $expected"
+ return 1
+ fi
+ elif [[ $expected == "local" ]]; then
+ if [[ $prop_src != $expected ]]; then
+ log_note "Property $prop of $target has source"\
+ " $prop_src rather than $expected"
+ return 1
+ fi
+ elif [[ $prop_src != "inherited from $expected" ]]; then
+ log_note "Property $prop of $expected has source $prop_src"\
+ " rather than 'inherited from $expected'"
+ return 1
+ fi
+
+ return 0
+}
+
+#
+# Simple function to set a property to a
+# specified value and verify it has changed
+# correctly.
+#
+function set_n_verify_prop #property value dataset
+{
+ typeset prop=$1
+ typeset prop_val=$2
+ typeset dataset=$3
+
+ zfs set $prop=$prop_val $dataset
+ check_val=`get_prop $prop $dataset`
+
+ if [[ $check_val != $prop_val ]]; then
+ log_fail "Property $prop of $dataset has value $check_val"\
+ " rather than $prop_val"
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh b/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
new file mode 100755
index 000000000000..7c5b81287736
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/inherit_001_pos.ksh
@@ -0,0 +1,452 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/inheritance/inherit.kshlib
+
+#
+# DESCRIPTION:
+# Test that properties are correctly inherited using 'zfs set',
+# 'zfs inherit' and 'zfs inherit -r'.
+#
+# STRATEGY:
+# 1) Read a configX.cfg file and create the specified datasets
+# 2) Read a stateX.cfg file and execute the commands within it
+# and verify that the properties have the correct values
+# 3) Repeat steps 1-2 for each configX and stateX files found.
+#
+
+verify_runnable "global"
+
+log_assert "Test properties are inherited correctly"
+
+#
+# Simple function to create specified datasets.
+#
+function create_dataset { #name type disks
+ typeset dataset=$1
+ typeset type=$2
+ typeset disks=$3
+
+ if [[ $type == "POOL" ]]; then
+ create_pool "$dataset" "$disks"
+ elif [[ $type == "CTR" ]]; then
+ log_must zfs create $dataset
+ log_must zfs set canmount=off $dataset
+ elif [[ $type == "FS" ]]; then
+ log_must zfs create $dataset
+ else
+ log_fail "Unrecognised type $type"
+ fi
+
+ list="$list $dataset"
+}
+
+#
+# Function to walk through all the properties in a
+# dataset, setting them to a 'local' value if required.
+#
+function init_props { #dataset init_code
+ typeset dataset=$1
+ typeset init_code=$2
+ typeset dir=$3
+
+ typeset -i i=0
+
+ #
+ # Though the effect of '-' and 'default' is the same we
+ # call them out via a log_note to aid in debugging the
+ # config files
+ #
+ if [[ $init_code == "-" ]]; then
+ log_note "Leaving properties for $dataset unchanged."
+ [[ $def_recordsize == 0 ]] && \
+ update_recordsize $dataset $init_code
+ return;
+ elif [[ $init_code == "default" ]]; then
+ log_note "Leaving properties for $dataset at default values."
+ [[ $def_recordsize == 0 ]] && \
+ update_recordsize $dataset $init_code
+ return;
+ elif [[ $init_code == "local" ]]; then
+ log_note "Setting properties for $dataset to local values."
+ while (( i < ${#prop[*]} )); do
+ if [[ ${prop[i]} == "recordsize" ]]; then
+ update_recordsize $dataset $init_code
+ else
+ if [[ ${prop[i]} == "mountpoint" ]]; then
+ set_n_verify_prop ${prop[i]} \
+ ${local_val[((i/2))]}.$dir $dataset
+ else
+ set_n_verify_prop ${prop[i]} \
+ ${local_val[((i/2))]} $dataset
+ fi
+ fi
+
+ ((i = i + 2))
+ done
+ else
+ log_fail "Unrecognised init code $init_code"
+ fi
+}
+
+#
+# We enter this function either to update the recordsize value
+# in the default array, or to update the local value array.
+#
+function update_recordsize { #dataset init_code
+ typeset dataset=$1
+ typeset init_code=$2
+ typeset idx=0
+ typeset record_val
+
+ #
+ # First need to find where the recordsize property is
+ # located in the arrays
+ #
+ while (( idx < ${#prop[*]} )); do
+ [[ ${prop[idx]} == "recordsize" ]] && break
+
+ ((idx = idx + 2))
+ done
+
+ ((idx = idx / 2))
+ record_val=`get_prop recordsize $dataset`
+ if [[ $init_code == "-" || $init_code == "default" ]]; then
+ def_val[idx]=$record_val
+ def_recordsize=1
+ elif [[ $init_code == "local" ]]; then
+ log_must zfs set recordsize=$record_val $dataset
+ local_val[idx]=$record_val
+ fi
+}
+
+#
+# The mountpoint property is slightly different from other properties and
+# so is handled here. For all other properties if they are set to a specific
+# value at a higher level in the data hierarchy (i.e. checksum=on) then that
+# value propagates down the hierarchy unchanged, with the source field being
+# set to 'inherited from <higher dataset>'.
+#
+# The mountpoint property is different in that while the value propagates
+# down the hierarchy, the value at each level is determined by a combination
+# of the top-level value and the current level in the hierarchy.
+#
+# For example consider the case where we have a pool (called pool1), containing
+# a dataset (ctr) which in turn contains a filesystem (fs). If we set the
+# mountpoint of the pool to '/mnt2' then the mountpoints for the dataset and
+# filesystem are '/mnt2/ctr' and /mnt2/ctr/fs' respectively, with the 'source'
+# field being set to 'inherited from pool1'.
+#
+# So at the filesystem level to calculate what our mountpoint property should
+# be set to we walk back up the hierarchy sampling the mountpoint property at
+# each level and forming up the expected mountpoint value piece by piece until
+# we reach the level specified in the 'source' field, which in this example is
+# the top-level pool.
+#
+function get_mntpt_val #dataset src index
+{
+ typeset dataset=$1
+ typeset src=$2
+ typeset idx=$3
+ typeset new_path=""
+ typeset dset
+ typeset mntpt=""
+
+ if [[ $src == "local" ]]; then
+ # Extract mount points specific to datasets
+ if [[ $dataset == "TESTPOOL" ]]; then
+ mntpt=${local_val[idx]}.1
+ elif [[ $dataset == "TESTPOOL/TESTCTR" ]]; then
+ mntpt=${local_val[idx]}.2
+ else
+ mntpt=${local_val[idx]}.3
+ fi
+ elif [[ $src == "default" ]]; then
+ mntpt="/$dataset"
+ else
+ # Walk back up the hierarchy building up the
+ # expected mountpoint property value.
+ obj_name=${dataset##*/}
+
+ while [[ $src != $dataset ]]; do
+ dset=${dataset%/*}
+
+ mnt_val=`get_prop mountpoint $dset`
+
+ mod_prop_val=${mnt_val##*/}
+ new_path="/"$mod_prop_val$new_path
+ dataset=$dset
+ done
+
+ mntpt=$new_path"/"$obj_name
+ fi
+ echo $mntpt
+}
+
+#
+# Simple function to verify that a property has the
+# expected value.
+#
+function verify_prop_val #property dataset src index
+{
+ typeset prop=$1
+ typeset dataset=$2
+ typeset src=$3
+ typeset idx=$4
+ typeset new_path=""
+ typeset dset
+ typeset exp_val
+ typeset prop_val
+
+ prop_val=`get_prop $prop $dataset`
+
+ # mountpoint property is handled as a special case
+ if [[ $prop == "mountpoint" ]]; then
+ exp_val=`get_mntpt_val $dataset $src $idx`
+ else
+ if [[ $src == "local" ]]; then
+ exp_val=${local_val[idx]}
+ elif [[ $src == "default" ]]; then
+ exp_val=${def_val[idx]}
+ else
+ #
+ # We are inheriting the value from somewhere
+ # up the hierarchy.
+ #
+ exp_val=`get_prop $prop $src`
+ fi
+ fi
+
+ if [[ $prop_val != $exp_val ]]; then
+ # After putback PSARC/2008/231 Apr,09,2008,
+ # the default value of aclinherit has changed to be
+ # 'restricted' instead of 'secure',
+ # but the old interface of 'secure' still exist
+
+ if [[ $prop != "aclinherit" || \
+ $exp_val != "secure" || \
+ $prop_val != "restricted" ]]; then
+
+ log_fail "$prop of $dataset is [$prop_val] rather "\
+ "than [$exp_val]"
+ fi
+ fi
+}
+
+#
+# Function to read the configX.cfg files and create the specified
+# dataset hierarchy
+#
+function scan_config { #config-file
+ typeset config_file=$1
+
+ DISK=${DISKS%% *}
+
+ list=""
+ typeset -i mount_dir=1
+
+ grep "^[^#]" $config_file | {
+ while read name type init ; do
+ create_dataset $name $type $DISK
+ init_props $name $init $mount_dir
+ ((mount_dir = mount_dir + 1))
+ done
+ }
+}
+
+#
+# Function to check an exit flag, calling log_fail if that exit flag
+# is non-zero. Can be used from code that runs in a tight loop, which
+# would otherwise result in a lot of journal output.
+#
+function check_failure { # int status, error message to use
+
+ typeset -i exit_flag=$1
+ error_message=$2
+
+ if [[ $exit_flag -ne 0 ]]; then
+ log_fail "$error_message"
+ fi
+}
+
+
+#
+# Main function. Executes the commands specified in the stateX.cfg
+# files and then verifies that all the properties have the correct
+# values and 'source' fields.
+#
+function scan_state { #state-file
+ typeset state_file=$1
+ typeset -i i=0
+ typeset -i j=0
+
+ log_note "Reading state from $state_file"
+
+ while ((i < ${#prop[*]})); do
+ grep "^[^#]" $state_file | {
+ while IFS=: read target op; do
+ #
+ # The user can if they wish specify that no
+ # operation be performed (by specifying '-'
+ # rather than a command). This is not as
+ # useless as it sounds as it allows us to
+ # verify that the dataset hierarchy has been
+ # set up correctly as specified in the
+ # configX.cfg file (which includes 'set'ting
+ # properties at a higher level and checking
+ # that they propagate down to the lower levels.
+ #
+ # Note in a few places here, we use
+ # check_failure, rather than log_must - this
+ # substantially reduces journal output.
+ #
+ if [[ $op == "-" ]]; then
+ log_note "No operation specified"
+ else
+ export __ZFS_POOL_RESTRICT="TESTPOOL"
+ log_must zfs unmount -a
+ unset __ZFS_POOL_RESTRICT
+
+ for p in ${prop[i]} ${prop[((i+1))]}; do
+ zfs $op $p $target
+ ret=$?
+ check_failure $ret "zfs $op $p \
+ $target"
+ done
+ fi
+ for check_obj in $list; do
+ read init_src final_src
+
+ for p in ${prop[i]} ${prop[((i+1))]}; do
+ # check_failure to keep journal small
+ verify_prop_src $check_obj $p \
+ $final_src
+ ret=$?
+ check_failure $ret "verify" \
+ "_prop_src $check_obj $p" \
+ "$final_src"
+
+ # Again, to keep journal size down.
+ verify_prop_val $p $check_obj \
+ $final_src $j
+ ret=$?
+ check_failure $ret "verify" \
+ "_prop_val $check_obj $p" \
+ "$final_src"
+ done
+ done
+ done
+ }
+ ((i = i + 2))
+ ((j = j + 1))
+ done
+}
+
+#
+# Note that we keep this list relatively short so that this test doesn't
+# time out (after taking more than 10 minutes).
+#
+set -A prop "checksum" "" \
+ "compression" "" \
+ "atime" "" \
+ "sharenfs" "" \
+ "recordsize" "recsize" \
+ "snapdir" "" \
+ "readonly" ""
+
+#
+# Note except for the mountpoint default value (which is handled in
+# the routine itself), each property specified in the 'prop' array
+# above must have a corresponding entry in the two arrays below.
+#
+
+set -A def_val "on" "off" "on" \
+ "off" "" \
+ "hidden" \
+ "off"
+
+set -A local_val "off" "on" "off" \
+ "on" "" \
+ "visible" \
+ "off"
+
+#
+# Add system specific values
+#
+if is_linux; then
+ prop+=("acltype" "")
+ def_val+=("off")
+ local_val+=("off")
+else
+ prop+=("aclmode" "")
+ def_val+=("discard")
+ local_val+=("groupmask")
+fi
+if is_illumos; then
+ prop+=("mountpoint" "")
+ def_val+=("")
+ local_val+=("$TESTDIR")
+fi
+
+#
+# Global flag indicating whether the default record size had been
+# read.
+#
+typeset def_recordsize=0
+
+set -A config_files $(ls $STF_SUITE/tests/functional/inheritance/config*[1-9]*.cfg)
+set -A state_files $(ls $STF_SUITE/tests/functional/inheritance/state*.cfg)
+
+#
+# Global list of datasets created.
+#
+list=""
+
+typeset -i k=0
+
+if [[ ${#config_files[*]} != ${#state_files[*]} ]]; then
+ log_fail "Must have the same number of config files " \
+ " (${#config_files[*]}) and state files ${#state_files[*]}"
+fi
+
+while ((k < ${#config_files[*]})); do
+ default_cleanup_noexit
+ def_recordsize=0
+
+ log_note "Testing configuration ${config_files[k]}"
+
+ scan_config ${config_files[k]}
+ scan_state ${state_files[k]}
+
+ ((k = k + 1))
+done
+
+log_pass "Properties correctly inherited as expected"
diff --git a/tests/zfs-tests/tests/functional/inheritance/state001.cfg b/tests/zfs-tests/tests/functional/inheritance/state001.cfg
new file mode 100644
index 000000000000..afaf3cccfe14
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state001.cfg
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# No command is actually run (hence '-:-') but rather this state file is
+# used to verify that the property that was set on the top level pool
+# via the 'local' keyword (in the config1.cfg file) has correctly
+# propagated down the hierarchy.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+-:-
+#
+local local
+TESTPOOL TESTPOOL
+TESTPOOL TESTPOOL
diff --git a/tests/zfs-tests/tests/functional/inheritance/state002.cfg b/tests/zfs-tests/tests/functional/inheritance/state002.cfg
new file mode 100644
index 000000000000..5b2f2d2dd98a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state002.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.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# No command is actually run (hence '-:-') but rather this state file is
+# used to verify that the property that was set on the middle level
+# dataset via the 'local' keyword (in the configX.cfg file) has
+# correctly propagated down the hierarchy to the filesystem underneath,
+# while leaving the top level pools properties unchanged.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+-:-
+#
+default default
+local local
+TESTPOOL/TESTCTR TESTPOOL/TESTCTR
diff --git a/tests/zfs-tests/tests/functional/inheritance/state003.cfg b/tests/zfs-tests/tests/functional/inheritance/state003.cfg
new file mode 100644
index 000000000000..5780065ace88
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state003.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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# No command is actually run (hence '-:-') but rather this state file is
+# used to verify that setting the filesystem's properties does not affect
+# the properties of datasets above it in the hierarchy.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+-:-
+#
+default default
+default default
+local local
diff --git a/tests/zfs-tests/tests/functional/inheritance/state004.cfg b/tests/zfs-tests/tests/functional/inheritance/state004.cfg
new file mode 100644
index 000000000000..e62979a04b7d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state004.cfg
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# No command is actually run (hence '-:-') but rather this state file is
+# used to verify that setting a property on a middle level dataset does
+# not prevent us from setting a property on the bottom level filesystem,
+# and that neither affects the top level pools properties.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+-:-
+#
+default default
+local local
+local local
diff --git a/tests/zfs-tests/tests/functional/inheritance/state005.cfg b/tests/zfs-tests/tests/functional/inheritance/state005.cfg
new file mode 100644
index 000000000000..097459ffedb9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state005.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.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# No command is actually run (hence '-:-') but rather this state file is
+# used to verify that when we set a property on a top level pool, followed
+# by a middle level dataset, that the bottom level filesystem inherits
+# the property from the middle level dataset, and not from the top level
+# pool.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+-:-
+#
+local local
+local local
+TESTPOOL/TESTCTR TESTPOOL/TESTCTR
diff --git a/tests/zfs-tests/tests/functional/inheritance/state006.cfg b/tests/zfs-tests/tests/functional/inheritance/state006.cfg
new file mode 100644
index 000000000000..9863b298fe35
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state006.cfg
@@ -0,0 +1,47 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# No command is actually run (hence '-:-') but rather this state file is
+# used to verify that when we set a property on a top level pool, followed
+# by a bottom level filesystem, that the middle level dataset inherits
+# the property from the top level pool, and not from the bottom level
+# filesystem.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+-:-
+#
+# <prop src before cmd> <prop src after cmd>
+#
+local local
+TESTPOOL TESTPOOL
+local local
diff --git a/tests/zfs-tests/tests/functional/inheritance/state007.cfg b/tests/zfs-tests/tests/functional/inheritance/state007.cfg
new file mode 100644
index 000000000000..731ec95a250b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state007.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.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# No command is actually run (hence '-:-') but rather this state file is
+# used to verify that when we can set properties on each level of the
+# hierarchy independently.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+-:-
+#
+# <prop src before cmd> <prop src after cmd>
+#
+local local
+local local
+local local
diff --git a/tests/zfs-tests/tests/functional/inheritance/state008.cfg b/tests/zfs-tests/tests/functional/inheritance/state008.cfg
new file mode 100644
index 000000000000..7385c98c3c07
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state008.cfg
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# No command is actually run (hence '-:-') but rather this state file is
+# used to verify that when we create a dataset hierarchy that the
+# properties of each dataset have their default values.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+-:-
+#
+# <prop src before cmd> <prop src after cmd>
+default default
+default default
+default default
diff --git a/tests/zfs-tests/tests/functional/inheritance/state009.cfg b/tests/zfs-tests/tests/functional/inheritance/state009.cfg
new file mode 100644
index 000000000000..3fb2841a2cc1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state009.cfg
@@ -0,0 +1,57 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit' at different levels of a
+# data hierarchy where the properties of each dataset have their
+# default values leaves the values unchanged.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit
+#
+default default
+default default
+default default
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+default default
+default default
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state010.cfg b/tests/zfs-tests/tests/functional/inheritance/state010.cfg
new file mode 100644
index 000000000000..4c51e808b1fa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state010.cfg
@@ -0,0 +1,56 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit -r' at different levels of a
+# data hierarchy where the properties of each dataset have their
+# default values leaves the values unchanged.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+TESTPOOL:inherit -r
+#
+default default
+default default
+default default
+#
+TESTPOOL/TESTCTR:inherit -r
+#
+default default
+default default
+default default
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit -r
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state011.cfg b/tests/zfs-tests/tests/functional/inheritance/state011.cfg
new file mode 100644
index 000000000000..f6e791ee73c1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state011.cfg
@@ -0,0 +1,58 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that running 'zfs inherit' at each level of the data hierarchy
+# when the bottom filesystem level properties have been set locally has
+# no effect except at the bottom level where the property values are
+# inherited from the middle level dataset.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit
+#
+default default
+default default
+local local
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+default default
+local local
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+local default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state012.cfg b/tests/zfs-tests/tests/functional/inheritance/state012.cfg
new file mode 100644
index 000000000000..47898244b025
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state012.cfg
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that running 'zfs inherit -r' at each level of the data hierarchy
+# when the bottom filesystem level properties have been set locally results
+# in the top level property values being propagated down the data
+# hierarchy.
+#
+# Executing inherit -r at the middle level and bottom levels after
+# running it at the top level is somewhat redundant as the top level value
+# should propagate down the entire data hierarchy. Done for completeness
+# sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+TESTPOOL:inherit -r
+#
+default default
+default default
+local default
+#
+TESTPOOL/TESTCTR:inherit -r
+#
+default default
+default default
+default default
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit -r
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state013.cfg b/tests/zfs-tests/tests/functional/inheritance/state013.cfg
new file mode 100644
index 000000000000..ae5919292623
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state013.cfg
@@ -0,0 +1,56 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit' on each level when the middle
+# and bottom levels properties are set locally results in the middle and
+# bottom levels inheriting values from the next level up in the hierarchy.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+TESTPOOL:inherit
+#
+default default
+local local
+local local
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+local default
+local local
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+local default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state014.cfg b/tests/zfs-tests/tests/functional/inheritance/state014.cfg
new file mode 100644
index 000000000000..3770c5093e52
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state014.cfg
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that running 'zfs inherit -r' at each level of the data hierarchy
+# when the bottom and middle level properties have been set locally results
+# in the top level property values being propagated down the data
+# hierarchy.
+#
+# Note : executing inherit -r at the middle level and bottom levels after
+# running it at the top level is somewhat redundant as the top level value
+# should propagate down the entire data hierarchy. Done for completeness
+# sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+TESTPOOL:inherit -r
+#
+default default
+local default
+local default
+#
+TESTPOOL/TESTCTR:inherit -r
+#
+default default
+default default
+default default
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit -r
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state015.cfg b/tests/zfs-tests/tests/functional/inheritance/state015.cfg
new file mode 100644
index 000000000000..fb1fc3907b76
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state015.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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit' at the top level in the hierarchy
+# when the middle level properties are set locally, and the bottom
+# level has inherited its value from the middle level, results in no change
+# to the top level properties.
+#
+# Executing 'zfs inherit' at the middle level results in the middle level
+# inheriting its value from the top level, and passing the values down to
+# the bottom level.
+#
+# Executing 'zfs inherit' at the bottom level is somewhat redundant but
+# is done for completeness sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit
+#
+default default
+local local
+TESTPOOL/TESTCTR TESTPOOL/TESTCTR
+#
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+local default
+TESTPOOL/TESTCTR default
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+default default
diff --git a/tests/zfs-tests/tests/functional/inheritance/state016.cfg b/tests/zfs-tests/tests/functional/inheritance/state016.cfg
new file mode 100644
index 000000000000..f17154c74519
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state016.cfg
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit -r' at the top level in the hierarchy
+# when the middle level properties are set locally, and the bottom
+# level has inherited its value from the middle level, results in no change
+# to the top level properties and the middle and bottom properties changing
+# to the top level (default) values.
+#
+# Executing 'zfs inherit -r' at the bottom and middle levels after executing
+# at the top level is somewhat redundant but ss done for completeness sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit -r
+#
+default default
+local default
+TESTPOOL default
+#
+TESTPOOL/TESTCTR:inherit -r
+#
+default default
+default default
+default default
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit -r
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state017.cfg b/tests/zfs-tests/tests/functional/inheritance/state017.cfg
new file mode 100644
index 000000000000..a993eed5f78c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state017.cfg
@@ -0,0 +1,67 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit' at the top level in the hierarchy
+# when the top level and middle level datasets properties are set locally,
+# and the bottom level has inherited its properties from the middle
+# level, results in the top level properties reverting back to their
+# default values.
+#
+# Executing 'zfs inherit' at the middle level results in the middle level
+# inheriting its value from the top level (which is now default), and passing
+# the values down to the bottom level.
+#
+# Executing 'zfs inherit' at the bottom level is somewhat redundant but
+# is done for completeness sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit
+#
+local default
+local local
+TESTPOOL/TESTCTR TESTPOOL/TESTCTR
+#
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+local default
+TESTPOOL/TESTCTR default
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+default default
diff --git a/tests/zfs-tests/tests/functional/inheritance/state018.cfg b/tests/zfs-tests/tests/functional/inheritance/state018.cfg
new file mode 100644
index 000000000000..6fd08c6fb8b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state018.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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit -r' at the top level in the hierarchy
+# when the top level and middle level datasets properties are set locally,
+# and the bottom level has inherited its properties from the middle
+# level, results in the top level properties reverting back to their
+# default values and being propagated down to the other datasets in the
+# hierarchy.
+#
+# Executing 'zfs inherit -r' at the middle and bottom levels after executing
+# it at the top level is somewhat redundant but is done for completeness sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit -r
+#
+local default
+local default
+TESTPOOL/TESTCTR default
+#
+#
+TESTPOOL/TESTCTR:inherit -r
+#
+default default
+default default
+default default
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+default default
diff --git a/tests/zfs-tests/tests/functional/inheritance/state019.cfg b/tests/zfs-tests/tests/functional/inheritance/state019.cfg
new file mode 100644
index 000000000000..67b488f84a09
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state019.cfg
@@ -0,0 +1,63 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit' at the top level in the hierarchy
+# when the top level properties are set locally and the middle and bottom
+# datasets have inherited from the top level, results in the top level
+# properties reverting back to their default values, the middle and bottom
+# levels inheriting the changed values.
+#
+# Executing 'zfs inherit' at the middle and bottom levels is somewhat
+# redundant but is done for completeness sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+TESTPOOL:inherit
+#
+local default
+TESTPOOL default
+TESTPOOL default
+#
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+default default
+default default
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state020.cfg b/tests/zfs-tests/tests/functional/inheritance/state020.cfg
new file mode 100644
index 000000000000..df8ba7dd5246
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state020.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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit -r' at the top level in the hierarchy
+# when the top level properties are set locally and the middle and bottom
+# datasets have inherited from the top level, results in the top level
+# properties reverting back to their default values, the middle and bottom
+# levels inheriting the changed values.
+#
+# Executing 'zfs inherit -r' at the middle and bottom levels is somewhat
+# redundant but is done for completeness sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit -r
+#
+local default
+TESTPOOL default
+TESTPOOL default
+#
+#
+TESTPOOL/TESTCTR:inherit -r
+#
+default default
+default default
+default default
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit -r
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state021.cfg b/tests/zfs-tests/tests/functional/inheritance/state021.cfg
new file mode 100644
index 000000000000..f61472eff197
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state021.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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit' at the top level in the hierarchy
+# when the top level and bottom level properties are set locally and the
+# middle dataset has inherited from the top level, results in the top level
+# properties reverting back to their default values, and the middle level
+# inheriting the new top level value.
+#
+# Executing 'zfs inherit' at the bottom level results in it inheriting
+# the middle level values.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit
+#
+local default
+TESTPOOL default
+local local
+#
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+default default
+local local
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+local default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state022.cfg b/tests/zfs-tests/tests/functional/inheritance/state022.cfg
new file mode 100644
index 000000000000..22462f97839a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state022.cfg
@@ -0,0 +1,63 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit -r' at the top level in the hierarchy
+# when the top level and bottom level properties are set locally and the
+# middle dataset has inherited from the top level, results in the top level
+# properties reverting back to their default values, the middle and bottom
+# levels inheriting the changed values.
+#
+# Executing 'zfs inherit -r' at the middle and bottom levels is somewhat
+# redundant but is done for completeness sake.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+TESTPOOL:inherit -r
+#
+local default
+TESTPOOL default
+local default
+#
+#
+TESTPOOL/TESTCTR:inherit -r
+#
+default default
+default default
+default default
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit -r
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state023.cfg b/tests/zfs-tests/tests/functional/inheritance/state023.cfg
new file mode 100644
index 000000000000..8219a2abf3c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state023.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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit' at the top level in the hierarchy
+# when each levels properties are set locally, results in the top level
+# properties reverting back to their default values.
+#
+# Executing 'zfs inherit' at the middle level results in it inheriting
+# the top levels (now default) values
+#
+# Executing 'zfs inherit' at the bottom level results in it inheriting
+# the middle levels (now default) values
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit
+#
+local default
+local local
+local local
+#
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+local default
+local local
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+local default
+#
diff --git a/tests/zfs-tests/tests/functional/inheritance/state024.cfg b/tests/zfs-tests/tests/functional/inheritance/state024.cfg
new file mode 100644
index 000000000000..848ae1437d06
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inheritance/state024.cfg
@@ -0,0 +1,63 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+# *** ASSERTION DESCRIPTION ***
+#
+# Verify that executing 'zfs inherit -r' at the top level in the hierarchy
+# when each levels properties are set locally, results in the top level
+# properties reverting back to their default values, and the changed
+# values being propagated down the hierarchy.
+#
+# Executing 'zfs inherit -r' at the middle and bottom levels after doing so
+# at the top level is somewhat redundant but is done for completeness.
+#
+# *** ASSERTION DESCRIPTION ***
+#
+#
+TESTPOOL:inherit -r
+#
+local default
+local default
+local default
+#
+#
+TESTPOOL/TESTCTR:inherit
+#
+default default
+default default
+default default
+#
+#
+TESTPOOL/TESTCTR/TESTFS1:inherit
+#
+default default
+default default
+default default
+#
diff --git a/tests/zfs-tests/tests/functional/inuse/Makefile.am b/tests/zfs-tests/tests/functional/inuse/Makefile.am
new file mode 100644
index 000000000000..c541e57eaa31
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/inuse
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ inuse_001_pos.ksh \
+ inuse_003_pos.ksh \
+ inuse_004_pos.ksh \
+ inuse_005_pos.ksh \
+ inuse_006_pos.ksh \
+ inuse_007_pos.ksh \
+ inuse_008_pos.ksh \
+ inuse_009_pos.ksh
+
+dist_pkgdata_DATA = \
+ inuse.cfg
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse.cfg b/tests/zfs-tests/tests/functional/inuse/inuse.cfg
new file mode 100644
index 000000000000..631ace7ab795
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse.cfg
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+set -A disk_array $(find_disks $DISKS)
+FS_DISK0=${disk_array[0]}
+FS_DISK1=${disk_array[1]}
+FS_DISK2=${disk_array[2]}
+disk0="${DEV_DSKDIR}/$FS_DISK0"
+disk1="${DEV_DSKDIR}/$FS_DISK1"
+disk2="${DEV_DSKDIR}/$FS_DISK2"
+disktargets="$disk0 $disk1 $disk2"
+rawdisk0="${DEV_RDSKDIR}/$FS_DISK0"
+rawdisk1="${DEV_RDSKDIR}/$FS_DISK1"
+rawdisk2="${DEV_RDSKDIR}/$FS_DISK2"
+rawtargets="$rawdisk0 $rawdisk1 $rawdisk2"
+vdisks="$FS_DISK0 $FS_DISK1"
+sdisks="$FS_DISK2"
+
+export FS_DISK0 FS_DISK1 FS_DISK2
+export disk0 disk1 disk2 disktargets
+export rawdisk0 rawdisk1 rawdisk2 rawtargets
+export vdisks sdisks
+
+export UFSMP=$TESTDIR/testinuseufsdump
+export FS_SIZE=1g
+export PREVDUMPDEV=""
+export PIDUFSDUMP=""
+export PIDUFSRESTORE=""
+# size of block to be written to test file - currently 1mb
+export BLOCK_SIZE=$(( 1024 * 1024 ))
+# number of blocks to write == size of file
+export BLOCK_COUNT=100
+export STF_TIMEOUT=1200 # 20 minutes max.
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_001_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_001_pos.ksh
new file mode 100755
index 000000000000..f824661c0067
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_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 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/inuse/inuse.cfg
+
+#
+# DESCRIPTION:
+# ZFS will not interfere with devices that are in use by dumpadm.
+#
+# STRATEGY:
+# 1. Create crash dump device using 'dumpadm'
+# 2. Try to create a ZFS pool using the 'dumpadm' crash dump device.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ #
+ # Remove dump device.
+ #
+ if [[ -n $PREVDUMPDEV ]]; then
+ log_must dumpadm -u -d $PREVDUMPDEV > /dev/null
+ fi
+
+ destroy_pool $TESTPOOL
+}
+
+log_assert "Ensure ZFS cannot use a device designated as a dump device"
+
+log_onexit cleanup
+
+typeset dumpdev=""
+
+PREVDUMPDEV=`dumpadm | grep "Dump device" | awk '{print $3}'`
+
+log_note "Zero $FS_DISK0"
+log_must cleanup_devices $FS_DISK0
+
+log_note "Configuring $rawdisk0 as dump device"
+log_must dumpadm -d $rawdisk0 > /dev/null
+
+log_note "Confirm that dump device has been setup"
+dumpdev=`dumpadm | grep "Dump device" | awk '{print $3}'`
+[[ -z "$dumpdev" ]] && log_untested "No dump device has been configured"
+
+[[ "$dumpdev" != "$rawdisk0" ]] && \
+ log_untested "Dump device has not been configured to $rawdisk0"
+
+log_note "Attempt to zpool the dump device"
+unset NOINUSE_CHECK
+log_mustnot zpool create $TESTPOOL "$rawdisk0"
+log_mustnot poolexists $TESTPOOL
+
+log_pass "Unable to zpool a device in use by dumpadm"
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_003_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_003_pos.ksh
new file mode 100755
index 000000000000..07d6ac17557c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_003_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/inuse/inuse.cfg
+
+#
+# DESCRIPTION:
+# ZFS will not interfere with devices that are in use by ufsdump or
+# ufsrestore.
+#
+# STRATEGY:
+# 1. newfs a disk
+# 2. mount the disk
+# 3. create files and dirs on disk
+# 4. umount the disk
+# 5. ufsdump this disk to a backup disk
+# 6. Try to create a ZFS pool with same disk (also as a spare device)
+# 7. ufsrestore the disk from backup
+# 8. try to create a zpool during the ufsrestore
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+
+ log_note "Kill off ufsdump process if still running"
+ kill -0 $PIDUFSDUMP > /dev/null 2>&1 && \
+ log_must kill -9 $PIDUFSDUMP > /dev/null 2>&1
+ #
+ # Note: It would appear that ufsdump spawns a number of processes
+ # which are not killed when the $PIDUFSDUMP is whacked. So best bet
+ # is to find the rest of the them and deal with them individually.
+ #
+ for all in `pgrep ufsdump`
+ do
+ kill -9 $all > /dev/null 2>&1
+ done
+
+ log_note "Kill off ufsrestore process if still running"
+ kill -0 $PIDUFSRESTORE > /dev/null 2>&1 && \
+ log_must kill -9 $PIDUFSRESTORE > /dev/null 2>&1
+
+ ismounted $UFSMP ufs && log_must umount $UFSMP
+
+ rm -rf $UFSMP
+ rm -rf $TESTDIR
+
+ #
+ # Tidy up the disks we used.
+ #
+ log_must cleanup_devices $vdisks $sdisks
+}
+
+log_assert "Ensure ZFS does not interfere with devices that are in use by " \
+ "ufsdump or ufsrestore"
+
+log_onexit cleanup
+
+typeset bigdir="${UFSMP}/bigdirectory"
+typeset restored_files="${UFSMP}/restored_files"
+typeset -i dirnum=0
+typeset -i filenum=0
+typeset cwd=""
+
+log_note "Make a ufs filesystem on source $rawdisk1"
+new_fs $rawdisk1 > /dev/null 2>&1
+(($? != 0)) && log_untested "Unable to create ufs filesystem on $rawdisk1"
+
+log_must mkdir -p $UFSMP
+
+log_note "mount source $disk1 on $UFSMP"
+log_must mount $disk1 $UFSMP
+
+log_note "Now create some directories and files to be ufsdump'ed"
+while (($dirnum <= 2)); do
+ log_must mkdir $bigdir${dirnum}
+ while (( $filenum <= 2 )); do
+ file_write -o create -f $bigdir${dirnum}/file${filenum} \
+ -b $BLOCK_SIZE -c $BLOCK_COUNT
+ if [[ $? -ne 0 ]]; then
+ if [[ $dirnum -lt 3 ]]; then
+ log_fail "file_write only wrote" \
+ "<(( $dirnum * 3 + $filenum ))>" \
+ "files, this is not enough"
+ fi
+ fi
+ ((filenum = filenum + 1))
+ done
+ filenum=0
+ ((dirnum = dirnum + 1))
+done
+
+log_must umount $UFSMP
+
+log_note "Start ufsdump in the background"
+log_note "ufsdump 0bf 512 $rawdisk0 $disk1"
+ufsdump 0bf 512 $rawdisk0 $disk1 &
+PIDUFSDUMP=$!
+
+unset NOINUSE_CHECK
+log_note "Attempt to zpool the source device in use by ufsdump"
+log_mustnot zpool create $TESTPOOL1 "$disk1"
+log_mustnot poolexists $TESTPOOL1
+
+log_note "Attempt to take the source device in use by ufsdump as spare device"
+log_mustnot zpool create $TESTPOOL1 "$FS_DISK2" spare "$disk1"
+log_mustnot poolexists $TESTPOOL1
+
+wait $PIDUFSDUMP
+typeset -i retval=$?
+(($retval != 0)) && log_fail "ufsdump failed with error code $ret_val"
+
+log_must mount $disk1 $UFSMP
+
+log_must rm -rf $UFSMP/*
+log_must mkdir $restored_files
+
+cwd=$PWD
+log_must cd $restored_files
+log_note "Start ufsrestore in the background from the target device"
+log_note "ufsrestore rbf 512 $rawdisk0"
+ufsrestore rbf 512 $rawdisk0 &
+PIDUFSRESTORE=$!
+log_must cd $cwd
+
+log_note "Attempt to zpool the restored device in use by ufsrestore"
+log_mustnot zpool create -f $TESTPOOL2 "$disk1"
+log_mustnot poolexists $TESTPOOL2
+
+log_note "Attempt to take the restored device in use by ufsrestore as spare" \
+ "device"
+log_mustnot zpool create -f $TESTPOOL2 "$FS_DISK2" spare "$disk1"
+log_mustnot poolexists $TESTPOOL2
+
+log_pass "Unable to zpool over a device in use by ufsdump or ufsrestore"
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_004_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_004_pos.ksh
new file mode 100755
index 000000000000..a9725e06dcf0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/inuse/inuse.cfg
+
+#
+# DESCRIPTION:
+# format will disallow modification of a mounted zfs disk partition or a spare
+# device
+#
+# STRATEGY:
+# 1. Create a ZFS filesystem
+# 2. Add a spare device to the ZFS pool
+# 3. Attempt to format the disk and the spare device.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ #
+ # Essentially this is the default_cleanup routine but I cannot get it
+ # to work correctly. So its reproduced below. Still need to fully
+ # understand why default_cleanup does not work correctly from here.
+ #
+ log_must zfs umount $TESTPOOL/$TESTFS
+
+ rm -rf $TESTDIR || \
+ log_unresolved Could not remove $TESTDIR
+
+ log_must zfs destroy $TESTPOOL/$TESTFS
+ destroy_pool $TESTPOOL
+}
+#
+# Currently, if a ZFS disk gets formatted things go horribly wrong, hence the
+# mini_format function. If the modify option is reached, then we know format
+# would happily continue - best to not go further.
+#
+function mini_format
+{
+ typeset disk=$1
+
+ if is_linux; then
+ parted $disk -s -- mklabel gpt
+ typeset -i retval=$?
+ elif is_freebsd; then
+ gpart create -s gpt $disk
+ typeset -i retval=$?
+ else
+ typeset format_file=$TEST_BASE_DIR/format_in.$$.1
+ echo "partition" > $format_file
+ echo "modify" >> $format_file
+
+ format -e -s -d $disk -f $format_file
+ typeset -i retval=$?
+
+ rm -rf $format_file
+ fi
+ return $retval
+}
+
+log_assert "format will disallow modification of a mounted zfs disk partition"\
+ " or a spare device"
+
+log_onexit cleanup
+log_must default_setup_noexit $FS_DISK0
+log_must zpool add $TESTPOOL spare $FS_DISK1
+
+log_note "Attempt to format a ZFS disk"
+log_mustnot mini_format $FS_DISK0
+log_note "Attempt to format a ZFS spare device"
+log_mustnot mini_format $FS_DISK1
+
+log_pass "Unable to format a disk in use by ZFS"
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_005_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_005_pos.ksh
new file mode 100755
index 000000000000..afe30d059997
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_005_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/inuse/inuse.cfg
+
+#
+# DESCRIPTION:
+# newfs will not interfere with devices and spare devices that are in use
+# by active pool.
+#
+# STRATEGY:
+# 1. Create a regular|mirror|raidz|raidz2 pool with the given disk
+# 2. Try to newfs against the disk, verify it fails as expect.
+#
+
+verify_runnable "global"
+
+if ! is_physical_device $FS_DISK0; then
+ log_unsupported "This directory cannot be run on raw files."
+fi
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ #
+ # Tidy up the disks we used.
+ #
+ cleanup_devices $vdisks $sdisks
+}
+
+function verify_assertion #disks
+{
+ typeset targets=$1
+
+ for t in $targets; do
+ if new_fs $t; then
+ log_fail "newfs over active pool " \
+ "unexpected return code of 0"
+ fi
+ done
+
+ return 0
+}
+
+log_assert "Verify newfs over active pool fails."
+
+log_onexit cleanup
+
+set -A vdevs "" "mirror" "raidz" "raidz1" "raidz2"
+
+typeset -i i=0
+
+unset NOINUSE_CHECK
+while (( i < ${#vdevs[*]} )); do
+ typeset spare="spare $sdisks"
+
+ # If this is for raidz2, use 3 disks for the pool.
+ [[ ${vdevs[i]} = "raidz2" ]] && spare="$sdisks"
+ create_pool $TESTPOOL1 ${vdevs[i]} $vdisks $spare
+ verify_assertion "$rawtargets"
+ destroy_pool $TESTPOOL1
+
+ (( i = i + 1 ))
+done
+
+log_pass "Newfs over active pool fails."
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_006_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_006_pos.ksh
new file mode 100755
index 000000000000..9657322526e7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_006_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/inuse/inuse.cfg
+
+#
+# DESCRIPTION:
+# dumpadm will not interfere with devices and spare devices that are in use
+# by active pool.
+#
+# STRATEGY:
+# 1. Create a regular|mirror|raidz|raidz2 pool with the given disk
+# 2. Try to dumpadm against the disk, verify it fails as expect.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if [[ -n $PREVDUMPDEV ]]; then
+ log_must dumpadm -u -d $PREVDUMPDEV
+ fi
+
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ #
+ # Tidy up the disks we used.
+ #
+ cleanup_devices $vdisks $sdisks
+}
+
+function verify_assertion # disks
+{
+ typeset targets=$1
+
+ for t in $targets; do
+ log_mustnot dumpadm -d $t
+ done
+
+ return 0
+}
+
+log_assert "Verify dumpadm over active pool fails."
+
+log_onexit cleanup
+
+set -A vdevs "" "mirror" "raidz" "raidz1" "raidz2"
+
+typeset -i i=0
+
+PREVDUMPDEV=`dumpadm | grep "Dump device" | awk '{print $3}'`
+
+unset NOINUSE_CHECK
+while (( i < ${#vdevs[*]} )); do
+ typeset spare="spare $sdisks"
+
+ # If this is for raidz2, use 3 disks for the pool.
+ [[ ${vdevs[i]} = "raidz2" ]] && spare="$sdisks"
+ create_pool $TESTPOOL1 ${vdevs[i]} $vdisks $spare
+ verify_assertion "$disktargets"
+ destroy_pool $TESTPOOL1
+
+ (( i = i + 1 ))
+done
+
+log_pass "Dumpadm over active pool fails."
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_007_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_007_pos.ksh
new file mode 100755
index 000000000000..b96b80890ed8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_007_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/inuse/inuse.cfg
+
+#
+# DESCRIPTION:
+# dumpadm will interfere with devices and spare devices that are in use
+# by exported pool.
+#
+# STRATEGY:
+# 1. Create a regular|mirror|raidz|raidz2 pool with the given disk
+# 2. Export the pool
+# 3. Try to dumpadm against the disk, verify it succeeds as expect.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if [[ -n $PREVDUMPDEV ]]; then
+ log_must dumpadm -u -d $PREVDUMPDEV
+ fi
+
+ poolexists $TESTPOOL1 || zpool import $TESTPOOL1 >/dev/null 2>&1
+
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ #
+ # Tidy up the disks we used.
+ #
+ cleanup_devices $vdisks $sdisks
+}
+
+function verify_assertion # disks
+{
+ typeset targets=$1
+
+ for t in $targets; do
+ log_must dumpadm -u -d $t
+
+ log_must dumpadm -u -d $PREVDUMPDEV
+ done
+
+ return 0
+}
+
+log_assert "Verify dumpadm over exported pool succeed."
+
+log_onexit cleanup
+
+set -A vdevs "" "mirror" "raidz" "raidz1" "raidz2"
+
+typeset -i i=0
+
+PREVDUMPDEV=`dumpadm | grep "Dump device" | awk '{print $3}'`
+
+while (( i < ${#vdevs[*]} )); do
+ typeset spare="spare $sdisks"
+
+ # If this is for raidz2, use 3 disks for the pool.
+ [[ ${vdevs[i]} = "raidz2" ]] && spare="$sdisks"
+ create_pool $TESTPOOL1 ${vdevs[i]} $vdisks $spare
+ log_must zpool export $TESTPOOL1
+ verify_assertion "$disktargets"
+ log_must zpool import $TESTPOOL1
+ destroy_pool $TESTPOOL1
+
+ (( i = i + 1 ))
+done
+
+log_pass "Dumpadm over exported pool succeed."
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_008_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_008_pos.ksh
new file mode 100755
index 000000000000..d60ebcee1554
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/inuse/inuse.cfg
+
+#
+# DESCRIPTION:
+# Newfs will interfere with devices and spare devices that are in use
+# by exported pool.
+#
+# STRATEGY:
+# 1. Create a regular|mirror|raidz|raidz2 pool with the given disk
+# 2. Export the pool
+# 3. Try to newfs against the disk, verify it succeeds as expect.
+#
+
+verify_runnable "global"
+
+if ! is_physical_device $FS_DISK0; then
+ log_unsupported "This directory cannot be run on raw files."
+fi
+
+function cleanup
+{
+ poolexists $TESTPOOL1 || zpool import $TESTPOOL1 >/dev/null 2>&1
+
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ #
+ # Tidy up the disks we used.
+ #
+ cleanup_devices $vdisks $sdisks
+}
+
+function verify_assertion # disks
+{
+ typeset targets=$1
+
+ for t in $targets; do
+ if ! new_fs $t; then
+ log_fail "newfs over exported pool " \
+ "fails unexpectedly."
+ fi
+ done
+
+ return 0
+}
+
+log_assert "Verify newfs over exported pool succeed."
+
+log_onexit cleanup
+
+set -A vdevs "" "mirror" "raidz" "raidz1" "raidz2"
+
+typeset -i i=0
+while (( i < ${#vdevs[*]} )); do
+ typeset spare="spare $sdisks"
+
+ # If this is for raidz2, use 3 disks for the pool.
+ [[ ${vdevs[i]} = "raidz2" ]] && spare="$sdisks"
+ create_pool $TESTPOOL1 ${vdevs[i]} $vdisks $spare
+ log_must zpool export $TESTPOOL1
+ verify_assertion "$rawtargets"
+
+ (( i = i + 1 ))
+done
+
+log_pass "Newfs over exported pool succeed."
diff --git a/tests/zfs-tests/tests/functional/inuse/inuse_009_pos.ksh b/tests/zfs-tests/tests/functional/inuse/inuse_009_pos.ksh
new file mode 100755
index 000000000000..54d201ad6291
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/inuse_009_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 2009 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/inuse/inuse.cfg
+
+#
+# DESCRIPTION:
+# format command will interfere with devices and spare devices that are in use
+# by exported pool.
+#
+# STRATEGY:
+# 1. Create a regular|mirror|raidz|raidz2 pool with the given disk
+# 2. Export the pool
+# 3. Try to format against the disk, verify it succeeds as expect.
+#
+
+verify_runnable "global"
+
+if ! is_physical_device $FS_DISK0; then
+ log_unsupported "This directory cannot be run on raw files."
+fi
+
+function cleanup
+{
+ poolexists $TESTPOOL1 || zpool import $TESTPOOL1 >/dev/null 2>&1
+
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+
+ #
+ # Tidy up the disks we used.
+ #
+ cleanup_devices $vdisks $sdisks
+}
+
+function verify_assertion # disks
+{
+ typeset targets=$1
+
+ for t in $targets; do
+ log_must zero_partitions $t
+ done
+
+ return 0
+}
+
+log_assert "Verify format over exported pool succeed."
+
+log_onexit cleanup
+
+set -A vdevs "" "mirror" "raidz" "raidz1" "raidz2"
+
+typeset -i i=0
+while (( i < ${#vdevs[*]} )); do
+ typeset spare="spare $sdisks"
+
+ # If this is for raidz2, use 3 disks for the pool.
+ [[ ${vdevs[i]} = "raidz2" ]] && spare="$sdisks"
+ create_pool $TESTPOOL1 ${vdevs[i]} $vdisks $spare
+ log_must zpool export $TESTPOOL1
+ verify_assertion "$vdisks $sdisks"
+
+ (( i = i + 1 ))
+done
+
+log_pass "Format over exported pool succeed."
diff --git a/tests/zfs-tests/tests/functional/inuse/setup.ksh b/tests/zfs-tests/tests/functional/inuse/setup.ksh
new file mode 100755
index 000000000000..962a0c98dc7e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/inuse/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/io/Makefile.am b/tests/zfs-tests/tests/functional/io/Makefile.am
new file mode 100644
index 000000000000..5253f08a0540
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/io
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ sync.ksh \
+ psync.ksh \
+ libaio.ksh \
+ posixaio.ksh \
+ mmap.ksh
+
+dist_pkgdata_DATA = \
+ io.cfg
diff --git a/tests/zfs-tests/tests/functional/io/cleanup.ksh b/tests/zfs-tests/tests/functional/io/cleanup.ksh
new file mode 100755
index 000000000000..0031a26c3cec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/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) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/io/io.cfg b/tests/zfs-tests/tests/functional/io/io.cfg
new file mode 100644
index 000000000000..9312ad1e1430
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/io.cfg
@@ -0,0 +1,25 @@
+#
+# 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) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+FIO_COMMON_ARGS="--numjobs=1 --bs=32k --size=32M --fallocate=none --group_reporting --verify=sha1 --minimal"
+
+FIO_READ_ARGS="--name=rw --rw=read $FIO_COMMON_ARGS"
+FIO_WRITE_ARGS="--name=rw --rw=write $FIO_COMMON_ARGS"
+FIO_RANDREAD_ARGS="--name=rw --rw=randread $FIO_COMMON_ARGS"
+FIO_RANDWRITE_ARGS="--name=rw --rw=randwrite $FIO_COMMON_ARGS"
diff --git a/tests/zfs-tests/tests/functional/io/libaio.ksh b/tests/zfs-tests/tests/functional/io/libaio.ksh
new file mode 100755
index 000000000000..c434ad90ddd7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/libaio.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 (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+# Verify Linux native asynchronous IO.
+#
+# STRATEGY:
+# 1. Use fio(1) in verify mode to perform write, read,
+# random read, and random write workloads.
+# 2. Repeat the test with additional fio(1) options.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must rm -f "$mntpnt/rw*"
+}
+
+log_assert "Verify Linux native asynchronous IO"
+
+log_onexit cleanup
+
+ioengine="--ioengine=libaio"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in "${fio_arg[@]}"; do
+ log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+ log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified Linux native asynchronous IO"
diff --git a/tests/zfs-tests/tests/functional/io/mmap.ksh b/tests/zfs-tests/tests/functional/io/mmap.ksh
new file mode 100755
index 000000000000..e9600787a8bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/mmap.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 (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+# Verify memory mapped IO with mmap(2) and memcpy(3)
+#
+# STRATEGY:
+# 1. Use fio(1) in verify mode to perform write, read,
+# random read, and random write workloads.
+# 2. Repeat the test with additional fio(1) options.
+#
+
+if ! compare_version_gte $(fio --version) "fio-2.3"; then
+ log_unsupported "Requires fio-2.3 or newer"
+fi
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must rm -f "$mntpnt/rw*"
+}
+
+log_assert "Verify memory mapped IO with mmap(2) and memcpy(3)"
+
+log_onexit cleanup
+
+ioengine="--ioengine=mmap"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in "${fio_arg[@]}"; do
+ log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+ log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified memory mapped IO with mmap(2) and memcpy(3)"
diff --git a/tests/zfs-tests/tests/functional/io/posixaio.ksh b/tests/zfs-tests/tests/functional/io/posixaio.ksh
new file mode 100755
index 000000000000..0758164c1673
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/posixaio.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 (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+# Verify POSIX asynchronous IO with aio_read(3) and aio_write(3).
+#
+# STRATEGY:
+# 1. Use fio(1) in verify mode to perform write, read,
+# random read, and random write workloads.
+# 2. Repeat the test with additional fio(1) options.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must rm -f "$mntpnt/rw*"
+}
+
+log_assert "Verify POSIX asynchronous IO with aio_read(3) and aio_write(3)"
+
+log_onexit cleanup
+
+ioengine="--ioengine=posixaio"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in "${fio_arg[@]}"; do
+ log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+ log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified POSIX asynchronous IO with aio_read(3) and aio_write(3)"
diff --git a/tests/zfs-tests/tests/functional/io/psync.ksh b/tests/zfs-tests/tests/functional/io/psync.ksh
new file mode 100755
index 000000000000..efeb1103d8bb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/psync.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 (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+# Verify basic pread(2) and pwrite(2).
+#
+# STRATEGY:
+# 1. Use fio(1) in verify mode to perform write, read,
+# random read, and random write workloads.
+# 2. Repeat the test with additional fio(1) options.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must rm -f "/$TESTPOOL/rw*"
+}
+
+log_assert "Verify basic pread(2), pwrite(2)"
+
+log_onexit cleanup
+
+ioengine="--ioengine=psync"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in "${fio_arg[@]}"; do
+ log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+ log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified basic pread(2), pwrite(2)"
diff --git a/tests/zfs-tests/tests/functional/io/setup.ksh b/tests/zfs-tests/tests/functional/io/setup.ksh
new file mode 100755
index 000000000000..ff72fc3db7c0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/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) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+verify_runnable "global"
+
+default_setup "$DISKS"
+log_must zfs set compression=on $TESTPOOL/$TESTFS
diff --git a/tests/zfs-tests/tests/functional/io/sync.ksh b/tests/zfs-tests/tests/functional/io/sync.ksh
new file mode 100755
index 000000000000..83f346c6972a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/io/sync.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 (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/io/io.cfg
+
+#
+# DESCRIPTION:
+# Verify basic read(2), write(2) and lseek(2).
+#
+# STRATEGY:
+# 1. Use fio(1) in verify mode to perform write, read,
+# random read, and random write workloads.
+# 2. Repeat the test with additional fio(1) options.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must rm -f "$mntpnt/rw*"
+}
+
+log_assert "Verify basic read(2), write(2) and lseek(2)"
+
+log_onexit cleanup
+
+ioengine="--ioengine=sync"
+mntpnt=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+dir="--directory=$mntpnt"
+
+set -A fio_arg -- "--sync=0" "--sync=1" "--direct=0" "--direct=1"
+
+for arg in ${fio_arg[@]}; do
+ log_must fio $dir $ioengine $arg $FIO_WRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_READ_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDWRITE_ARGS
+ log_must fio $dir $ioengine $arg $FIO_RANDREAD_ARGS
+ log_must rm -f "$mntpnt/rw*"
+done
+
+log_pass "Verified basic read(2), write(2) and lseek(2)"
diff --git a/tests/zfs-tests/tests/functional/large_files/Makefile.am b/tests/zfs-tests/tests/functional/large_files/Makefile.am
new file mode 100644
index 000000000000..0e471533090c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/large_files/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/large_files
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ large_files_001_pos.ksh \
+ large_files_002_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/large_files/cleanup.ksh b/tests/zfs-tests/tests/functional/large_files/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/large_files/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/large_files/large_files_001_pos.ksh b/tests/zfs-tests/tests/functional/large_files/large_files_001_pos.ksh
new file mode 100755
index 000000000000..f59603724e76
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/large_files/large_files_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Write a file to the allowable ZFS fs size.
+#
+# STRATEGY:
+# 1. largest_file will write to a file and increase its size
+# to the maximum allowable.
+# 2. The last byte of the file should be accessible without error.
+# 3. Writing beyond the maximum file size generates an 'errno' of
+# EFBIG.
+#
+
+verify_runnable "both"
+
+log_assert "Write a file to the allowable ZFS fs size."
+
+log_note "Invoke 'largest_file' with $TESTDIR/bigfile"
+log_must largest_file $TESTDIR/bigfile
+
+log_pass "Successfully created a file to the maximum allowable size."
diff --git a/tests/zfs-tests/tests/functional/large_files/large_files_002_pos.ksh b/tests/zfs-tests/tests/functional/large_files/large_files_002_pos.ksh
new file mode 100755
index 000000000000..255a8f8b5ad6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/large_files/large_files_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 (c) 2015 by Lawrence Livermore National Security, LLC.
+# All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify 'ulimit -f' file size restrictions are enforced.
+#
+# STRATEGY:
+# 1. Set ulimit file size to unlimited, verify files can be created.
+# 2. Reduce ulimit file size, verify the expected error is returned.
+#
+
+verify_runnable "both"
+
+log_assert "Verify 'ulimit -f' maximum file size is enforced"
+
+# Verify 'ulimit -f unlimited' works
+log_must ulimit -f unlimited
+log_must sh -c 'dd if=/dev/zero of=$TESTDIR/ulimit_write_file bs=1M count=2'
+log_must sh -c 'truncate -s2M $TESTDIR/ulimit_trunc_file'
+log_must rm $TESTDIR/ulimit_write_file $TESTDIR/ulimit_trunc_file
+
+# Verify 'ulimit -f <size>' works
+log_must ulimit -f 1024
+log_mustnot sh -c 'dd if=/dev/zero of=$TESTDIR/ulimit_write_file bs=1M count=2'
+log_must rm $TESTDIR/ulimit_write_file
+# FreeBSD allows the sparse file because space has not been allocated.
+if ! is_freebsd; then
+ log_mustnot sh -c 'truncate -s2M $TESTDIR/ulimit_trunc_file'
+ log_must rm $TESTDIR/ulimit_trunc_file
+fi
+
+log_pass "Successfully enforced 'ulimit -f' maximum file size"
diff --git a/tests/zfs-tests/tests/functional/large_files/setup.ksh b/tests/zfs-tests/tests/functional/large_files/setup.ksh
new file mode 100755
index 000000000000..3a45ec8d510d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/large_files/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+disk=${DISKS%% *}
+
+default_setup $disk
diff --git a/tests/zfs-tests/tests/functional/largest_pool/Makefile.am b/tests/zfs-tests/tests/functional/largest_pool/Makefile.am
new file mode 100644
index 000000000000..5f1473dede70
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/largest_pool/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/largest_pool
+dist_pkgdata_SCRIPTS = \
+ largest_pool_001_pos.ksh
+
+dist_pkgdata_DATA = \
+ largest_pool.cfg
diff --git a/tests/zfs-tests/tests/functional/largest_pool/largest_pool.cfg b/tests/zfs-tests/tests/functional/largest_pool/largest_pool.cfg
new file mode 100644
index 000000000000..13c157789dd7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/largest_pool/largest_pool.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export TESTVOL=testvol$$
+export VOL_PATH=${ZVOL_DEVDIR}/${TESTPOOL2}/$TESTVOL
+export VOLSIZES=${VOLSIZES-"2pb 5pb 10pb 2eb 5eb 7eb"}
+
+# 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"
diff --git a/tests/zfs-tests/tests/functional/largest_pool/largest_pool_001_pos.ksh b/tests/zfs-tests/tests/functional/largest_pool/largest_pool_001_pos.ksh
new file mode 100755
index 000000000000..a8934159b244
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/largest_pool/largest_pool_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/largest_pool/largest_pool.cfg
+
+# DESCRIPTION:
+# The largest pool can be created and a dataset in that
+# pool can be created and mounted.
+#
+# STRATEGY:
+# create a pool which will contain a volume device.
+# create a volume device of desired sizes.
+# create the largest pool allowed using the volume vdev.
+# create and mount a dataset in the largest pool.
+# create some files in the zfs file system.
+# do some zpool list commands and parse the output.
+
+verify_runnable "global"
+
+#
+# Parse the results of zpool & zfs creation with specified size
+#
+# $1: volume size
+#
+# return value:
+# 0 -> success
+# 1 -> failure
+#
+function parse_expected_output
+{
+ UNITS=`echo $1 | sed -e 's/^\([0-9].*\)\([a-z].\)/\2/'`
+ case "$UNITS" in
+ 'mb') CHKUNIT="M" ;;
+ 'gb') CHKUNIT="G" ;;
+ 'tb') CHKUNIT="T" ;;
+ 'pb') CHKUNIT="P" ;;
+ 'eb') CHKUNIT="E" ;;
+ *) CHKUNIT="M" ;;
+ esac
+
+ log_note "Detect zpool $TESTPOOL in this test machine."
+ log_must eval "zpool list $TESTPOOL > $TEST_BASE_DIR/j.$$"
+ log_must eval "grep $TESTPOOL $TEST_BASE_DIR/j.$$ | \
+ awk '{print $2}' | grep $CHKUNIT"
+
+ log_note "Detect the file system in this test machine."
+ log_must eval "df -F zfs -h > $TEST_BASE_DIR/j.$$"
+ log_must eval "grep $TESTPOOL $TEST_BASE_DIR/j.$$ | \
+ awk '{print $2}' | grep $CHKUNIT"
+
+ return 0
+}
+
+#
+# Check and destroy zfs, volume & zpool remove the temporary files
+#
+function cleanup
+{
+ log_note "Start cleanup the zfs and pool"
+
+ if datasetexists $TESTPOOL/$TESTFS ; then
+ if ismounted $TESTPOOL/$TESTFS ; then
+ log_must zfs unmount $TESTPOOL/$TESTFS
+ fi
+ log_must zfs destroy $TESTPOOL/$TESTFS
+ fi
+
+ destroy_pool $TESTPOOL
+
+ datasetexists $TESTPOOL2/$TESTVOL && \
+ log_must zfs destroy $TESTPOOL2/$TESTVOL
+
+ destroy_pool $TESTPOOL2
+
+ rm -f $TEST_BASE_DIR/j.* > /dev/null
+}
+
+log_assert "The largest pool can be created and a dataset in that" \
+ "pool can be created and mounted."
+
+# Set trigger. When the test case exit, cleanup is executed.
+log_onexit cleanup
+
+# -----------------------------------------------------------------------
+# volume sizes with unit designations.
+#
+# Note: specifying the number '1' as size will not give the correct
+# units for 'df'. It must be greater than one.
+# -----------------------------------------------------------------------
+typeset str
+typeset -i ret
+for volsize in $VOLSIZES; do
+ log_note "Create a pool which will contain a volume device"
+ create_pool $TESTPOOL2 "$DISKS"
+
+ log_note "Create a volume device of desired sizes: $volsize"
+ str=$(zfs create -sV $volsize $TESTPOOL2/$TESTVOL 2>&1)
+ ret=$?
+ if (( ret != 0 )); then
+ if [[ is_32bit && \
+ $str == *${VOL_LIMIT_KEYWORD1}* || \
+ $str == *${VOL_LIMIT_KEYWORD2}* || \
+ $str == *${VOL_LIMIT_KEYWORD3}* ]]
+ then
+ log_unsupported \
+ "Max volume size is 1TB on 32-bit systems."
+ else
+ log_fail "zfs create -sV $volsize $TESTPOOL2/$TESTVOL"
+ fi
+ fi
+ block_device_wait
+
+ log_note "Create the largest pool allowed using the volume vdev"
+ create_pool $TESTPOOL "$VOL_PATH"
+
+ log_note "Create a zfs file system in the largest pool"
+ log_must zfs create $TESTPOOL/$TESTFS
+
+ log_note "Parse the execution result"
+ parse_expected_output $volsize
+
+ log_note "unmount this zfs file system $TESTPOOL/$TESTFS"
+ log_must zfs unmount $TESTPOOL/$TESTFS
+
+ log_note "Destroy zfs, volume & zpool"
+ log_must zfs destroy $TESTPOOL/$TESTFS
+ destroy_pool $TESTPOOL
+ log_must zfs destroy $TESTPOOL2/$TESTVOL
+ destroy_pool $TESTPOOL2
+done
+
+log_pass "Dataset can be created, mounted & destroy in largest pool succeeded."
diff --git a/tests/zfs-tests/tests/functional/libzfs/.gitignore b/tests/zfs-tests/tests/functional/libzfs/.gitignore
new file mode 100644
index 000000000000..ed21ddbc9b94
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/libzfs/.gitignore
@@ -0,0 +1 @@
+/many_fds
diff --git a/tests/zfs-tests/tests/functional/libzfs/Makefile.am b/tests/zfs-tests/tests/functional/libzfs/Makefile.am
new file mode 100644
index 000000000000..53cb635444ab
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/libzfs/Makefile.am
@@ -0,0 +1,17 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/libzfs
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/libzfs
+
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ libzfs_input.ksh
+
+many_fds_LDADD = \
+ $(abs_top_builddir)/lib/libzfs/libzfs.la
+
+pkgexec_PROGRAMS = many_fds
+many_fds_SOURCES = many_fds.c
+
diff --git a/tests/zfs-tests/tests/functional/libzfs/cleanup.ksh b/tests/zfs-tests/tests/functional/libzfs/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/libzfs/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/libzfs/libzfs_input.ksh b/tests/zfs-tests/tests/functional/libzfs/libzfs_input.ksh
new file mode 100755
index 000000000000..bc39c0367bed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/libzfs/libzfs_input.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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+#
+# DESCRIPTION:
+# run C program to test passing different input to libzfs ioctls
+#
+
+log_assert "libzfs ioctls handle invalid input arguments"
+
+log_must libzfs_input_check $TESTPOOL
+
+log_pass "libzfs ioctls handle invalid input arguments"
diff --git a/tests/zfs-tests/tests/functional/libzfs/many_fds.c b/tests/zfs-tests/tests/functional/libzfs/many_fds.c
new file mode 100644
index 000000000000..e09ed60eef9a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/libzfs/many_fds.c
@@ -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 (C) 2015 STRATO AG.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <libzfs.h>
+#include <sys/resource.h>
+#include <errno.h>
+
+/*
+ * Check if libzfs works with more than 255 held file handles.
+ */
+/* ARGSUSED */
+int
+main(int argc, char **argv)
+{
+ int i;
+ struct rlimit limit;
+ libzfs_handle_t *h;
+
+ limit.rlim_cur = 65535;
+ limit.rlim_max = 65535;
+
+ if (setrlimit(RLIMIT_NOFILE, &limit) != 0) {
+ (void) printf("many_fds: setrlimit() failed with errno=%d\n",
+ errno);
+ exit(1);
+ }
+
+ for (i = 0; i < 255; ++i) {
+ int fd = open("/dev/null", O_RDONLY);
+ if (fd == -1) {
+ (void) printf("open failed with errno=%d\n", errno);
+ return (1);
+ }
+ }
+
+ h = libzfs_init();
+
+ if (h != NULL) {
+ libzfs_fini(h);
+ return (0);
+ } else {
+ (void) printf("many_fds: libzfs_init() failed with errno=%d\n",
+ errno);
+ return (1);
+ }
+}
diff --git a/tests/zfs-tests/tests/functional/libzfs/setup.ksh b/tests/zfs-tests/tests/functional/libzfs/setup.ksh
new file mode 100755
index 000000000000..fc5cec3063a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/libzfs/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/limits/Makefile.am b/tests/zfs-tests/tests/functional/limits/Makefile.am
new file mode 100644
index 000000000000..72455922485d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/limits/Makefile.am
@@ -0,0 +1,9 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/limits
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ filesystem_count.ksh \
+ filesystem_limit.ksh \
+ snapshot_count.ksh \
+ snapshot_limit.ksh
+
diff --git a/tests/zfs-tests/tests/functional/limits/cleanup.ksh b/tests/zfs-tests/tests/functional/limits/cleanup.ksh
new file mode 100755
index 000000000000..2a84ab4438b6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/limits/cleanup.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 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib
+
+cleanup_user_group
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/limits/filesystem_count.ksh b/tests/zfs-tests/tests/functional/limits/filesystem_count.ksh
new file mode 100755
index 000000000000..e9f839ca8ad4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/limits/filesystem_count.ksh
@@ -0,0 +1,123 @@
+#!/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:
+# ZFS 'filesystem_count' property is handled correctly by various actions
+#
+# STRATEGY:
+# 1. Verify 'zfs create' and 'zfs clone' increment 'filesystem_count' value
+# 2. Verify 'zfs destroy' decrements the value
+# 3. Verify 'zfs rename' updates counts across different hierarchies
+# 4. Verify 'zfs promote' preserves counts within different hierarchies
+# 5. Verify 'zfs receive' correct behaviour
+# 6. Verify 'zfs rollback' does not update 'filesystem_count' value
+# 7. Verify 'zfs diff' does not update 'filesystem_count' value
+#
+
+verify_runnable "both"
+
+function setup
+{
+ log_must zfs create "$DATASET_TEST"
+ log_must zfs create "$DATASET_UTIL"
+ # Set filesystem_limit just to activate the filesystem_count property
+ log_must zfs set filesystem_limit=100 "$DATASET_TEST"
+}
+
+function cleanup
+{
+ destroy_dataset "$DATASET_TEST" "-Rf"
+ destroy_dataset "$DATASET_UTIL" "-Rf"
+ rm -f $ZSTREAM
+}
+
+log_assert "Verify 'filesystem_count' is handled correctly by various actions"
+log_onexit cleanup
+
+DATASET_TEST="$TESTPOOL/$TESTFS/filesystem_count_test"
+DATASET_UTIL="$TESTPOOL/$TESTFS/filesystem_count_util"
+ZSTREAM="$TEST_BASE_DIR/filesystem_count.$$"
+
+# 1. Verify 'zfs create' and 'zfs clone' increment 'filesystem_count' value
+setup
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "0"
+log_must zfs create "$DATASET_TEST/create_clone"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "1"
+log_must zfs snapshot "$DATASET_TEST/create_clone@snap"
+log_must zfs clone "$DATASET_TEST/create_clone@snap" "$DATASET_TEST/clone"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "2"
+cleanup
+
+# 2. Verify 'zfs destroy' decrements the value
+setup
+log_must zfs create "$DATASET_TEST/destroy"
+log_must zfs destroy "$DATASET_TEST/destroy"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "0"
+cleanup
+
+# 3. Verify 'zfs rename' updates counts across different hierarchies
+setup
+log_must zfs create "$DATASET_TEST/rename"
+log_must zfs rename "$DATASET_TEST/rename" "$DATASET_UTIL/renamed"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "0"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_UTIL")" == "1"
+cleanup
+
+# 4. Verify 'zfs promote' preserves counts within different hierarchies
+setup
+log_must zfs create "$DATASET_UTIL/promote"
+log_must zfs snapshot "$DATASET_UTIL/promote@snap"
+log_must zfs clone "$DATASET_UTIL/promote@snap" "$DATASET_TEST/promoted"
+log_must zfs promote "$DATASET_TEST/promoted"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "1"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_UTIL")" == "1"
+cleanup
+
+# 5. Verify 'zfs receive' correct behaviour
+setup
+log_must zfs create "$DATASET_UTIL/send"
+log_must zfs snapshot "$DATASET_UTIL/send@snap1"
+log_must zfs snapshot "$DATASET_UTIL/send@snap2"
+log_must eval "zfs send $DATASET_UTIL/send@snap1 > $ZSTREAM"
+log_must eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "1"
+log_must eval "zfs send -i @snap1 $DATASET_UTIL/send@snap2 > $ZSTREAM"
+log_must eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "1"
+cleanup
+
+# 6. Verify 'zfs rollback' does not update 'filesystem_count' value
+setup
+log_must zfs create "$DATASET_TEST/rollback"
+log_must zfs snapshot "$DATASET_TEST/rollback@snap"
+log_must zfs rollback "$DATASET_TEST/rollback@snap"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "1"
+cleanup
+
+# 7. Verify 'zfs diff' does not update 'filesystem_count' value
+setup
+log_must zfs create "$DATASET_TEST/diff"
+log_must zfs snapshot "$DATASET_TEST/diff@snap1"
+log_must zfs snapshot "$DATASET_TEST/diff@snap2"
+log_must zfs diff "$DATASET_TEST/diff@snap1" "$DATASET_TEST/diff@snap2"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "1"
+log_must zfs diff "$DATASET_TEST/diff@snap2"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "1"
+
+log_pass "'filesystem_count' property is handled correctly"
diff --git a/tests/zfs-tests/tests/functional/limits/filesystem_limit.ksh b/tests/zfs-tests/tests/functional/limits/filesystem_limit.ksh
new file mode 100755
index 000000000000..fbfc141be3e3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/limits/filesystem_limit.ksh
@@ -0,0 +1,139 @@
+#!/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/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# ZFS 'filesystem_limit' is enforced when executing various actions
+# NOTE: the limit should *not* be enforced if the user is allowed to change it.
+#
+# STRATEGY:
+# 1. Verify 'zfs create' and 'zfs clone' cannot exceed the filesystem_limit
+# 2. Verify 'zfs rename' cannot move filesystems exceeding the limit
+# 3. Verify 'zfs receive' cannot exceed the limit
+#
+
+verify_runnable "both"
+
+#
+# The has_capability() function was first exported in the 4.10 Linux kernel
+# then backported to some LTS kernels. Prior to this change there was no
+# mechanism to perform the needed permission check. Therefore, this test
+# is expected to fail on older kernels and is skipped.
+#
+if is_linux; then
+ if [[ $(linux_version) -lt $(linux_version "4.10") ]]; then
+ log_unsupported "Requires has_capability() kernel function"
+ fi
+fi
+
+function setup
+{
+ # We can't delegate 'mount' privs under Linux: to avoid issues with
+ # commands that may need to (re)mount datasets we set mountpoint=none
+ if is_linux; then
+ log_must zfs create -o mountpoint=none "$DATASET_TEST"
+ log_must zfs create -o mountpoint=none "$DATASET_UTIL"
+ else
+ log_must zfs create "$DATASET_TEST"
+ log_must zfs create "$DATASET_UTIL"
+ fi
+ if is_freebsd; then
+ # Ensure our non-root user has the permission to create the
+ # mountpoints and mount the filesystems.
+ sysctl vfs.usermount=1
+ log_must chmod 777 $(get_prop mountpoint "$DATASET_TEST")
+ log_must chmod 777 $(get_prop mountpoint "$DATASET_UTIL")
+ fi
+ log_must zfs allow -d -l $STAFF1 'create,mount,rename,clone,receive' \
+ "$DATASET_TEST"
+ log_must zfs allow -d -l $STAFF1 'create,mount,rename,clone,receive' \
+ "$DATASET_UTIL"
+}
+
+function cleanup
+{
+ if is_freebsd; then
+ sysctl vfs.usermount=0
+ fi
+ destroy_dataset "$DATASET_TEST" "-Rf"
+ destroy_dataset "$DATASET_UTIL" "-Rf"
+ rm -f $ZSTREAM
+}
+
+log_assert "Verify 'filesystem_limit' is enforced executing various actions"
+log_onexit cleanup
+
+DATASET_TEST="$TESTPOOL/$TESTFS/filesystem_limit_test"
+DATASET_UTIL="$TESTPOOL/$TESTFS/filesystem_limit_util"
+ZSTREAM="$TEST_BASE_DIR/filesystem_limit.$$"
+
+# 1. Verify 'zfs create' and 'zfs clone' cannot exceed the filesystem_limit
+setup
+# NOTE: we allow 'canmount' to the non-root user so we can use 'log_must' with
+# 'user_run zfs create -o canmount=off' successfully
+log_must zfs allow -d -l $STAFF1 'canmount' "$DATASET_TEST"
+log_must zfs set filesystem_limit=1 "$DATASET_TEST"
+log_must user_run $STAFF1 zfs create -o canmount=off "$DATASET_TEST/create"
+log_mustnot user_run $STAFF1 zfs create -o canmount=off "$DATASET_TEST/create_exceed"
+log_mustnot datasetexists "$DATASET_TEST/create_exceed"
+log_must zfs set filesystem_limit=2 "$DATASET_TEST"
+log_must zfs snapshot "$DATASET_TEST/create@snap"
+log_must user_run $STAFF1 zfs clone -o canmount=off "$DATASET_TEST/create@snap" "$DATASET_TEST/clone"
+log_mustnot user_run $STAFF1 zfs clone -o canmount=off "$DATASET_TEST/create@snap" "$DATASET_TEST/clone_exceed"
+log_mustnot datasetexists "$DATASET_TEST/clone_exceed"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "2"
+# Verify filesystem_limit is *not* enforced for users allowed to change it
+log_must zfs create "$DATASET_TEST/create_notenforced_root"
+log_must zfs allow -l $STAFF1 'filesystem_limit' "$DATASET_TEST"
+log_must user_run $STAFF1 zfs create -o canmount=off "$DATASET_TEST/create_notenforced_user"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "4"
+cleanup
+
+# 2. Verify 'zfs rename' cannot move filesystems exceeding the limit
+setup
+log_must zfs set filesystem_limit=0 "$DATASET_UTIL"
+log_must zfs create "$DATASET_TEST/rename"
+log_mustnot user_run $STAFF1 zfs rename "$DATASET_TEST/rename" "$DATASET_UTIL/renamed"
+log_mustnot datasetexists "$DATASET_UTIL/renamed"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_UTIL")" == "0"
+# Verify filesystem_limit is *not* enforced for users allowed to change it
+log_must zfs rename "$DATASET_TEST/rename" "$DATASET_UTIL/renamed_notenforced_root"
+log_must zfs rename "$DATASET_UTIL/renamed_notenforced_root" "$DATASET_TEST/rename"
+log_must zfs allow -l $STAFF1 'filesystem_limit' "$DATASET_UTIL"
+log_must user_run $STAFF1 zfs rename "$DATASET_TEST/rename" "$DATASET_UTIL/renamed_notenforced_user"
+log_must datasetexists "$DATASET_UTIL/renamed_notenforced_user"
+cleanup
+
+# 3. Verify 'zfs receive' cannot exceed the limit
+setup
+log_must zfs set filesystem_limit=0 "$DATASET_TEST"
+log_must zfs create "$DATASET_UTIL/send"
+log_must zfs snapshot "$DATASET_UTIL/send@snap1"
+log_must eval "zfs send $DATASET_UTIL/send@snap1 > $ZSTREAM"
+log_mustnot user_run $STAFF1 eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_mustnot datasetexists "$DATASET_TEST/received"
+log_must test "$(get_prop 'filesystem_count' "$DATASET_TEST")" == "0"
+# Verify filesystem_limit is *not* enforced for users allowed to change it
+log_must eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must zfs destroy -r "$DATASET_TEST/received"
+log_must zfs allow -l $STAFF1 'filesystem_limit' "$DATASET_TEST"
+log_must user_run $STAFF1 eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must datasetexists "$DATASET_TEST/received"
+
+log_pass "'filesystem_limit' property is enforced"
diff --git a/tests/zfs-tests/tests/functional/limits/setup.ksh b/tests/zfs-tests/tests/functional/limits/setup.ksh
new file mode 100755
index 000000000000..94f3e7b4d47f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/limits/setup.ksh
@@ -0,0 +1,28 @@
+#!/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/delegate/delegate_common.kshlib
+
+DISK=${DISKS%% *}
+
+cleanup_user_group
+
+# Create staff group and user
+log_must add_group $STAFF_GROUP
+log_must add_user $STAFF_GROUP $STAFF1
+
+default_volume_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/limits/snapshot_count.ksh b/tests/zfs-tests/tests/functional/limits/snapshot_count.ksh
new file mode 100755
index 000000000000..ac4a47ddc74d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/limits/snapshot_count.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 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZFS 'snapshot_count' property is handled correctly by various actions
+#
+# STRATEGY:
+# 1. Verify 'zfs snapshot' increments 'snapshot_count' value
+# 2. Verify 'zfs destroy' decrements the value
+# 3. Verify 'zfs rename' updates counts across different hierarchies
+# 4. Verify 'zfs promote' updates counts across different hierarchies
+# 5. Verify 'zfs receive' correct behaviour
+#
+
+verify_runnable "both"
+
+function setup
+{
+ log_must zfs create "$DATASET_TEST"
+ log_must zfs create "$DATASET_UTIL"
+ # Set snapshot_limit just to activate the snapshot_count property
+ log_must zfs set snapshot_limit=100 "$DATASET_TEST"
+}
+
+function cleanup
+{
+ destroy_dataset "$DATASET_TEST" "-Rf"
+ destroy_dataset "$DATASET_UTIL" "-Rf"
+ rm -f $ZSTREAM
+}
+
+log_assert "Verify 'snapshot_count' is handled correctly by various actions"
+log_onexit cleanup
+
+DATASET_TEST="$TESTPOOL/$TESTFS/snapshot_count_test"
+DATASET_UTIL="$TESTPOOL/$TESTFS/snapshot_count_util"
+ZSTREAM="$TEST_BASE_DIR/snapshot_count.$$"
+
+# 1. Verify 'zfs snapshot' increments 'snapshot_count' value
+setup
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "0"
+log_must zfs snapshot "$DATASET_TEST@snap"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "1"
+cleanup
+
+# 2. Verify 'zfs destroy' decrements the value
+setup
+log_must zfs snapshot "$DATASET_TEST@snap"
+log_must zfs destroy "$DATASET_TEST@snap"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "0"
+cleanup
+
+# 3. Verify 'zfs rename' updates counts across different hierarchies
+setup
+log_must zfs create "$DATASET_TEST/renamed"
+log_must zfs snapshot "$DATASET_TEST/renamed@snap"
+log_must zfs rename "$DATASET_TEST/renamed" "$DATASET_UTIL/renamed"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "0"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_UTIL")" == "1"
+cleanup
+
+# 4. Verify 'zfs promote' updates counts across different hierarchies
+setup
+log_must zfs create "$DATASET_UTIL/promote"
+log_must zfs snapshot "$DATASET_UTIL/promote@snap"
+log_must zfs clone "$DATASET_UTIL/promote@snap" "$DATASET_TEST/promoted"
+log_must zfs promote "$DATASET_TEST/promoted"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "1"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_UTIL")" == "0"
+cleanup
+
+# 5. Verify 'zfs receive' correct behaviour
+setup
+log_must zfs create "$DATASET_UTIL/send"
+log_must zfs snapshot "$DATASET_UTIL/send@snap1"
+log_must zfs snapshot "$DATASET_UTIL/send@snap2"
+log_must eval "zfs send $DATASET_UTIL/send@snap1 > $ZSTREAM"
+log_must eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "1"
+log_must eval "zfs send -i @snap1 $DATASET_UTIL/send@snap2 > $ZSTREAM"
+log_must eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "2"
+
+log_pass "'snapshot_count' property is handled correctly"
diff --git a/tests/zfs-tests/tests/functional/limits/snapshot_limit.ksh b/tests/zfs-tests/tests/functional/limits/snapshot_limit.ksh
new file mode 100755
index 000000000000..62f14466e693
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/limits/snapshot_limit.ksh
@@ -0,0 +1,166 @@
+#!/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/delegate/delegate_common.kshlib
+
+#
+# DESCRIPTION:
+# ZFS 'snapshot_limit' is enforced when executing various actions
+# NOTE: the limit should *not* be enforced if the user is allowed to change it.
+#
+# STRATEGY:
+# 1. Verify 'zfs snapshot' cannot exceed the snapshot_limit
+# 2. Verify 'zfs rename' cannot move snapshots exceeding the limit
+# 3. Verify 'zfs promote' cannot exceed the limit
+# 4. Verify 'zfs receive' cannot exceed the limit
+#
+
+verify_runnable "both"
+
+#
+# The has_capability() function was first exported in the 4.10 Linux kernel
+# then backported to some LTS kernels. Prior to this change there was no
+# mechanism to perform the needed permission check. Therefore, this test
+# is expected to fail on older kernels and is skipped.
+#
+if is_linux; then
+ if [[ $(linux_version) -lt $(linux_version "4.10") ]]; then
+ log_unsupported "Requires has_capability() kernel function"
+ fi
+fi
+
+function setup
+{
+ # We can't delegate 'mount' privs under Linux: to avoid issues with
+ # commands that may need to (re)mount datasets we set mountpoint=none
+ if is_linux; then
+ log_must zfs create -o mountpoint=none "$DATASET_TEST"
+ log_must zfs create -o mountpoint=none "$DATASET_UTIL"
+ else
+ log_must zfs create "$DATASET_TEST"
+ log_must zfs create "$DATASET_UTIL"
+ fi
+ if is_freebsd; then
+ # Ensure our non-root user has the permission to create the
+ # mountpoints and mount the filesystems.
+ sysctl vfs.usermount=1
+ log_must chmod 777 $(get_prop mountpoint "$DATASET_TEST")
+ log_must chmod 777 $(get_prop mountpoint "$DATASET_UTIL")
+ fi
+ log_must zfs allow -d -l $STAFF1 \
+ 'create,snapshot,rename,mount,promote,receive' "$DATASET_TEST"
+ log_must zfs allow -d -l $STAFF1 \
+ 'create,snapshot,rename,mount,promote,receive' "$DATASET_UTIL"
+}
+
+function cleanup
+{
+ if is_freebsd; then
+ sysctl vfs.usermount=0
+ fi
+ destroy_dataset "$DATASET_TEST" "-Rf"
+ destroy_dataset "$DATASET_UTIL" "-Rf"
+ rm -f $ZSTREAM
+}
+
+log_assert "Verify 'snapshot_limit' is enforced when executing various actions"
+log_onexit cleanup
+
+DATASET_TEST="$TESTPOOL/$TESTFS/snapshot_limit_test"
+DATASET_UTIL="$TESTPOOL/$TESTFS/snapshot_limit_util"
+ZSTREAM="$TEST_BASE_DIR/snapshot_limit.$$"
+
+# 1. Verify 'zfs snapshot' cannot exceed the snapshot_limit
+setup
+log_must zfs set snapshot_limit=1 "$DATASET_TEST"
+log_must user_run $STAFF1 zfs snapshot "$DATASET_TEST@snap"
+log_mustnot user_run $STAFF1 zfs snapshot "$DATASET_TEST@snap_exceed"
+log_mustnot datasetexists "$DATASET_TEST@snap_exceed"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "1"
+# Verify snapshot_limit is *not* enforced for users allowed to change it
+log_must zfs snapshot "$DATASET_TEST@snap_notenforced_root"
+log_must zfs allow -l $STAFF1 'snapshot_limit' "$DATASET_TEST"
+log_must user_run $STAFF1 zfs snapshot "$DATASET_TEST@snap_notenforced_user"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "3"
+cleanup
+
+# 2. Verify 'zfs rename' cannot move snapshots exceeding the limit
+setup
+log_must zfs set snapshot_limit=0 "$DATASET_UTIL"
+log_must zfs create "$DATASET_TEST/rename"
+log_must zfs snapshot "$DATASET_TEST/rename@snap"
+log_mustnot user_run $STAFF1 \
+ zfs rename "$DATASET_TEST/rename" "$DATASET_UTIL/renamed"
+log_mustnot datasetexists "$DATASET_UTIL/renamed"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_UTIL")" == "0"
+# Verify snapshot_limit is *not* enforced for users allowed to change it
+log_must zfs rename "$DATASET_TEST/rename" \
+ "$DATASET_UTIL/renamed_notenforced_root"
+log_must zfs create "$DATASET_TEST/rename"
+log_must zfs snapshot "$DATASET_TEST/rename@snap"
+log_must zfs allow -l $STAFF1 'snapshot_limit' "$DATASET_UTIL"
+log_must user_run $STAFF1 \
+ zfs rename "$DATASET_TEST/rename" "$DATASET_UTIL/renamed_notenforced_user"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_UTIL")" == "2"
+cleanup
+
+# 3. Verify 'zfs promote' cannot exceed the limit
+setup
+log_must zfs set snapshot_limit=0 "$DATASET_UTIL"
+log_must zfs create "$DATASET_TEST/promote"
+log_must zfs snapshot "$DATASET_TEST/promote@snap"
+log_must zfs clone "$DATASET_TEST/promote@snap" "$DATASET_UTIL/promoted"
+log_mustnot user_run $STAFF1 zfs promote "$DATASET_UTIL/promoted"
+log_mustnot datasetexists "$DATASET_UTIL/promoted@snap"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_UTIL")" == "0"
+# Verify snapshot_limit is *not* enforced for users allowed to change it
+log_must zfs promote "$DATASET_UTIL/promoted"
+log_must zfs promote "$DATASET_TEST/promote"
+log_must zfs allow -l $STAFF1 'snapshot_limit' "$DATASET_UTIL"
+log_must user_run $STAFF1 zfs promote "$DATASET_UTIL/promoted"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_UTIL")" == "1"
+cleanup
+
+# 4. Verify 'zfs receive' cannot exceed the limit
+setup
+log_must zfs set snapshot_limit=0 "$DATASET_TEST"
+log_must zfs create "$DATASET_UTIL/send"
+log_must zfs snapshot "$DATASET_UTIL/send@snap1"
+log_must eval "zfs send $DATASET_UTIL/send@snap1 > $ZSTREAM"
+log_mustnot user_run $STAFF1 \
+ eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_mustnot datasetexists "$DATASET_TEST/received"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "0"
+log_must zfs set snapshot_limit=1 "$DATASET_TEST"
+log_must user_run $STAFF1 \
+ eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must zfs snapshot "$DATASET_UTIL/send@snap2"
+log_must eval "zfs send -i @snap1 $DATASET_UTIL/send@snap2 > $ZSTREAM"
+log_mustnot user_run $STAFF1 \
+ eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_mustnot datasetexists "$DATASET_TEST/received@snap2"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "1"
+# Verify snapshot_limit is *not* enforced for users allowed to change it
+log_must eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must zfs snapshot "$DATASET_UTIL/send@snap3"
+log_must eval "zfs send -i @snap2 $DATASET_UTIL/send@snap3 > $ZSTREAM"
+log_must zfs allow -l $STAFF1 'snapshot_limit' "$DATASET_TEST"
+log_must user_run $STAFF1 \
+ eval "zfs receive $DATASET_TEST/received < $ZSTREAM"
+log_must test "$(get_prop 'snapshot_count' "$DATASET_TEST")" == "3"
+
+log_pass "'snapshot_limit' property is enforced"
diff --git a/tests/zfs-tests/tests/functional/link_count/Makefile.am b/tests/zfs-tests/tests/functional/link_count/Makefile.am
new file mode 100644
index 000000000000..bfb7154a6518
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/link_count/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/link_count
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ link_count_001.ksh \
+ link_count_root_inode.ksh
diff --git a/tests/zfs-tests/tests/functional/link_count/cleanup.ksh b/tests/zfs-tests/tests/functional/link_count/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/link_count/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/link_count/link_count_001.ksh b/tests/zfs-tests/tests/functional/link_count/link_count_001.ksh
new file mode 100755
index 000000000000..3ab3fbef8df8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/link_count/link_count_001.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify file link count is zero on zfs
+#
+# STRATEGY:
+# 1. Make sure this test executes on multi-processes system
+# 2. Make zero size files and remove them in the background
+# 3. Call the binary
+# 4. Make sure the files can be removed successfully
+#
+
+verify_runnable "both"
+
+log_assert "Verify file link count is zero on zfs"
+
+export ITERS=10
+export NUMFILES=10000
+
+if is_freebsd; then
+ log_unsupported "Not applicable on FreeBSD"
+fi
+
+# Detect and make sure this test must be executed on a multi-process system
+if ! is_mp; then
+ log_unsupported "This test requires a multi-processor system."
+fi
+
+log_must mkdir -p ${TESTDIR}/tmp
+
+typeset -i i=0
+while [ $i -lt $NUMFILES ]; do
+ (( i = i + 1 ))
+ touch ${TESTDIR}/tmp/x$i > /dev/null 2>&1
+done
+
+sleep 3
+
+rm -f ${TESTDIR}/tmp/x* >/dev/null 2>&1
+
+rm_lnkcnt_zero_file ${TESTDIR}/tmp/test$$ > /dev/null 2>&1 &
+PID=$!
+log_note "rm_lnkcnt_zero_file ${TESTDIR}/tmp/test$$ pid: $PID"
+
+i=0
+while [ $i -lt $ITERS ]; do
+ if ! pgrep rm_lnkcnt_zero_file > /dev/null ; then
+ log_note "rm_lnkcnt_zero_file completes"
+ break
+ fi
+ log_must sleep 10
+ (( i = i + 1 ))
+done
+
+if pgrep rm_lnkcnt_zero_file > /dev/null; then
+ log_must kill -TERM $PID
+ log_fail "file link count is zero"
+fi
+
+log_must kill -TERM $PID
+log_must rm -f ${TESTDIR}/tmp/test$$*
+
+log_pass "Verify file link count is zero on zfs"
diff --git a/tests/zfs-tests/tests/functional/link_count/link_count_root_inode.ksh b/tests/zfs-tests/tests/functional/link_count/link_count_root_inode.ksh
new file mode 100755
index 000000000000..d2bf30ac37c2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/link_count/link_count_root_inode.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 Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify root inode (directory) has correct link count.
+#
+# STRATEGY:
+# 1. Create pool and fs.
+# 2. Test link count of root inode.
+# 3. Create directories and test link count of root inode.
+# 4. Delete directories and test link count of root inode.
+# 5. Create regular file and test link count of root inode.
+# 6. Delete regular file and test link count of root inode.
+#
+
+function assert_link_count
+{
+ typeset dirpath="$1"
+ typeset value="$2"
+
+ log_must test "$(ls -ld $dirpath | awk '{ print $2 }')" == "$value"
+}
+
+verify_runnable "both"
+
+log_note "Verify root inode (directory) has correct link count."
+
+# Delete a directory from link_count_001.ksh.
+if [ -d "${TESTDIR}" -a -d "${TESTDIR}/tmp" ]; then
+ log_must rm -rf ${TESTDIR}/tmp
+fi
+
+#
+# Test with hidden '.zfs' directory.
+# This also tests general directories.
+#
+log_note "Testing with snapdir set to hidden (default)"
+
+for dst in $TESTPOOL $TESTPOOL/$TESTFS
+do
+ typeset mtpt=$(get_prop mountpoint $dst)
+ log_must zfs set snapdir=hidden $dst
+ log_must test -d "$mtpt/.zfs"
+ if test -n "$(ls $mtpt)"; then
+ ls $mtpt
+ log_note "$mtpt not empty, skipping"
+ continue
+ fi
+ assert_link_count $mtpt 2
+
+ log_must mkdir $mtpt/a
+ assert_link_count $mtpt 3
+ log_must rmdir $mtpt/a
+ assert_link_count $mtpt 2
+
+ log_must mkdir -p $mtpt/a/b
+ assert_link_count $mtpt 3
+ log_must rmdir $mtpt/a/b
+ log_must rmdir $mtpt/a
+ assert_link_count $mtpt 2
+
+ log_must touch $mtpt/a
+ assert_link_count $mtpt 2
+ log_must rm $mtpt/a
+ assert_link_count $mtpt 2
+done
+
+#
+# Test with visible '.zfs' directory.
+#
+log_note "Testing with snapdir set to visible"
+
+for dst in $TESTPOOL $TESTPOOL/$TESTFS
+do
+ typeset mtpt=$(get_prop mountpoint $dst)
+ log_must zfs set snapdir=visible $dst
+ log_must test -d "$mtpt/.zfs"
+ if test -n "$(ls $mtpt)"; then
+ ls $mtpt
+ log_note "$mtpt not empty, skipping"
+ continue
+ fi
+ assert_link_count $mtpt 3
+
+ log_must mkdir $mtpt/a
+ assert_link_count $mtpt 4
+ log_must rmdir $mtpt/a
+ assert_link_count $mtpt 3
+
+ log_must mkdir -p $mtpt/a/b
+ assert_link_count $mtpt 4
+ log_must rmdir $mtpt/a/b
+ log_must rmdir $mtpt/a
+ assert_link_count $mtpt 3
+
+ log_must touch $mtpt/a
+ assert_link_count $mtpt 3
+ log_must rm $mtpt/a
+ assert_link_count $mtpt 3
+done
+
+log_pass "Verify root inode (directory) has correct link count passed"
diff --git a/tests/zfs-tests/tests/functional/link_count/setup.ksh b/tests/zfs-tests/tests/functional/link_count/setup.ksh
new file mode 100755
index 000000000000..d275e063b13a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/link_count/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/log_spacemap/Makefile.am b/tests/zfs-tests/tests/functional/log_spacemap/Makefile.am
new file mode 100644
index 000000000000..a1e523426c6a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/log_spacemap/Makefile.am
@@ -0,0 +1,2 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/log_spacemap
+dist_pkgdata_SCRIPTS = log_spacemap_import_logs.ksh
diff --git a/tests/zfs-tests/tests/functional/log_spacemap/log_spacemap_import_logs.ksh b/tests/zfs-tests/tests/functional/log_spacemap/log_spacemap_import_logs.ksh
new file mode 100755
index 000000000000..fca0e8e4a1b4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/log_spacemap/log_spacemap_import_logs.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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Log spacemaps are generally destroyed at export in order to
+# not induce performance overheads at import time. As a result,
+# the log spacemap codepaths that read the logs in import times
+# are not tested outside of ztest and pools with DEBUG bits doing
+# many imports/exports while running the test suite.
+#
+# This test uses an internal tunable and forces ZFS to keep the
+# log spacemaps at export, and then re-imports the pool, thus
+# providing explicit testing of those codepaths. It also uses
+# another tunable to load all the metaslabs when the pool is
+# re-imported so more assertions and verifications will be hit.
+#
+# STRATEGY:
+# 1. Create pool.
+# 2. Do a couple of writes to generate some data for spacemap logs.
+# 3. Set tunable to keep logs after export.
+# 4. Export pool and verify that there are logs with zdb.
+# 5. Set tunable to load all metaslabs at import.
+# 6. Import pool.
+# 7. Reset tunables.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 0
+ log_must set_tunable64 METASLAB_DEBUG_LOAD 0
+ if poolexists $LOGSM_POOL; then
+ log_must zpool destroy -f $LOGSM_POOL
+ fi
+}
+log_onexit cleanup
+
+LOGSM_POOL="logsm_import"
+TESTDISK="$(echo $DISKS | cut -d' ' -f1)"
+
+log_must zpool create -o cachefile=none -f $LOGSM_POOL $TESTDISK
+log_must zfs create $LOGSM_POOL/fs
+
+log_must dd if=/dev/urandom of=/$LOGSM_POOL/fs/00 bs=128k count=10
+log_must sync
+log_must dd if=/dev/urandom of=/$LOGSM_POOL/fs/00 bs=128k count=10
+log_must sync
+
+log_must set_tunable64 KEEP_LOG_SPACEMAPS_AT_EXPORT 1
+log_must zpool export $LOGSM_POOL
+
+LOGSM_COUNT=$(zdb -m -e $LOGSM_POOL | grep "Log Spacemap object" | wc -l)
+if (( LOGSM_COUNT == 0 )); then
+ log_fail "Pool does not have any log spacemaps after being exported"
+fi
+
+log_must set_tunable64 METASLAB_DEBUG_LOAD 1
+log_must zpool import $LOGSM_POOL
+
+log_pass "Log spacemaps imported with no errors"
diff --git a/tests/zfs-tests/tests/functional/migration/Makefile.am b/tests/zfs-tests/tests/functional/migration/Makefile.am
new file mode 100644
index 000000000000..9c4f244156ce
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/Makefile.am
@@ -0,0 +1,20 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/migration
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ migration_001_pos.ksh \
+ migration_002_pos.ksh \
+ migration_003_pos.ksh \
+ migration_004_pos.ksh \
+ migration_005_pos.ksh \
+ migration_006_pos.ksh \
+ migration_007_pos.ksh \
+ migration_008_pos.ksh \
+ migration_009_pos.ksh \
+ migration_010_pos.ksh \
+ migration_011_pos.ksh \
+ migration_012_pos.ksh
+
+dist_pkgdata_DATA = \
+ migration.cfg \
+ migration.kshlib
diff --git a/tests/zfs-tests/tests/functional/migration/cleanup.ksh b/tests/zfs-tests/tests/functional/migration/cleanup.ksh
new file mode 100755
index 000000000000..1a1f3f42731e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/cleanup.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 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/migration/migration.cfg
+
+verify_runnable "global"
+
+ismounted $NONZFS_TESTDIR $NEWFS_DEFAULT_FS
+(( $? == 0 )) && log_must umount -f $NONZFS_TESTDIR
+
+ismounted $TESTPOOL/$TESTFS
+[[ $? == 0 ]] && log_must zfs umount -f $TESTDIR
+destroy_pool $TESTPOOL
+
+DISK=${DISKS%% *}
+if is_mpath_device $DISK; then
+ delete_partitions
+fi
+
+# recreate and destroy a zpool over the disks to restore the partitions to
+# normal
+case $DISK_COUNT in
+0)
+ log_note "No disk devices to restore"
+ ;;
+1)
+ log_must cleanup_devices $ZFS_DISK
+ ;;
+*)
+ log_must cleanup_devices $ZFS_DISK $NONZFS_DISK
+ ;;
+esac
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/migration/migration.cfg b/tests/zfs-tests/tests/functional/migration/migration.cfg
new file mode 100644
index 000000000000..12a5a7799b7a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration.cfg
@@ -0,0 +1,110 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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
+
+export DISKSARRAY=$DISKS
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+set -A disk_array $(find_disks $DISKS)
+case "${#disk_array[*]}" in
+0)
+ DISK_COUNT=0
+ ;;
+1)
+ # We need to repartition the single disk to two slices.
+ DISK_COUNT=1
+ ZFS_DISK=${disk_array[0]}
+ SINGLE_DISK=$ZFS_DISK
+ NONZFS_DISK=$ZFS_DISK
+ if is_linux; then
+ if is_mpath_device $ZFS_DISK; then
+ export DEV_DSKDIR=$DEV_MPATHDIR
+ else
+ export DEV_DSKDIR=$DEV_RDSKDIR
+ fi
+ if ( is_mpath_device $ZFS_DISK ) && [[ -z $(echo $ZFS_DISK | awk 'substr($1,18,1)\
+ ~ /^[[:digit:]]+$/') ]] || ( is_real_device $ZFS_DISK ); then
+ ZFSSIDE_DISK=${SINGLE_DISK}1
+ NONZFSSIDE_DISK=${SINGLE_DISK}2
+ elif ( is_mpath_device $ZFS_DISK || is_loop_device $ZFS_DISK ); then
+ ZFSSIDE_DISK=${SINGLE_DISK}p1
+ NONZFSSIDE_DISK=${SINGLE_DISK}p2
+ else
+ log_fail "$ZFS_DISK not supported for partitioning."
+ fi
+ else
+ ZFSSIDE_DISK=${SINGLE_DISK}s0
+ NONZFSSIDE_DISK=${SINGLE_DISK}s1
+ fi
+ ;;
+*)
+ # In this case there are at least enough disks to use.
+ DISK_COUNT=2
+ ZFS_DISK=${disk_array[0]}
+ NONZFS_DISK=${disk_array[1]}
+ if is_linux; then
+ if is_mpath_device $ZFS_DISK; then
+ export DEV_DSKDIR=$DEV_MPATHDIR
+ else
+ export DEV_DSKDIR=$DEV_RDSKDIR
+ fi
+ if ( is_mpath_device $ZFS_DISK ) && [[ -z $(echo $ZFS_DISK | awk 'substr($1,18,1)\
+ ~ /^[[:digit:]]+$/') ]] || ( is_real_device $ZFS_DISK ); then
+ ZFSSIDE_DISK=${ZFS_DISK}1
+ elif ( is_mpath_device $ZFS_DISK || is_loop_device $ZFS_DISK ); then
+ ZFSSIDE_DISK=${ZFS_DISK}p1
+ else
+ log_fail "$ZFS_DISK not supported for partitioning."
+ fi
+ if ( is_mpath_device $NONZFS_DISK ) && [[ -z $(echo $NONZFS_DISK | awk 'substr($1,18,1)\
+ ~ /^[[:digit:]]+$/') ]] || ( is_real_device $NONZFS_DISK ); then
+ NONZFSSIDE_DISK=${NONZFS_DISK}1
+ elif ( is_mpath_device $NONZFS_DISK || is_loop_device $NONZFS_DISK ); then
+ NONZFSSIDE_DISK=${NONZFS_DISK}p1
+ else
+ log_fail "$NONZFS_DISK not supported for partitioning."
+ fi
+ else
+ ZFSSIDE_DISK=${ZFS_DISK}s0
+ NONZFSSIDE_DISK=${NONZFS_DISK}s0
+ fi
+ ;;
+esac
+
+export DISK_COUNT ZFS_DISK NONZFS_DISK SINGLE_DISK ZFSSIDE_DISK NONZFSSIDE_DISK
+
+export TESTFILE=/etc/passwd
+export NONZFS_TESTDIR=$TESTDIR/nonzfstestdir
+tmp=`sum $TESTFILE`
+export SUMA=`echo $tmp | awk '{print $1}'`
+export SUMB=`echo $tmp | awk '{print $2}'`
+export FS_SIZE=1g
+export BNAME=`basename $TESTFILE`
+export DNAME=`dirname $TESTFILE`
diff --git a/tests/zfs-tests/tests/functional/migration/migration.kshlib b/tests/zfs-tests/tests/functional/migration/migration.kshlib
new file mode 100644
index 000000000000..a2b4ed99b11e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration.kshlib
@@ -0,0 +1,153 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/migration/migration.cfg
+
+#
+# This function creates the test archive for migration.
+#
+# Usage:
+# prepare srcdir cmd
+#
+# Return value: 0 on success
+# 1 on failure
+#
+# Where:
+# srcdir: is the directory where the testfile is
+# cmd: is the command to be executed.
+# E.g.
+# tar cf $TESTDIR/tar$$.tar
+#
+function prepare #srcdir cmd
+{
+ typeset srcdir=$1
+ typeset cmd=$2
+ typeset -i retval=0
+
+ cwd=$PWD
+ cd $srcdir
+ (( $? != 0 )) && return 1
+
+ $cmd
+ (( $? != 0 )) && return 1
+
+ cd $cwd
+ (( $? != 0 )) && return 1
+
+ return 0
+}
+
+#
+# This function executes a passed in command and then determines the chksum
+# of the resulting file. The chksum components are checked against the ones
+# passed in to determine if they are equal. If they are equal, 0 is returned
+# otherwise 1 is returned.
+#
+# Usage:
+# migrate destdir oldsuma oldsumb command_to_execute
+#
+# Return value: 0 on success
+# 1 on failure
+#
+# Where:
+# destdir: is the directory where the command is to be executed on
+# oldsuma: is the first part of the values returned by sum
+# oldsumb: is the second part of the values returned by sum
+# cmd: is the command to be executed;
+# E.g.
+# "tar xf $TESTDIR/tar$$.tar"
+#
+function migrate #destdir oldsuma oldsumb cmd
+{
+ typeset destdir=$1
+ typeset oldsuma=$2
+ typeset oldsumb=$3
+ typeset cmd=$4
+ typeset -i retval=0
+
+ cwd=$PWD
+ cd $destdir
+ (( $? != 0 )) && return 1
+
+ $cmd
+ (( $? != 0 )) && return 1
+
+ sumy=`sum ./$BNAME`
+ suma=`echo $sumy | awk '{print $1}'`
+ sumb=`echo $sumy | awk '{print $2}'`
+
+ if (( $oldsuma != $suma )); then
+ log_note "sum values are not the same"
+ retval=1
+ fi
+
+ if (( $oldsumb != $sumb )); then
+ log_note "sum values are not the same"
+ retval=1
+ fi
+
+ cd $cwd
+ (( $? != 0 )) && return 1
+ return $retval
+}
+
+function migrate_cpio
+{
+ typeset destdir=$1
+ typeset archive=$2
+ typeset oldsuma=$3
+ typeset oldsumb=$4
+ typeset -i retval=0
+
+ cwd=$PWD
+ cd $destdir
+ (( $? != 0 )) && return 1
+
+ cpio -iv < $archive
+ (( $? != 0 )) && return 1
+
+ sumy=`sum ./$BNAME`
+ suma=`echo $sumy | awk '{print $1}'`
+ sumb=`echo $sumy | awk '{print $2}'`
+
+ if (( $oldsuma != $suma )); then
+ log_note "sum values are not the same"
+ retval=1
+ fi
+
+ if (( $oldsumb != $sumb )); then
+ log_note "sum values are not the same"
+ retval=1
+ fi
+
+ cd $cwd
+ (( $? != 0 )) && return 1
+ return $retval
+}
diff --git a/tests/zfs-tests/tests/functional/migration/migration_001_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_001_pos.ksh
new file mode 100755
index 000000000000..875d2f7c78be
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from ZFS fs to ZFS fs using tar.
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Tar up test file and place on a ZFS filesystem
+# 3. Extract tar contents to a ZFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/tar$$.tar
+ rm -rf $TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from ZFS fs to ZFS fs using tar"
+
+log_onexit cleanup
+
+prepare $DNAME "tar cf $TESTDIR/tar$$.tar $BNAME"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $TESTDIR $SUMA $SUMB "tar xf $TESTDIR/tar$$.tar"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from ZFS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_002_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_002_pos.ksh
new file mode 100755
index 000000000000..6b97e2a4071b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from ZFS fs to UFS fs using tar.
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Tar up test file and place on a ZFS filesystem
+# 3. Extract tar contents to a UFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/tar$$.tar
+ rm -rf $NONZFS_TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from ZFS fs to UFS fs using tar"
+
+log_onexit cleanup
+
+prepare $DNAME "tar cf $TESTDIR/tar$$.tar $BNAME"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $NONZFS_TESTDIR $SUMA $SUMB "tar xf $TESTDIR/tar$$.tar"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to UFS fs"
+
+log_pass "Successfully migrated test file from ZFS fs to UFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_003_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_003_pos.ksh
new file mode 100755
index 000000000000..dd0baeaa9b78
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_003_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from UFS fs to ZFS fs using tar.
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Tar up test file and place on a UFS filesystem
+# 3. Extract tar contents to a ZFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $NONZFS_TESTDIR/tar$$.tar
+ rm -rf $TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from UFS fs to ZFS fs using tar"
+
+log_onexit cleanup
+
+prepare $DNAME "tar cf $NONZFS_TESTDIR/tar$$.tar $BNAME"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $TESTDIR $SUMA $SUMB "tar xvf $NONZFS_TESTDIR/tar$$.tar"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "UFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from UFS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_004_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_004_pos.ksh
new file mode 100755
index 000000000000..00a6cc172ab6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_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 2007 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/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from ZFS fs to ZFS fs using cpio
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Cpio up test file and place on a ZFS filesystem
+# 3. Extract cpio contents to a ZFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/cpio$$.cpio
+ rm -rf $TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from ZFS fs to ZFS fs using cpio"
+
+log_onexit cleanup
+
+cwd=$PWD
+cd $DNAME
+(( $? != 0 )) && log_untested "Could not change directory to $DNAME"
+
+ls $BNAME | cpio -oc > $TESTDIR/cpio$$.cpio
+(( $? != 0 )) && log_fail "Unable to create cpio archive"
+
+cd $cwd
+(( $? != 0 )) && log_untested "Could not change directory to $cwd"
+
+migrate_cpio $TESTDIR "$TESTDIR/cpio$$.cpio" $SUMA $SUMB
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from ZFS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_005_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_005_pos.ksh
new file mode 100755
index 000000000000..4386596f777d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from ZFS fs to UFS fs using cpio
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Cpio up test file and place on a ZFS filesystem
+# 3. Extract cpio contents to a UFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/cpio$$.cpio
+ rm -rf $NONZFS_TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from ZFS fs to uFS fs using cpio"
+
+log_onexit cleanup
+
+cwd=$PWD
+cd $DNAME
+(( $? != 0 )) && log_untested "Could not change directory to $DNAME"
+
+ls $BNAME | cpio -oc > $TESTDIR/cpio$$.cpio
+(( $? != 0 )) && log_fail "Unable to create cpio archive"
+
+cd $cwd
+(( $? != 0 )) && log_untested "Could not change directory to $cwd"
+
+migrate_cpio $NONZFS_TESTDIR "$TESTDIR/cpio$$.cpio" $SUMA $SUMB
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to UFS fs"
+
+log_pass "Successfully migrated test file from ZFS fs to UFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_006_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_006_pos.ksh
new file mode 100755
index 000000000000..9b5c9166ed97
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_006_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from UFS fs to ZFS fs using cpio
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Cpio up test file and place on a UFS filesystem
+# 3. Extract cpio contents to a ZFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $NONZFS_TESTDIR/cpio$$.cpio
+ rm -rf $TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from UFS fs to ZFS fs using cpio"
+
+log_onexit cleanup
+
+cwd=$PWD
+cd $DNAME
+(( $? != 0 )) && log_untested "Could not change directory to $DNAME"
+
+ls $BNAME | cpio -oc > $NONZFS_TESTDIR/cpio$$.cpio
+(( $? != 0 )) && log_fail "Unable to create cpio archive"
+
+cd $cwd
+(( $? != 0 )) && log_untested "Could not change directory to $cwd"
+
+migrate_cpio $TESTDIR "$NONZFS_TESTDIR/cpio$$.cpio" $SUMA $SUMB
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from UFS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_007_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_007_pos.ksh
new file mode 100755
index 000000000000..0d136550f740
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_007_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from ZFS fs to ZFS fs using dd.
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Dd up test file and place on a ZFS filesystem
+# 3. Extract dd contents to a ZFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/dd$$.dd
+ rm -rf $TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from ZFS fs to ZFS fs using dd"
+
+log_onexit cleanup
+
+prepare $DNAME "dd if=$BNAME obs=128k of=$TESTDIR/dd$$.dd"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $TESTDIR $SUMA $SUMB "dd if=$TESTDIR/dd$$.dd obs=128k of=$BNAME"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from ZFS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_008_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_008_pos.ksh
new file mode 100755
index 000000000000..f62b1f33a3e5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_008_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from ZFS fs to UFS fs using dd.
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Dd up test file and place on a ZFS filesystem
+# 3. Extract dd contents to a UFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/dd$$.dd
+ rm -rf $NONZFS_TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from ZFS fs to UFS fs using dd"
+
+log_onexit cleanup
+
+prepare $DNAME "dd if=$BNAME obs=128k of=$TESTDIR/dd$$.dd"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $NONZFS_TESTDIR $SUMA $SUMB "dd if=$TESTDIR/dd$$.dd obs=128k of=$BNAME"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from ZFS fs to UFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_009_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_009_pos.ksh
new file mode 100755
index 000000000000..907be39eb4dd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_009_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from UFS fs to ZFS fs using dd.
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. Dd up test file and place on a UFS filesystem
+# 3. Extract dd contents to a ZFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/dd$$.dd
+ rm -rf $NONZFS_TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from UFS fs to ZFS fs using dd"
+
+log_onexit cleanup
+
+prepare $DNAME "dd if=$BNAME obs=128k of=$NONZFS_TESTDIR/dd$$.dd"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $TESTDIR $SUMA $SUMB "dd if=$NONZFS_TESTDIR/dd$$.dd obs=128k of=$BNAME"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from UFS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_010_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_010_pos.ksh
new file mode 100755
index 000000000000..e80dd67cdc21
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_010_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from ZFS fs to ZFS fs using cp
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. CP up test file and place on a ZFS filesystem
+# 3. Extract cp contents to a ZFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/cp$$.cp
+ rm -rf $TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from ZFS fs to ZFS fs using cp"
+
+log_onexit cleanup
+
+prepare $DNAME "cp $BNAME $TESTDIR/cp$$.cp"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $TESTDIR $SUMA $SUMB "cp $TESTDIR/cp$$.cp $BNAME"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from ZFS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_011_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_011_pos.ksh
new file mode 100755
index 000000000000..2d7ecb45eadb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_011_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from ZFS fs to UFS fs using cp
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. CP up test file and place on a ZFS filesystem
+# 3. Extract cp contents to a UFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $NONZFS_TESTDIR/cp$$.cp
+ rm -rf $TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from ZFS fs to UFS fs using cp"
+
+log_onexit cleanup
+
+prepare $DNAME "cp $BNAME $TESTDIR/cp$$.cp"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $NONZFS_TESTDIR $SUMA $SUMB "cp $TESTDIR/cp$$.cp $BNAME"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "ZFS fs to UFS fs"
+
+log_pass "Successfully migrated test file from ZFS fs to UFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/migration_012_pos.ksh b/tests/zfs-tests/tests/functional/migration/migration_012_pos.ksh
new file mode 100755
index 000000000000..fd9c4549164a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/migration_012_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.kshlib
+
+#
+# DESCRIPTION:
+# Migrating test file from UFS fs to ZFS fs using cp
+#
+# STRATEGY:
+# 1. Calculate chksum of testfile
+# 2. CP up test file and place on a UFS filesystem
+# 3. Extract cp contents to a ZFS file system
+# 4. Calculate chksum of extracted file
+# 5. Compare old and new chksums.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -rf $TESTDIR/cp$$.cp
+ rm -rf $NONZFS_TESTDIR/$BNAME
+}
+
+log_assert "Migrating test file from UFS fs to ZFS fs using cp"
+
+log_onexit cleanup
+
+prepare $DNAME "cp $BNAME $NONZFS_TESTDIR/cp$$.cp"
+(( $? != 0 )) && log_fail "Unable to create src archive"
+
+migrate $TESTDIR $SUMA $SUMB "cp $NONZFS_TESTDIR/cp$$.cp $BNAME"
+(( $? != 0 )) && log_fail "Unable to successfully migrate test file from" \
+ "UFS fs to ZFS fs"
+
+log_pass "Successfully migrated test file from UFS fs to ZFS fs".
diff --git a/tests/zfs-tests/tests/functional/migration/setup.ksh b/tests/zfs-tests/tests/functional/migration/setup.ksh
new file mode 100755
index 000000000000..58edc0a9291d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/migration/setup.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/migration/migration.cfg
+
+verify_runnable "global"
+
+case $DISK_COUNT in
+0)
+ log_untested "Need at least 1 disk device for test"
+ ;;
+1)
+ log_note "Partitioning a single disk ($SINGLE_DISK)"
+ ;;
+*)
+ log_note "Partitioning disks ($ZFS_DISK $NONZFS_DISK)"
+ ;;
+esac
+
+create_pool $TESTPOOL "$ZFS_DISK"
+
+rm -rf $TESTDIR || log_unresolved Could not remove $TESTDIR
+mkdir -p $TESTDIR || log_unresolved Could not create $TESTDIR
+
+log_must zfs create $TESTPOOL/$TESTFS
+log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+rm -rf $NONZFS_TESTDIR || log_unresolved Could not remove $NONZFS_TESTDIR
+mkdir -p $NONZFS_TESTDIR || log_unresolved Could not create $NONZFS_TESTDIR
+
+new_fs ${DEV_DSKDIR}/$NONZFS_DISK
+(( $? != 0 )) &&
+ log_untested "Unable to setup a $NEWFS_DEFAULT_FS file system"
+
+log_must mount ${DEV_DSKDIR}/$NONZFS_DISK $NONZFS_TESTDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/mmap/Makefile.am b/tests/zfs-tests/tests/functional/mmap/Makefile.am
new file mode 100644
index 000000000000..2adc398b8c09
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmap/Makefile.am
@@ -0,0 +1,10 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/mmap
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ mmap_read_001_pos.ksh \
+ mmap_write_001_pos.ksh \
+ mmap_libaio_001_pos.ksh
+
+dist_pkgdata_DATA = \
+ mmap.cfg
diff --git a/tests/zfs-tests/tests/functional/mmap/cleanup.ksh b/tests/zfs-tests/tests/functional/mmap/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmap/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap.cfg b/tests/zfs-tests/tests/functional/mmap/mmap.cfg
new file mode 100644
index 000000000000..1501c0463015
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmap/mmap.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/mmap/mmap_libaio_001_pos.ksh b/tests/zfs-tests/tests/functional/mmap/mmap_libaio_001_pos.ksh
new file mode 100755
index 000000000000..36a7e76f9f3d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmap/mmap_libaio_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 2018 Canonical. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmap/mmap.cfg
+
+#
+# DESCRIPTION:
+# Verify libaio functions correctly with mmap()'d files.
+#
+# STRATEGY:
+# 1. Call mmap_libaio binary
+# 2. Verify the file exists and is the expected size
+# 3. Verify the filesystem is intact and not hung in any way
+#
+
+verify_runnable "global"
+
+log_assert "verify mmap'd pages work with libaio"
+
+# mmap_libaio is built when the libaio-devel package is installed.
+if ! which mmap_libaio; then
+ log_unsupported "This test requires mmap_libaio."
+fi
+
+log_must chmod 777 $TESTDIR
+
+for size in 512 4096 8192; do
+ log_mustnot stat $TESTDIR/test-libaio-file
+ log_must mmap_libaio $TESTDIR/test-libaio-file $size
+ log_must verify_eq $(stat --format=%s $TESTDIR/test-libaio-file) $size
+ log_must rm $TESTDIR/test-libaio-file
+done
+
+typeset dir=$(get_device_dir $DISKS)
+verify_filesys "$TESTPOOL" "$TESTPOOL/$TESTFS" "$dir"
+
+log_pass "mmap'd pages work with libaio"
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap_read_001_pos.ksh b/tests/zfs-tests/tests/functional/mmap/mmap_read_001_pos.ksh
new file mode 100755
index 000000000000..470f10d937bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmap/mmap_read_001_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 2009 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/mmap/mmap.cfg
+
+#
+# DESCRIPTION:
+# read()s from mmap()'ed file contain correct data.
+#
+# STRATEGY:
+# 1. Create a pool & dataset
+# 2. Call readmmap binary
+# 3. unmount this file system
+# 4. Verify the integrity of this pool & dataset
+#
+
+verify_runnable "global"
+
+log_assert "read()s from mmap()'ed file contain correct data."
+
+log_must chmod 777 $TESTDIR
+log_must readmmap $TESTDIR/test-read-file
+log_must zfs unmount $TESTPOOL/$TESTFS
+
+typeset dir=$(get_device_dir $DISKS)
+verify_filesys "$TESTPOOL" "$TESTPOOL/$TESTFS" "$dir"
+
+log_pass "read(2) calls from a mmap(2)'ed file succeeded."
diff --git a/tests/zfs-tests/tests/functional/mmap/mmap_write_001_pos.ksh b/tests/zfs-tests/tests/functional/mmap/mmap_write_001_pos.ksh
new file mode 100755
index 000000000000..2f4257993d4a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmap/mmap_write_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Writing to a file and mmapping that file at the
+# same time does not result in a deadlock.
+#
+# STRATEGY:
+# 1. Make sure this test executes on multi-processes system.
+# 2. Call mmapwrite binary.
+# 3. wait 30s and make sure the test file existed.
+#
+
+verify_runnable "both"
+
+log_assert "write()s to a file and mmap() that file at the same time does not "\
+ "result in a deadlock."
+
+# Detect and make sure this test must be executed on a multi-process system
+if ! is_mp; then
+ log_unsupported "This test requires a multi-processor system."
+fi
+
+log_must chmod 777 $TESTDIR
+mmapwrite $TESTDIR/normal_write_file $TESTDIR/map_write_file &
+PID_MMAPWRITE=$!
+log_note "mmapwrite $TESTDIR/normal_write_file $TESTDIR/map_write_file"\
+ "pid: $PID_MMAPWRITE"
+log_must sleep 30
+
+log_must kill -9 $PID_MMAPWRITE
+log_must ls -l $TESTDIR/normal_write_file
+log_must ls -l $TESTDIR/map_write_file
+
+log_pass "write(2) a mmap(2)'ing file succeeded."
diff --git a/tests/zfs-tests/tests/functional/mmap/setup.ksh b/tests/zfs-tests/tests/functional/mmap/setup.ksh
new file mode 100755
index 000000000000..d275e063b13a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmap/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/mmp/Makefile.am b/tests/zfs-tests/tests/functional/mmp/Makefile.am
new file mode 100644
index 000000000000..2848fd4ce692
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/Makefile.am
@@ -0,0 +1,21 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/mmp
+dist_pkgdata_SCRIPTS = \
+ multihost_history.ksh \
+ mmp_on_thread.ksh \
+ mmp_on_uberblocks.ksh \
+ mmp_on_off.ksh \
+ mmp_interval.ksh \
+ mmp_active_import.ksh \
+ mmp_inactive_import.ksh \
+ mmp_exported_import.ksh \
+ mmp_write_uberblocks.ksh \
+ mmp_reset_interval.ksh \
+ mmp_on_zdb.ksh \
+ mmp_write_distribution.ksh \
+ mmp_hostid.ksh \
+ setup.ksh \
+ cleanup.ksh
+
+dist_pkgdata_DATA = \
+ mmp.kshlib \
+ mmp.cfg
diff --git a/tests/zfs-tests/tests/functional/mmp/cleanup.ksh b/tests/zfs-tests/tests/functional/mmp/cleanup.ksh
new file mode 100755
index 000000000000..b41d6ccbeb7c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/cleanup.ksh
@@ -0,0 +1,28 @@
+#!/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 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+
+verify_runnable "global"
+
+log_must set_tunable64 MULTIHOST_HISTORY $MMP_HISTORY_OFF
+
+log_pass "mmp cleanup passed"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp.cfg b/tests/zfs-tests/tests/functional/mmp/mmp.cfg
new file mode 100644
index 000000000000..9f7e76e27018
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp.cfg
@@ -0,0 +1,46 @@
+#
+# 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 Lawrence Livermore National Security, LLC.
+#
+
+export PREV_UBER="$TEST_BASE_DIR/mmp-uber-prev.txt"
+export CURR_UBER="$TEST_BASE_DIR/mmp-uber-curr.txt"
+export DISK=${DISKS%% *}
+
+export HOSTID_FILE="/etc/hostid"
+export HOSTID1=01234567
+export HOSTID2=89abcdef
+
+export TXG_TIMEOUT_LONG=5000
+export TXG_TIMEOUT_DEFAULT=5
+
+export MMP_POOL=mmppool
+export MMP_DIR=$TEST_BASE_DIR/mmp
+export MMP_CACHE=$MMP_DIR/zpool.cache
+export MMP_ZTEST_LOG=$MMP_DIR/ztest.log
+export MMP_HISTORY=100
+export MMP_HISTORY_OFF=0
+
+export MMP_INTERVAL_HOUR=$((60*60*1000))
+export MMP_INTERVAL_DEFAULT=1000
+export MMP_INTERVAL_MIN=100
+
+export MMP_IMPORT_INTERVALS=20
+export MMP_FAIL_INTERVALS_DEFAULT=10
+export MMP_FAIL_INTERVALS_MIN=2
+
+export MMP_TEST_DURATION_DEFAULT=$((MMP_IMPORT_INTERVALS*MMP_INTERVAL_DEFAULT/1000))
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp.kshlib b/tests/zfs-tests/tests/functional/mmp/mmp.kshlib
new file mode 100644
index 000000000000..661cbf3a52e7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp.kshlib
@@ -0,0 +1,333 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+
+
+function check_pool_import # pool opts token keyword
+{
+ typeset pool=${1:-$MMP_POOL}
+ typeset opts=$2
+ typeset token=$3
+ typeset keyword=$4
+
+ zpool import $opts 2>&1 | \
+ nawk -v token="$token:" '($1==token) {print $0}' | \
+ grep -i "$keyword" > /dev/null 2>&1
+
+ return $?
+}
+
+function is_pool_imported # pool opts
+{
+ typeset pool=${1:-$MMP_POOL}
+ typeset opts=$2
+
+ check_pool_import "$pool" "$opts" "status" \
+ "The pool is currently imported"
+ return $?
+}
+
+function wait_pool_imported # pool opts
+{
+ typeset pool=${1:-$MMP_POOL}
+ typeset opts=$2
+
+ while is_pool_imported "$pool" "$opts"; do
+ log_must sleep 5
+ done
+
+ return 0
+}
+
+function try_pool_import # pool opts message
+{
+ typeset pool=${1:-$MMP_POOL}
+ typeset opts=$2
+ typeset msg=$3
+
+ zpool import $opts $pool 2>&1 | grep -i "$msg"
+
+ return $?
+}
+
+function mmp_set_hostid
+{
+ typeset hostid=$1
+
+ zgenhostid $1
+
+ if [ $(hostid) != "$hostid" ]; then
+ return 1
+ fi
+
+ return 0
+}
+
+function mmp_clear_hostid
+{
+ rm -f $HOSTID_FILE
+}
+
+function mmp_pool_create_simple # pool dir
+{
+ typeset pool=${1:-$MMP_POOL}
+ typeset dir=${2:-$MMP_DIR}
+
+ log_must mkdir -p $dir
+ log_must rm -f $dir/*
+ log_must truncate -s $MINVDEVSIZE $dir/vdev1 $dir/vdev2
+
+ log_must mmp_clear_hostid
+ log_must mmp_set_hostid $HOSTID1
+ log_must zpool create -f -o cachefile=$MMP_CACHE $pool \
+ mirror $dir/vdev1 $dir/vdev2
+ log_must zpool set multihost=on $pool
+}
+
+function mmp_pool_create # pool dir
+{
+ typeset pool=${1:-$MMP_POOL}
+ typeset dir=${2:-$MMP_DIR}
+ typeset opts="-VVVVV -T120 -M -k0 -f $dir -E -p $pool"
+
+ mmp_pool_create_simple $pool $dir
+
+ log_must mv $MMP_CACHE ${MMP_CACHE}.stale
+ log_must zpool export $pool
+ log_must mmp_clear_hostid
+ log_must mmp_set_hostid $HOSTID2
+
+ log_note "Starting ztest in the background as hostid $HOSTID1"
+ log_must eval "ZFS_HOSTID=$HOSTID1 ztest $opts >$MMP_ZTEST_LOG 2>&1 &"
+
+ while ! is_pool_imported "$pool" "-d $dir"; do
+ log_must pgrep ztest
+ log_must sleep 5
+ done
+}
+
+function mmp_pool_destroy # pool dir
+{
+ typeset pool=${1:-$MMP_POOL}
+ typeset dir=${2:-$MMP_DIR}
+
+ ZTESTPID=$(pgrep ztest)
+ if [ -n "$ZTESTPID" ]; then
+ log_must kill $ZTESTPID
+ wait $ZTESTPID
+ fi
+
+ if poolexists $pool; then
+ destroy_pool $pool
+ fi
+
+ log_must rm -f $dir/*
+ mmp_clear_hostid
+}
+
+function mmp_pool_set_hostid # pool hostid
+{
+ typeset pool=$1
+ typeset hostid=$2
+
+ log_must mmp_clear_hostid
+ log_must mmp_set_hostid $hostid
+ log_must zpool export $pool
+ log_must zpool import $pool
+
+ return 0
+}
+# Return the number of seconds the activity check portion of the import process
+# will take. Does not include the time to find devices and assemble a config.
+# Note that the activity check may be skipped, e.g. if the pool and host
+# hostid's match, but this will return non-zero because mmp_* are populated.
+function seconds_mmp_waits_for_activity
+{
+ typeset pool=$1
+ typeset devpath=$2
+
+ typeset seconds=0
+ typeset devices=${#DISK[@]}
+ typeset import_intervals=$(get_tunable MULTIHOST_IMPORT_INTERVALS)
+ typeset import_interval=$(get_tunable MULTIHOST_INTERVAL)
+ typeset tmpfile=$(mktemp)
+ typeset mmp_fail
+ typeset mmp_write
+ typeset mmp_delay
+
+ log_must zdb -e -p $devpath $pool >$tmpfile 2>/dev/null
+ mmp_fail=$(awk '/mmp_fail/ {print $NF}' $tmpfile)
+ mmp_write=$(awk '/mmp_write/ {print $NF}' $tmpfile)
+ mmp_delay=$(awk '/mmp_delay/ {print $NF}' $tmpfile)
+ if [ -f $tmpfile ]; then
+ rm $tmpfile
+ fi
+
+ # In order of preference:
+ if [ -n $mmp_fail -a -n $mmp_write ]; then
+ seconds=$((2*mmp_fail*mmp_write/1000))
+ elif [ -n $mmp_delay ]; then
+ # MMP V0: Based on mmp_delay from the best Uberblock
+ seconds=$((import_intervals*devices*mmp_delay/1000000000))
+ else
+ # Non-MMP aware: Based on zfs_multihost_interval and import_intervals
+ seconds=$((import_intervals*import_interval/1000))
+ fi
+
+ echo $seconds
+}
+
+function import_no_activity_check # pool opts
+{
+ typeset pool=$1
+ typeset opts=$2
+
+ typeset max_duration=$((MMP_TEST_DURATION_DEFAULT-1))
+
+ SECONDS=0
+ zpool import $opts $pool
+ typeset rc=$?
+
+ if [[ $SECONDS -gt $max_duration ]]; then
+ log_fail "ERROR: import_no_activity_check unexpected activity \
+check (${SECONDS}s gt $max_duration)"
+ fi
+
+ return $rc
+}
+
+function import_activity_check # pool opts act_test_duration
+{
+ typeset pool=$1
+ typeset opts=$2
+ typeset min_duration=${3:-$MMP_TEST_DURATION_DEFAULT}
+
+ SECONDS=0
+ zpool import $opts $pool
+ typeset rc=$?
+
+ if [[ $SECONDS -le $min_duration ]]; then
+ log_fail "ERROR: import_activity_check expected activity check \
+(${SECONDS}s le min_duration $min_duration)"
+ fi
+
+ return $rc
+}
+
+function clear_mmp_history
+{
+ log_must set_tunable64 MULTIHOST_HISTORY $MMP_HISTORY_OFF
+ log_must set_tunable64 MULTIHOST_HISTORY $MMP_HISTORY
+}
+
+function count_skipped_mmp_writes # pool duration
+{
+ typeset pool=$1
+ typeset -i duration=$2
+ typeset hist_path="/proc/spl/kstat/zfs/$pool/multihost"
+
+ sleep $duration
+ awk 'BEGIN {count=0}; $NF == "-" {count++}; END {print count};' "$hist_path"
+}
+
+function count_mmp_writes # pool duration
+{
+ typeset pool=$1
+ typeset -i duration=$2
+ typeset hist_path="/proc/spl/kstat/zfs/$pool/multihost"
+
+ sleep $duration
+ awk 'BEGIN {count=0}; $NF != "-" {count++}; END {print count};' "$hist_path"
+}
+
+function summarize_uberblock_mmp # device
+{
+ typeset device=$1
+
+ zdb -luuuu $device | awk '
+ BEGIN {write_fail_present=0; write_fail_missing=0; uber_invalid=0;}
+ /Uberblock\[[0-9][0-9]*\]/ {delay=-99; write=-99; fail=-99; total++; if (/invalid/) {uber_invalid++};};
+ /mmp_fail/ {fail=$3};
+ /mmp_seq/ {seq=$3};
+ /mmp_write/ {write=$3};
+ /mmp_delay/ {delay=$3; if (delay==0) {delay_zero++};};
+ /mmp_valid/ && delay>0 && write>0 && fail>0 {write_fail_present++};
+ /mmp_valid/ && delay>0 && (write<=0 || fail<=0) {write_fail_missing++};
+ /mmp_valid/ && delay>0 && write<=0 {write_missing++};
+ /mmp_valid/ && delay>0 && fail<=0 {fail_missing++};
+ /mmp_valid/ && delay>0 && seq>0 {seq_nonzero++};
+ END {
+ print "total_uberblocks " total;
+ print "delay_zero " delay_zero;
+ print "write_fail_present " write_fail_present;
+ print "write_fail_missing " write_fail_missing;
+ print "write_missing " write_missing;
+ print "fail_missing " fail_missing;
+ print "seq_nonzero " seq_nonzero;
+ print "uberblock_invalid " uber_invalid;
+ }'
+}
+
+function count_mmp_write_fail_present # device
+{
+ typeset device=$1
+
+ summarize_uberblock_mmp $device | awk '/write_fail_present/ {print $NF}'
+}
+
+function count_mmp_write_fail_missing # device
+{
+ typeset device=$1
+
+ summarize_uberblock_mmp $device | awk '/write_fail_missing/ {print $NF}'
+}
+
+function verify_mmp_write_fail_present # device
+{
+ typeset device=$1
+
+ count=$(count_mmp_write_fail_present $device)
+ log_note "present count: $count"
+ if [ $count -eq 0 ]; then
+ summarize_uberblock_mmp $device
+ log_note "----- snip -----"
+ zdb -luuuu $device
+ log_note "----- snip -----"
+ log_fail "No Uberblocks contain valid mmp_write and fail values"
+ fi
+
+ count=$(count_mmp_write_fail_missing $device)
+ log_note "missing count: $count"
+ if [ $count -gt 0 ]; then
+ summarize_uberblock_mmp $device
+ log_note "----- snip -----"
+ zdb -luuuu $device
+ log_note "----- snip -----"
+ log_fail "Uberblocks missing mmp_write or mmp_fail"
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_active_import.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_active_import.ksh
new file mode 100755
index 000000000000..c4ed894826ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_active_import.ksh
@@ -0,0 +1,125 @@
+#!/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 Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Under no circumstances when multihost is active, should an active pool
+# with one hostid be importable by a host with a different hostid.
+#
+# STRATEGY:
+# 1. Simulate an active pool on another host with ztest.
+# 2. Verify 'zpool import' reports an active pool.
+# 3. Verify 'zpool import [-f] $MMP_POOL' cannot import the pool.
+# 4. Kill ztest to make pool eligible for import.
+# 5. Verify 'zpool import' fails with the expected error message.
+# 6. Verify 'zpool import $MMP_POOL' fails with the expected message.
+# 7. Verify 'zpool import -f $MMP_POOL' can now import the pool.
+# 8. Verify pool may be exported/imported without -f argument.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ mmp_pool_destroy $MMP_POOL $MMP_DIR
+ log_must mmp_clear_hostid
+ ZTESTPID=$(pgrep ztest)
+ if [ -n "$ZTESTPID" ]; then
+ for pid in $ZTESTPID; do
+ log_must kill -9 $pid
+ done
+ else
+ # if ztest not running and log present, ztest crashed
+ if [ -f $MMP_ZTEST_LOG ]; then
+ log_note "ztest appears to have crashed. Tail of log:"
+ tail -n 50 $MMP_ZTEST_LOG
+ fi
+ fi
+}
+
+log_assert "multihost=on|off active pool activity checks"
+log_onexit cleanup
+
+# 1. Simulate an active pool on another host with ztest.
+mmp_pool_destroy $MMP_POOL $MMP_DIR
+mmp_pool_create $MMP_POOL $MMP_DIR
+
+# 2. Verify 'zpool import' reports an active pool.
+log_must mmp_set_hostid $HOSTID2
+log_must is_pool_imported $MMP_POOL "-d $MMP_DIR"
+
+# 3. Verify 'zpool import [-f] $MMP_POOL' cannot import the pool.
+MMP_IMPORTED_MSG="Cannot import '$MMP_POOL': pool is imported"
+
+log_must try_pool_import $MMP_POOL "-d $MMP_DIR" "$MMP_IMPORTED_MSG"
+for i in {1..10}; do
+ log_must try_pool_import $MMP_POOL "-f -d $MMP_DIR" "$MMP_IMPORTED_MSG"
+done
+
+log_must try_pool_import $MMP_POOL "-c ${MMP_CACHE}.stale" "$MMP_IMPORTED_MSG"
+
+for i in {1..10}; do
+ log_must try_pool_import $MMP_POOL "-f -c ${MMP_CACHE}.stale" \
+ "$MMP_IMPORTED_MSG"
+done
+
+# 4. Kill ztest to make pool eligible for import. Poll with 'zpool status'.
+ZTESTPID=$(pgrep ztest)
+if [ -n "$ZTESTPID" ]; then
+ log_must kill -9 $ZTESTPID
+fi
+log_must wait_pool_imported $MMP_POOL "-d $MMP_DIR"
+if [ -f $MMP_ZTEST_LOG ]; then
+ log_must rm $MMP_ZTEST_LOG
+fi
+
+# 5. Verify 'zpool import' fails with the expected error message, when
+# - hostid=0: - configuration error
+# - hostid=matches - safe to import the pool
+# - hostid=different - previously imported on a different system
+#
+log_must mmp_clear_hostid
+MMP_IMPORTED_MSG="Set a unique system hostid"
+log_must check_pool_import $MMP_POOL "-d $MMP_DIR" "action" "$MMP_IMPORTED_MSG"
+
+log_must mmp_set_hostid $HOSTID1
+MMP_IMPORTED_MSG="The pool can be imported"
+log_must check_pool_import $MMP_POOL "-d $MMP_DIR" "action" "$MMP_IMPORTED_MSG"
+
+log_must mmp_clear_hostid
+log_must mmp_set_hostid $HOSTID2
+MMP_IMPORTED_MSG="The pool was last accessed by another system."
+log_must check_pool_import $MMP_POOL "-d $MMP_DIR" "status" "$MMP_IMPORTED_MSG"
+
+# 6. Verify 'zpool import $MMP_POOL' fails with the expected message.
+MMP_IMPORTED_MSG="pool was previously in use from another system."
+log_must try_pool_import $MMP_POOL "-d $MMP_DIR" "$MMP_IMPORTED_MSG"
+
+# 7. Verify 'zpool import -f $MMP_POOL' can now import the pool.
+log_must import_activity_check $MMP_POOL "-f -d $MMP_DIR"
+
+# 8 Verify pool may be exported/imported without -f argument.
+log_must zpool export $MMP_POOL
+log_must import_no_activity_check $MMP_POOL "-d $MMP_DIR"
+
+log_pass "multihost=on|off active pool activity checks passed"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_exported_import.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_exported_import.ksh
new file mode 100755
index 000000000000..3d67deb02c5f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_exported_import.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 (c) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify import behavior for exported pool (no activity check)
+#
+# STRATEGY:
+# 1. Create a zpool
+# 2. Verify multihost=off and hostids match (no activity check)
+# 3. Verify multihost=off and hostids differ (no activity check)
+# 4. Verify multihost=off and hostid zero allowed (no activity check)
+# 5. Verify multihost=on and hostids match (no activity check)
+# 6. Verify multihost=on and hostids differ (no activity check)
+# 7. Verify multihost=on and hostid zero fails (no activity check)
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must mmp_clear_hostid
+}
+
+log_assert "multihost=on|off activity checks exported pool"
+log_onexit cleanup
+
+# 1. Create a zpool
+log_must mmp_set_hostid $HOSTID1
+default_setup_noexit $DISK
+
+# 2. Verify multihost=off and hostids match (no activity check)
+log_must zpool set multihost=off $TESTPOOL
+
+for opt in "" "-f"; do
+ log_must zpool export $TESTPOOL
+ log_must import_no_activity_check $TESTPOOL $opt
+done
+
+# 3. Verify multihost=off and hostids differ (no activity check)
+for opt in "" "-f"; do
+ log_must mmp_pool_set_hostid $TESTPOOL $HOSTID1
+ log_must zpool export $TESTPOOL
+ log_must mmp_clear_hostid
+ log_must mmp_set_hostid $HOSTID2
+ log_must import_no_activity_check $TESTPOOL $opt
+done
+
+# 4. Verify multihost=off and hostid zero allowed (no activity check)
+log_must mmp_clear_hostid
+
+for opt in "" "-f"; do
+ log_must zpool export $TESTPOOL
+ log_must import_no_activity_check $TESTPOOL $opt
+done
+
+# 5. Verify multihost=on and hostids match (no activity check)
+log_must mmp_pool_set_hostid $TESTPOOL $HOSTID1
+log_must zpool set multihost=on $TESTPOOL
+
+for opt in "" "-f"; do
+ log_must zpool export $TESTPOOL
+ log_must import_no_activity_check $TESTPOOL $opt
+done
+
+# 6. Verify multihost=on and hostids differ (no activity check)
+for opt in "" "-f"; do
+ log_must mmp_pool_set_hostid $TESTPOOL $HOSTID1
+ log_must zpool export $TESTPOOL
+ log_must mmp_clear_hostid
+ log_must mmp_set_hostid $HOSTID2
+ log_must import_no_activity_check $TESTPOOL $opt
+done
+
+# 7. Verify multihost=on and hostid zero fails (no activity check)
+log_must zpool export $TESTPOOL
+log_must mmp_clear_hostid
+
+for opt in "" "-f"; do
+ MMP_IMPORTED_MSG="Set a unique system hostid"
+ log_must check_pool_import $TESTPOOL "" "action" "$MMP_IMPORTED_MSG"
+ log_mustnot import_no_activity_check $TESTPOOL $opt
+done
+
+log_pass "multihost=on|off exported pool activity checks passed"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_hostid.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_hostid.ksh
new file mode 100755
index 000000000000..e3c6e34f4bc0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_hostid.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) 2019 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify the hostid file can reside on a ZFS dataset.
+#
+# STRATEGY:
+# 1. Create a non-redundant pool
+# 2. Create an 'etc' dataset containing a valid hostid file
+# 3. Create a file so the pool will have some contents
+# 4. Verify multihost cannot be enabled until the /etc/hostid is linked
+# 5. Verify vdevs may be attached and detached
+# 6. Verify normal, cache, log and special vdevs can be added
+# 7. Verify normal, cache, and log vdevs can be removed
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm $MMP_DIR/file.{0,1,2,3,4,5}
+ log_must rmdir $MMP_DIR
+ log_must mmp_clear_hostid
+ if [[ -L $HOSTID_FILE ]]; then
+ rm -f $HOSTID_FILE
+ fi
+}
+
+log_assert "Verify hostid file can reside on a ZFS dataset"
+log_onexit cleanup
+
+log_must mkdir -p $MMP_DIR
+log_must truncate -s $MINVDEVSIZE $MMP_DIR/file.{0,1,2,3,4,5}
+
+# 1. Create a non-redundant pool
+log_must zpool create $MMP_POOL $MMP_DIR/file.0
+
+# 2. Create an 'etc' dataset containing a valid hostid file; caching is
+# disabled on the dataset to force the hostid to be read from disk.
+log_must zfs create -o primarycache=none -o secondarycache=none $MMP_POOL/etc
+mntpnt_etc=$(get_prop mountpoint $MMP_POOL/etc)
+log_must mmp_set_hostid $HOSTID1
+log_must mv $HOSTID_FILE $mntpnt_etc/hostid
+
+# 3. Create a file so the pool will have some contents
+log_must zfs create $MMP_POOL/fs
+mntpnt_fs=$(get_prop mountpoint $MMP_POOL/fs)
+log_must mkfile 1M $mntpnt_fs/file
+
+# 4. Verify multihost cannot be enabled until the /etc/hostid is linked
+log_mustnot zpool set multihost=on $MMP_POOL
+log_mustnot ls -l $HOSTID_FILE
+log_must ln -s $mntpnt_etc/hostid $HOSTID_FILE
+log_must zpool set multihost=on $MMP_POOL
+
+# 5. Verify vdevs may be attached and detached
+log_must zpool attach $MMP_POOL $MMP_DIR/file.0 $MMP_DIR/file.1
+log_must zpool detach $MMP_POOL $MMP_DIR/file.1
+
+# 6. Verify normal, cache, log and special vdevs can be added
+log_must zpool add $MMP_POOL $MMP_DIR/file.1
+log_must zpool add $MMP_POOL $MMP_DIR/file.2
+log_must zpool add $MMP_POOL cache $MMP_DIR/file.3
+log_must zpool add $MMP_POOL log $MMP_DIR/file.4
+log_must zpool add $MMP_POOL special $MMP_DIR/file.5
+
+# 7. Verify normal, cache, and log vdevs can be removed
+log_must zpool remove $MMP_POOL $MMP_DIR/file.2
+log_must zpool remove $MMP_POOL $MMP_DIR/file.3
+log_must zpool remove $MMP_POOL $MMP_DIR/file.4
+
+log_pass "Verify hostid file can reside on a ZFS dataset."
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_inactive_import.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_inactive_import.ksh
new file mode 100755
index 000000000000..6e7bb637548d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_inactive_import.ksh
@@ -0,0 +1,111 @@
+#!/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 Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify import behavior for inactive, but not exported, pools
+#
+# STRATEGY:
+# 1. Create a zpool
+# 2. Verify multihost=off and hostids match (no activity check)
+# 3. Verify multihost=off and hostids differ (no activity check)
+# 4. Verify multihost=off and hostid allowed (no activity check)
+# 5. Verify multihost=on and hostids match (no activity check)
+# 6. Verify multihost=on and hostids differ (activity check)
+# 7. Verify mmp_write and mmp_fail are set correctly
+# 8. Verify multihost=on and hostid zero fails (no activity check)
+# 9. Verify activity check duration based on mmp_write and mmp_fail
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must mmp_clear_hostid
+ log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT
+}
+
+log_assert "multihost=on|off inactive pool activity checks"
+log_onexit cleanup
+
+# 1. Create a zpool
+log_must mmp_set_hostid $HOSTID1
+default_setup_noexit $DISK
+
+# 2. Verify multihost=off and hostids match (no activity check)
+log_must zpool set multihost=off $TESTPOOL
+
+for opt in "" "-f"; do
+ log_must zpool export -F $TESTPOOL
+ log_must import_no_activity_check $TESTPOOL $opt
+done
+
+# 3. Verify multihost=off and hostids differ (no activity check)
+log_must zpool export -F $TESTPOOL
+log_must mmp_clear_hostid
+log_must mmp_set_hostid $HOSTID2
+log_mustnot import_no_activity_check $TESTPOOL ""
+log_must import_no_activity_check $TESTPOOL "-f"
+
+# 4. Verify multihost=off and hostid zero allowed (no activity check)
+log_must zpool export -F $TESTPOOL
+log_must mmp_clear_hostid
+log_mustnot import_no_activity_check $TESTPOOL ""
+log_must import_no_activity_check $TESTPOOL "-f"
+
+# 5. Verify multihost=on and hostids match (no activity check)
+log_must mmp_pool_set_hostid $TESTPOOL $HOSTID1
+log_must zpool set multihost=on $TESTPOOL
+
+for opt in "" "-f"; do
+ log_must zpool export -F $TESTPOOL
+ log_must import_no_activity_check $TESTPOOL $opt
+done
+
+# 6. Verify multihost=on and hostids differ (activity check)
+log_must zpool export -F $TESTPOOL
+log_must mmp_clear_hostid
+log_must mmp_set_hostid $HOSTID2
+log_mustnot import_activity_check $TESTPOOL ""
+log_must import_activity_check $TESTPOOL "-f"
+
+# 7. Verify mmp_write and mmp_fail are set correctly
+log_must zpool export -F $TESTPOOL
+log_must verify_mmp_write_fail_present ${DISK[0]}
+
+# 8. Verify multihost=on and hostid zero fails (no activity check)
+log_must mmp_clear_hostid
+MMP_IMPORTED_MSG="Set a unique system hostid"
+log_must check_pool_import $TESTPOOL "-f" "action" "$MMP_IMPORTED_MSG"
+log_mustnot import_no_activity_check $TESTPOOL "-f"
+
+# 9. Verify activity check duration based on mmp_write and mmp_fail
+# Specify a short test via tunables but import pool imported while
+# tunables set to default duration.
+log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_MIN
+log_must mmp_clear_hostid
+log_must mmp_set_hostid $HOSTID1
+log_must import_activity_check $TESTPOOL "-f" $MMP_TEST_DURATION_DEFAULT
+
+log_pass "multihost=on|off inactive pool activity checks passed"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_interval.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_interval.ksh
new file mode 100755
index 000000000000..0c080ab5d313
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_interval.ksh
@@ -0,0 +1,47 @@
+#!/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 Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# MULTIHOST_INTERVAL should only accept valid values.
+#
+# STRATEGY:
+# 1. Set MULTIHOST_INTERVAL to invalid values (negative).
+# 2. Set MULTIHOST_INTERVAL to valid values.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT
+}
+
+log_assert "MULTIHOST_INTERVAL cannot be set to an invalid value"
+log_onexit cleanup
+
+log_mustnot set_tunable64 MULTIHOST_INTERVAL -1
+log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_MIN
+log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT
+
+log_pass "MULTIHOST_INTERVAL cannot be set to an invalid value"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_on_off.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_on_off.ksh
new file mode 100755
index 000000000000..29d771de8f8b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_on_off.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 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# When multihost=off ensure that leaf vdev uberblocks are not updated.
+#
+# STRATEGY:
+# 1. Set multihost=off (disables mmp)
+# 2. Set TXG_TIMEOUT to large value
+# 3. Create a zpool
+# 4. Find the current "best" uberblock
+# 5. Sleep for enough time for uberblocks to change
+# 6. Find the current "best" uberblock
+# 7. If the uberblock changed, fail
+# 8. Set multihost=on
+# 9. Sleep for enough time for uberblocks to change
+# 10. Find the current "best" uberblock
+# 11. If uberblocks didn't change, fail
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must set_tunable64 TXG_TIMEOUT $TXG_TIMEOUT_DEFAULT
+ log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT
+ log_must rm -f $PREV_UBER $CURR_UBER
+ log_must mmp_clear_hostid
+}
+
+log_assert "mmp thread won't write uberblocks with multihost=off"
+log_onexit cleanup
+
+log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_MIN
+log_must set_tunable64 TXG_TIMEOUT $TXG_TIMEOUT_LONG
+log_must mmp_set_hostid $HOSTID1
+
+default_setup_noexit $DISK
+log_must zpool set multihost=off $TESTPOOL
+
+log_must zdb -u $TESTPOOL > $PREV_UBER
+log_must sleep 5
+log_must zdb -u $TESTPOOL > $CURR_UBER
+
+if ! diff "$CURR_UBER" "$PREV_UBER"; then
+ log_fail "mmp thread has updated an uberblock"
+fi
+
+log_must zpool set multihost=on $TESTPOOL
+log_must sleep 5
+log_must zdb -u $TESTPOOL > $CURR_UBER
+
+if diff "$CURR_UBER" "$PREV_UBER"; then
+ log_fail "mmp failed to update uberblocks"
+fi
+
+log_pass "mmp thread won't write uberblocks with multihost=off passed"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_on_thread.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_on_thread.ksh
new file mode 100755
index 000000000000..01cca61c3c3e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_on_thread.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) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Ensure that the MMP thread is writing uberblocks.
+#
+# STRATEGY:
+# 1. Set zfs_txg_timeout to large value
+# 2. Create a zpool
+# 3. Find the current "best" uberblock
+# 4. Sleep for enough time for a potential uberblock update
+# 5. Find the current "best" uberblock
+# 6. If the uberblock never changed, fail
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must set_tunable64 TXG_TIMEOUT $TXG_TIMEOUT_DEFAULT
+ log_must rm -f $PREV_UBER $CURR_UBER
+ log_must mmp_clear_hostid
+}
+
+log_assert "mmp thread writes uberblocks (MMP)"
+log_onexit cleanup
+
+log_must set_tunable64 TXG_TIMEOUT $TXG_TIMEOUT_LONG
+log_must mmp_set_hostid $HOSTID1
+
+default_setup_noexit $DISK
+log_must zpool set multihost=on $TESTPOOL
+
+log_must zdb -u $TESTPOOL > $PREV_UBER
+log_must sleep 5
+log_must zdb -u $TESTPOOL > $CURR_UBER
+
+if diff -u "$CURR_UBER" "$PREV_UBER"; then
+ log_fail "mmp failed to update uberblocks"
+fi
+
+log_pass "mmp thread writes uberblocks (MMP) passed"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.ksh
new file mode 100755
index 000000000000..007288a78f4b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_on_uberblocks.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 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Ensure that MMP updates uberblocks with MMP info at expected intervals.
+#
+# STRATEGY:
+# 1. Set TXG_TIMEOUT to large value
+# 2. Create a zpool
+# 3. Clear multihost history
+# 4. Sleep, then collect count of uberblocks written
+# 5. If number of changes seen is less than min threshold, then fail
+# 6. If number of changes seen is more than max threshold, then fail
+# 7. Sequence number increments when no TXGs are syncing
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+UBER_CHANGES=0
+EXPECTED=$(($(echo $DISKS | wc -w) * 10))
+FUDGE=$((EXPECTED * 20 / 100))
+MIN_UB_WRITES=$((EXPECTED - FUDGE))
+MAX_UB_WRITES=$((EXPECTED + FUDGE))
+MIN_SEQ_VALUES=7
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT
+ set_tunable64 TXG_TIMEOUT $TXG_TIMEOUT_DEFAULT
+ log_must mmp_clear_hostid
+}
+
+log_assert "Ensure MMP uberblocks update at the correct interval"
+log_onexit cleanup
+
+log_must set_tunable64 TXG_TIMEOUT $TXG_TIMEOUT_LONG
+log_must mmp_set_hostid $HOSTID1
+
+default_setup_noexit "$DISKS"
+log_must zpool set multihost=on $TESTPOOL
+clear_mmp_history
+UBER_CHANGES=$(count_mmp_writes $TESTPOOL 10)
+
+log_note "Uberblock changed $UBER_CHANGES times"
+
+if [ $UBER_CHANGES -lt $MIN_UB_WRITES ]; then
+ log_fail "Fewer uberblock writes occurred than expected ($EXPECTED)"
+fi
+
+if [ $UBER_CHANGES -gt $MAX_UB_WRITES ]; then
+ log_fail "More uberblock writes occurred than expected ($EXPECTED)"
+fi
+
+log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_MIN
+SEQ_BEFORE=$(zdb -luuuu ${DISK[0]} | awk '/mmp_seq/ {if ($NF>max) max=$NF}; END {print max}')
+sleep 1
+SEQ_AFTER=$(zdb -luuuu ${DISK[0]} | awk '/mmp_seq/ {if ($NF>max) max=$NF}; END {print max}')
+if [ $((SEQ_AFTER - SEQ_BEFORE)) -lt $MIN_SEQ_VALUES ]; then
+ zdb -luuuu ${DISK[0]}
+ log_fail "ERROR: mmp_seq did not increase by $MIN_SEQ_VALUES; before $SEQ_BEFORE after $SEQ_AFTER"
+fi
+
+log_pass "Ensure MMP uberblocks update at the correct interval passed"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_on_zdb.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_on_zdb.ksh
new file mode 100755
index 000000000000..131fd21e8817
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_on_zdb.ksh
@@ -0,0 +1,81 @@
+#!/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 Lawrence Livermore National Security, LLC.
+# Copyright (c) 2018 by Nutanix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+#
+# Description:
+# zdb will work while multihost is enabled.
+#
+# Strategy:
+# 1. Create a pool
+# 2. Enable multihost
+# 3. Run zdb -d with pool and dataset arguments.
+# 4. Create a checkpoint
+# 5. Run zdb -kd with pool and dataset arguments.
+# 6. Discard the checkpoint
+# 7. Export the pool
+# 8. 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_must mmp_clear_hostid
+}
+
+log_assert "Verify zdb -d works while multihost is enabled"
+log_onexit cleanup
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+default_mirror_setup_noexit $DISKS
+log_must mmp_set_hostid $HOSTID1
+log_must zpool set multihost=on $TESTPOOL
+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 checkpoint $TESTPOOL
+log_must zdb -kd $TESTPOOL
+log_must zdb -kd $TESTPOOL/
+log_must zdb -kd $TESTPOOL/$TESTFS
+log_must zdb -kd $TESTPOOL/$TESTFS@snap
+log_must zpool checkpoint -d $TESTPOOL
+
+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 while multihost is enabled"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_reset_interval.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_reset_interval.ksh
new file mode 100755
index 000000000000..6e3d1fe34d4b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_reset_interval.ksh
@@ -0,0 +1,119 @@
+#!/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 Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Ensure that the MMP thread is notified when MULTIHOST_INTERVAL is
+# reduced, and that changes to MULTIHOST_INTERVAL and
+# MULTIHOST_FAIL_INTERVALS do not trigger pool suspensions.
+#
+# STRATEGY:
+# 1. Set MULTIHOST_INTERVAL to much longer than the test duration
+# 2. Create a zpool and enable multihost
+# 3. Verify no MMP writes occurred
+# 4. Set MULTIHOST_INTERVAL to 1 second
+# 5. Sleep briefly
+# 6. Verify MMP writes began
+# 7. Verify mmp_fail and mmp_write in uberblock reflect tunables
+# 8. Repeatedly change tunables relating to pool suspension
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT
+ log_must set_tunable64 MULTIHOST_FAIL_INTERVALS \
+ $MMP_FAIL_INTERVALS_DEFAULT
+ log_must mmp_clear_hostid
+}
+
+log_assert "mmp threads notified when MULTIHOST_INTERVAL reduced"
+log_onexit cleanup
+
+log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_HOUR
+log_must mmp_set_hostid $HOSTID1
+
+default_setup_noexit $DISK
+log_must zpool set multihost=on $TESTPOOL
+
+clear_mmp_history
+log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT
+uber_count=$(count_mmp_writes $TESTPOOL 1)
+
+if [ $uber_count -eq 0 ]; then
+ log_fail "ERROR: mmp writes did not start when MULTIHOST_INTERVAL reduced"
+fi
+
+# 7. Verify mmp_write and mmp_fail are written
+for fails in $(seq $MMP_FAIL_INTERVALS_MIN $((MMP_FAIL_INTERVALS_MIN*2))); do
+ for interval in $(seq $MMP_INTERVAL_MIN 200 $MMP_INTERVAL_DEFAULT); do
+ log_must set_tunable64 MULTIHOST_FAIL_INTERVALS $fails
+ log_must set_tunable64 MULTIHOST_INTERVAL $interval
+ log_must sync_pool $TESTPOOL
+ typeset mmp_fail=$(zdb $TESTPOOL 2>/dev/null |
+ awk '/mmp_fail/ {print $NF}')
+ if [ $fails -ne $mmp_fail ]; then
+ log_fail "ERROR: mmp_fail $mmp_fail != $fails"
+ fi
+ typeset mmp_write=$(zdb $TESTPOOL 2>/dev/null |
+ awk '/mmp_write/ {print $NF}')
+ if [ $interval -ne $mmp_write ]; then
+ log_fail "ERROR: mmp_write $mmp_write != $interval"
+ fi
+ done
+done
+
+
+# 8. Repeatedly change MULTIHOST_INTERVAL and fail_intervals
+for x in $(seq 10); do
+ typeset new_interval=$(( (RANDOM % 20 + 1) * $MMP_INTERVAL_MIN ))
+ log_must set_tunable64 MULTIHOST_INTERVAL $new_interval
+ typeset action=$((RANDOM %10))
+ if [ $action -eq 0 ]; then
+ log_must zpool export -a
+ log_must mmp_clear_hostid
+ log_must mmp_set_hostid $HOSTID1
+ log_must zpool import $TESTPOOL
+ elif [ $action -eq 1 ]; then
+ log_must zpool export -F $TESTPOOL
+ log_must zpool import $TESTPOOL
+ elif [ $action -eq 2 ]; then
+ log_must zpool export -F $TESTPOOL
+ log_must mmp_clear_hostid
+ log_must mmp_set_hostid $HOSTID2
+ log_must zpool import -f $TESTPOOL
+ elif [ $action -eq 3 ]; then
+ log_must zpool export -F $TESTPOOL
+ log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_MIN
+ log_must zpool import $TESTPOOL
+ elif [ $action -eq 4 ]; then
+ log_must set_tunable64 MULTIHOST_FAIL_INTERVALS \
+ $((RANDOM % MMP_FAIL_INTERVALS_DEFAULT))
+ fi
+ sleep 5
+done
+
+
+log_pass "mmp threads notified when MULTIHOST_INTERVAL reduced"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_write_distribution.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_write_distribution.ksh
new file mode 100755
index 000000000000..b6bdc6811634
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_write_distribution.ksh
@@ -0,0 +1,92 @@
+#!/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 Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify MMP writes are distributed evenly among leaves
+#
+# STRATEGY:
+# 1. Create an asymmetric mirrored pool
+# 2. Enable multihost and multihost_history
+# 3. Delay for MMP writes to occur
+# 4. Verify the MMP writes are distributed evenly across leaf vdevs
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zpool destroy $MMP_POOL
+ log_must rm $MMP_DIR/file.{0,1,2,3,4,5,6,7}
+ log_must rm $MMP_HISTORY_TMP
+ log_must rmdir $MMP_DIR
+ log_must mmp_clear_hostid
+}
+
+log_assert "mmp writes are evenly distributed across leaf vdevs"
+log_onexit cleanup
+
+MMP_HISTORY_TMP=$MMP_DIR/history
+MMP_HISTORY=/proc/spl/kstat/zfs/$MMP_POOL/multihost
+
+# Step 1
+log_must mkdir -p $MMP_DIR
+log_must truncate -s 128M $MMP_DIR/file.{0,1,2,3,4,5,6,7}
+log_must zpool create -f $MMP_POOL mirror $MMP_DIR/file.{0,1} mirror $MMP_DIR/file.{2,3,4,5,6,7}
+
+# Step 2
+log_must mmp_set_hostid $HOSTID1
+log_must zpool set multihost=on $MMP_POOL
+set_tunable64 MULTIHOST_HISTORY 0
+set_tunable64 MULTIHOST_HISTORY 40
+
+# Step 3
+# default settings, every leaf written once/second
+sleep 4
+
+# Step 4
+typeset -i min_writes=999
+typeset -i max_writes=0
+typeset -i write_count
+# copy to get as close to a consistent view as possible
+cat $MMP_HISTORY > $MMP_HISTORY_TMP
+for x in $(seq 0 7); do
+ write_count=$(grep -c file.${x} $MMP_HISTORY_TMP)
+ if [ $write_count -lt $min_writes ]; then
+ min_writes=$write_count
+ fi
+ if [ $write_count -gt $max_writes ]; then
+ max_writes=$write_count
+ fi
+done
+log_note "mmp min_writes $min_writes max_writes $max_writes"
+
+if [ $min_writes -lt 1 ]; then
+ log_fail "mmp writes were not counted correctly"
+fi
+
+if [ $((max_writes - min_writes)) -gt 1 ]; then
+ log_fail "mmp writes were not evenly distributed across leaf vdevs"
+fi
+
+log_pass "mmp writes were evenly distributed across leaf vdevs"
diff --git a/tests/zfs-tests/tests/functional/mmp/mmp_write_uberblocks.ksh b/tests/zfs-tests/tests/functional/mmp/mmp_write_uberblocks.ksh
new file mode 100755
index 000000000000..e287f41983d7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/mmp_write_uberblocks.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 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# Verify MMP behaves correctly when failing to write uberblocks.
+#
+# STRATEGY:
+# 1. Create a mirrored pool and enable multihost
+# 2. Inject a 50% failure rate when writing uberblocks to a device
+# 3. Delay briefly for additional MMP writes to complete
+# 4. Verify the failed uberblock writes did not prevent MMP updates
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ zinject -c all
+ default_cleanup_noexit
+ log_must mmp_clear_hostid
+}
+
+log_assert "mmp behaves correctly when failing to write uberblocks."
+log_onexit cleanup
+
+log_must mmp_set_hostid $HOSTID1
+default_mirror_setup_noexit $DISKS
+log_must zpool set multihost=on $TESTPOOL
+log_must zinject -d ${DISK[0]} -e io -T write -f 50 $TESTPOOL -L uber
+clear_mmp_history
+uber_count=$(count_mmp_writes $TESTPOOL 3)
+
+if [ $uber_count -eq 0 ]; then
+ log_fail "mmp writes did not occur when uberblock IO errors injected"
+fi
+
+log_pass "mmp correctly wrote uberblocks when IO errors injected"
diff --git a/tests/zfs-tests/tests/functional/mmp/multihost_history.ksh b/tests/zfs-tests/tests/functional/mmp/multihost_history.ksh
new file mode 100755
index 000000000000..e831475dbcb2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/multihost_history.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 by Lawrence Livermore National Security, LLC.
+#
+
+# DESCRIPTION:
+# zfs_multihost_history should report both writes issued and gaps
+#
+# STRATEGY:
+# 1. Create a 2-vdev pool with mmp enabled
+# 2. Delay writes by 2*MMP_INTERVAL_DEFAULT
+# 3. Check multihost_history for both issued writes, and for gaps where
+# no write could be issued because all vdevs are busy
+#
+# During the first MMP_INTERVAL period 2 MMP writes will be issued - one to
+# each vdev. At the third scheduled attempt to write, at time t0+MMP_INTERVAL,
+# both vdevs will still have outstanding writes, so a skipped write entry will
+# be recorded in the multihost_history.
+
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+. $STF_SUITE/tests/functional/mmp/mmp.kshlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zinject -c all
+ mmp_pool_destroy $MMP_POOL $MMP_DIR
+ log_must mmp_clear_hostid
+}
+
+log_assert "zfs_multihost_history records writes and skipped writes"
+log_onexit cleanup
+
+mmp_pool_create_simple $MMP_POOL $MMP_DIR
+log_must zinject -d $MMP_DIR/vdev1 -D$((2*MMP_INTERVAL_DEFAULT)):10 $MMP_POOL
+log_must zinject -d $MMP_DIR/vdev2 -D$((2*MMP_INTERVAL_DEFAULT)):10 $MMP_POOL
+
+mmp_writes=$(count_mmp_writes $MMP_POOL $((MMP_INTERVAL_DEFAULT/1000)))
+mmp_skips=$(count_skipped_mmp_writes $MMP_POOL $((MMP_INTERVAL_DEFAULT/1000)))
+
+if [ $mmp_writes -lt 1 ]; then
+ log_fail "mmp writes entries missing when delays injected"
+fi
+
+if [ $mmp_skips -lt 1 ]; then
+ log_fail "mmp skipped write entries missing when delays injected"
+fi
+
+log_pass "zfs_multihost_history records writes and skipped writes"
diff --git a/tests/zfs-tests/tests/functional/mmp/setup.ksh b/tests/zfs-tests/tests/functional/mmp/setup.ksh
new file mode 100755
index 000000000000..b1e5431c8427
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mmp/setup.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) 2017 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mmp/mmp.cfg
+
+verify_runnable "global"
+
+if [ -e $HOSTID_FILE ]; then
+ log_unsupported "System has existing $HOSTID_FILE file"
+fi
+
+log_must set_tunable64 MULTIHOST_HISTORY $MMP_HISTORY
+log_must set_tunable64 MULTIHOST_INTERVAL $MMP_INTERVAL_DEFAULT
+log_must set_tunable64 MULTIHOST_FAIL_INTERVALS $MMP_FAIL_INTERVALS_DEFAULT
+
+log_pass "mmp setup pass"
diff --git a/tests/zfs-tests/tests/functional/mount/Makefile.am b/tests/zfs-tests/tests/functional/mount/Makefile.am
new file mode 100644
index 000000000000..bdafa69badd8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mount/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/mount
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ umount_001.ksh \
+ umount_unlinked_drain.ksh \
+ umountall_001.ksh
diff --git a/tests/zfs-tests/tests/functional/mount/cleanup.ksh b/tests/zfs-tests/tests/functional/mount/cleanup.ksh
new file mode 100755
index 000000000000..f20c72841f42
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mount/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.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+log_must destroy_pool $TESTPOOL
+
+for dir in $TESTDIRS; do
+ rm -rf $dir
+done
diff --git a/tests/zfs-tests/tests/functional/mount/setup.ksh b/tests/zfs-tests/tests/functional/mount/setup.ksh
new file mode 100755
index 000000000000..8e2edcd24f4b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mount/setup.ksh
@@ -0,0 +1,48 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+create_pool $TESTPOOL "$DISK"
+
+for i in 1 2 3; do
+ dir=$TESTDIR.$i
+ fs=$TESTPOOL/$TESTFS.$i
+
+ log_must zfs create $fs
+ log_must mkdir -p $dir
+ log_must zfs set mountpoint=$dir $fs
+
+ log_must mounted $fs
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/mount/umount_001.ksh b/tests/zfs-tests/tests/functional/mount/umount_001.ksh
new file mode 100755
index 000000000000..ec4954569961
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mount/umount_001.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# zfs mount and unmount commands should mount and unmount existing
+# file systems.
+#
+# STRATEGY:
+# 1. Call zfs mount command
+# 2. Make sure the file systems were mounted
+# 3. Call zfs unmount command
+# 4. Make sure the file systems were unmounted
+#
+
+for fs in 1 2 3; do
+ log_must mounted $TESTDIR.$fs
+ log_must zfs umount $TESTPOOL/$TESTFS.$fs
+ log_must unmounted $TESTDIR.$fs
+ log_must zfs mount $TESTPOOL/$TESTFS.$fs
+ log_must mounted $TESTDIR.$fs
+done
+
+log_pass "All file systems are unmounted"
diff --git a/tests/zfs-tests/tests/functional/mount/umount_unlinked_drain.ksh b/tests/zfs-tests/tests/functional/mount/umount_unlinked_drain.ksh
new file mode 100755
index 000000000000..6130e2c82893
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mount/umount_unlinked_drain.ksh
@@ -0,0 +1,118 @@
+#!/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:
+# Test async unlinked drain to ensure mounting is not held up when there are
+# entries in the unlinked set. We also try to test that the list is able to be
+# filled up and drained at the same time.
+#
+# STRATEGY:
+# 1. Use zfs_unlink_suspend_progress tunable to disable freeing to build up
+# the unlinked set
+# 2. Make sure mount happens even when there are entries in the unlinked set
+# 3. Drain and build up the unlinked list at the same time to test for races
+#
+
+function cleanup
+{
+ log_must set_tunable32 UNLINK_SUSPEND_PROGRESS $default_unlink_sp
+ for fs in $(seq 1 3); do
+ mounted $TESTDIR.$fs || zfs mount $TESTPOOL/$TESTFS.$fs
+ rm -f $TESTDIR.$fs/file-*
+ zfs set xattr=on $TESTPOOL/$TESTFS.$fs
+ done
+}
+
+function unlinked_size_is
+{
+ MAX_ITERS=5 # iteration to do before we consider reported number stable
+ iters=0
+ last_usize=0
+ while [[ $iters -le $MAX_ITERS ]]; do
+ kstat_file=$(grep -nrwl /proc/spl/kstat/zfs/$2/objset-0x* -e $3)
+ nunlinks=`cat $kstat_file | grep nunlinks | awk '{print $3}'`
+ nunlinked=`cat $kstat_file | grep nunlinked | awk '{print $3}'`
+ usize=$(($nunlinks - $nunlinked))
+ if [[ $iters == $MAX_ITERS && $usize == $1 ]]; then
+ return 0
+ fi
+ if [[ $usize == $last_usize ]]; then
+ (( iters++ ))
+ else
+ iters=0
+ fi
+ last_usize=$usize
+ done
+
+ log_note "Unexpected unlinked set size: $last_usize, expected $1"
+ return 1
+}
+
+
+default_unlink_sp=$(get_tunable UNLINK_SUSPEND_PROGRESS)
+
+log_onexit cleanup
+
+log_assert "Unlinked list drain does not hold up mounting of fs"
+
+for fs in 1 2 3; do
+ set -A xattrs on sa off
+ for xa in ${xattrs[@]}; do
+ # setup fs and ensure all deleted files got into unliked set
+ log_must mounted $TESTDIR.$fs
+
+ log_must zfs set xattr=$xa $TESTPOOL/$TESTFS.$fs
+
+ if [[ $xa == off ]]; then
+ for fn in $(seq 1 175); do
+ log_must mkfile 128k $TESTDIR.$fs/file-$fn
+ done
+ else
+ log_must xattrtest -f 175 -x 3 -r -k -p $TESTDIR.$fs
+ fi
+
+ log_must set_tunable32 UNLINK_SUSPEND_PROGRESS 1
+ log_must unlinked_size_is 0 $TESTPOOL $TESTPOOL/$TESTFS.$fs
+
+ # build up unlinked set
+ for fn in $(seq 1 100); do
+ log_must eval "rm $TESTDIR.$fs/file-$fn &"
+ done
+ log_must unlinked_size_is 100 $TESTPOOL $TESTPOOL/$TESTFS.$fs
+
+ # test that we can mount fs without emptying the unlinked list
+ log_must zfs umount $TESTPOOL/$TESTFS.$fs
+ log_must unmounted $TESTDIR.$fs
+ log_must zfs mount $TESTPOOL/$TESTFS.$fs
+ log_must mounted $TESTDIR.$fs
+ log_must unlinked_size_is 100 $TESTPOOL $TESTPOOL/$TESTFS.$fs
+
+ # confirm we can drain and add to unlinked set at the same time
+ log_must set_tunable32 UNLINK_SUSPEND_PROGRESS 0
+ log_must zfs umount $TESTPOOL/$TESTFS.$fs
+ log_must zfs mount $TESTPOOL/$TESTFS.$fs
+ for fn in $(seq 101 175); do
+ log_must eval "rm $TESTDIR.$fs/file-$fn &"
+ done
+ log_must unlinked_size_is 0 $TESTPOOL $TESTPOOL/$TESTFS.$fs
+ done
+done
+
+log_pass "Confirmed unlinked list drain does not hold up mounting of fs"
diff --git a/tests/zfs-tests/tests/functional/mount/umountall_001.ksh b/tests/zfs-tests/tests/functional/mount/umountall_001.ksh
new file mode 100755
index 000000000000..814c831e408c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mount/umountall_001.ksh
@@ -0,0 +1,81 @@
+#!/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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# There are myriad problems associated with trying to test umountall in a way
+# that works reliable across different systems. Some filesystems won't unmount
+# because they're busy. Some won't remount because they were legacy mounts in
+# the first place. etc...
+# Make a best approximation by calling umountall with the -n option, and verify
+# that the list of things it would try to unmout makes sense.
+#
+# STRATEGY:
+# 1. Make a list of file systems umountall is known to ignore.
+# 2. Append all ZFS file systems on this system.
+# 3. Run umountall -n and verify the file systems it reports are in the list.
+#
+
+log_must zfs mount -a
+for fs in 1 2 3 ; do
+ log_must mounted $TESTPOOL/$TESTFS.$fs
+done
+
+# This is the list we check the output of umountall -n against. We seed it
+# with these values because umountall will ignore them, and they're possible
+# (though most are improbable) ZFS filesystem mountpoints.
+zfs_list="/ /lib /sbin /tmp /usr /var /var/adm /var/run"
+
+# Append our ZFS filesystems to the list, not worrying about duplicates.
+if is_linux; then
+ typeset mounts=$(mount | awk '{if ($5 == "zfs") print $3}')
+elif is_freebsd; then
+ typeset mounts=$(mount -p | awk '{if ($3 == "zfs") print $2}')
+else
+ typeset mounts=$(mount -p | awk '{if ($4 == "zfs") print $3}')
+fi
+
+for fs in $mounts; do
+ zfs_list="$zfs_list $fs"
+done
+
+if is_linux; then
+ mounts=$(umount --fake -av -t zfs 2>&1 | \
+ grep "successfully umounted" | awk '{print $1}')
+ # Fallback to /proc/mounts for umount(8) (util-linux-ng 2.17.2)
+ if [[ -z $mounts ]]; then
+ mounts=$(awk '/zfs/ { print $2 }' /proc/mounts)
+ fi
+elif is_freebsd; then
+ # Umountall and umount not supported on FreeBSD
+ mounts=$(mount -t zfs | sort -r | awk '{print $3}')
+else
+ mounts=$(umountall -n -F zfs 2>&1 | awk '{print $2}')
+fi
+
+fs=''
+for fs in $mounts; do
+ for i in $zfs_list; do
+ [[ $fs = $i ]] && continue 2
+ done
+ log_fail "umountall -n -F zfs tried to unmount $fs"
+done
+[[ -n $mounts ]] || log_fail "umountall -n -F zfs produced no output"
+
+log_pass "All ZFS file systems would have been unmounted"
diff --git a/tests/zfs-tests/tests/functional/mv_files/Makefile.am b/tests/zfs-tests/tests/functional/mv_files/Makefile.am
new file mode 100644
index 000000000000..cec02140e307
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mv_files/Makefile.am
@@ -0,0 +1,11 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/mv_files
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ mv_files_001_pos.ksh \
+ mv_files_002_pos.ksh \
+ random_creation.ksh
+
+dist_pkgdata_DATA = \
+ mv_files.cfg \
+ mv_files_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/mv_files/cleanup.ksh b/tests/zfs-tests/tests/functional/mv_files/cleanup.ksh
new file mode 100755
index 000000000000..a664433743af
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mv_files/cleanup.ksh
@@ -0,0 +1,48 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mv_files/mv_files_common.kshlib
+
+verify_runnable "global"
+
+[[ -f $TEST_BASE_DIR/exitsZero.ksh ]] && \
+ log_must rm -f $TEST_BASE_DIR/exitsZero.ksh
+[[ -f $TEST_BASE_DIR/testbackgprocs.ksh ]] && \
+ log_must rm -f $TEST_BASE_DIR/testbackgprocs.ksh
+
+ismounted $TESTPOOL/$TESTFS_TGT
+(( $? == 0 )) && log_must zfs umount $TESTPOOL/$TESTFS_TGT
+log_must zfs destroy $TESTPOOL/$TESTFS_TGT
+
+[[ -d $TESTDIR_TGT ]] && log_must rm -rf $TESTDIR_TGT
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/mv_files/mv_files.cfg b/tests/zfs-tests/tests/functional/mv_files/mv_files.cfg
new file mode 100644
index 000000000000..ed28ff1efd27
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mv_files/mv_files.cfg
@@ -0,0 +1,50 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+export DISK=${DISKS%% *}
+export DISKSARRAY=$DISKS
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+set_device_dir
+
+export TESTFILE=testfile
+
+export TESTDIR_TGT=${TEST_BASE_DIR%%/}/testdir_tgt
+export TESTFS_TGT=testzfs_tgt
+export OLDDIR=$TESTDIR/olddir
+export NEWDIR_IN_FS=$TESTDIR/newdir
+export NEWDIR_ACROSS_FS=$TESTDIR_TGT/newdir
+
+export MVNUMFILES=2000 # <number of files to start>
+export MVNUMINCR=1000 # <number of files to be increased to>
+export GANGPIDS=50 # <number of limit for parallel background running process>
+
+# controls the "random_creation" test
+export RC_PASS1=65536 # <number of files to create in the first directory>
+export RC_PASS2=8192 # <process this many files into the second directory
diff --git a/tests/zfs-tests/tests/functional/mv_files/mv_files_001_pos.ksh b/tests/zfs-tests/tests/functional/mv_files/mv_files_001_pos.ksh
new file mode 100755
index 000000000000..4ea5e3db3889
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mv_files/mv_files_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mv_files/mv_files_common.kshlib
+
+#
+# DESCRIPTION:
+# Doing a 'mv' of a large amount of files between two directories
+# within a zfs filesystem works without errors.
+#
+# STRATEGY:
+#
+# 1. create a pool and a zfs filesystem
+# 2. create two directories within the filesystem
+# 3. create a large number of files within a directory
+# 4. Move files from one directory to another and back again
+# 5. validate file number
+# 6. increase the number of files to $MVNUMFILES + $MVNUMINCR
+# 7. repeat steps 3,4,5,6 above
+# 8. verify the data integrity
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ PIDS=""
+ rm -f $OLDDIR/* >/dev/null 2>&1
+ rm -f $NEWDIR_IN_FS/* >/dev/null 2>&1
+}
+
+log_assert "Doing a 'mv' of a large amount of files within a zfs filesystem" \
+ "works without errors."
+
+log_onexit cleanup
+
+mv_test $OLDDIR $NEWDIR_IN_FS
+(($? != 0 )) && log_fail "'mv' test failed to complete."
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/mv_files/mv_files_002_pos.ksh b/tests/zfs-tests/tests/functional/mv_files/mv_files_002_pos.ksh
new file mode 100755
index 000000000000..283770d4a4bf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mv_files/mv_files_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mv_files/mv_files_common.kshlib
+
+#
+# DESCRIPTION:
+# Doing a 'mv' of a large amount of files between two directories across
+# two zfs filesystems works without errors.
+#
+# STRATEGY:
+#
+# 1. create a pool and two zfs filesystems
+# 2. create a directory in each filesystem
+# 3. create a large number of files in a directory of a filesystem
+# 4. Move files from the directory to another directory in another
+# filesystem and back again
+# 5. validate file number
+# 6. increase the number of files to $MVNUMFILES + $MVNUMINCR
+# 7. repeat steps 3,4,5,6 above
+# 8. verify the data integrity
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ PIDS=""
+ rm -f $OLDDIR/* >/dev/null 2>&1
+ rm -f $NEWDIR_ACROSS_FS/* >/dev/null 2>&1
+}
+
+log_assert "Doing a 'mv' of a large amount of files across two zfs filesystems" \
+ "works without errors."
+
+log_onexit cleanup
+
+mv_test $OLDDIR $NEWDIR_ACROSS_FS
+(($? != 0 )) && \
+ log_fail "'mv' test failed to complete."
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib b/tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib
new file mode 100644
index 000000000000..6b925501b088
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mv_files/mv_files_common.kshlib
@@ -0,0 +1,205 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/mv_files/mv_files.cfg
+
+#
+# Determine whether this version of the ksh being
+# executed has a bug where the limit of background
+# processes of 25.
+#
+function check_bg_procs_limit_num
+{
+echo "#!/bin/ksh" > $TEST_BASE_DIR/exitsZero.ksh
+echo "exit 0" >> $TEST_BASE_DIR/exitsZero.ksh
+chmod 777 $TEST_BASE_DIR/exitsZero.ksh
+
+cat <<EOF > $TEST_BASE_DIR/testbackgprocs.ksh
+#!/bin/ksh
+#
+# exitsZero.ksh is a one line script
+# that exit with status of "0"
+#
+
+PIDS=""
+typeset -i i=1
+while [ \$i -le 50 ]
+do
+ $TEST_BASE_DIR/exitsZero.ksh &
+ PIDS="\$PIDS \$!"
+ (( i = i + 1 ))
+done
+
+sleep 1
+
+for pid in \$PIDS
+do
+ wait \$pid
+ (( \$? == 127 )) && exit 1
+done
+exit 0
+EOF
+
+ksh $TEST_BASE_DIR/testbackgprocs.ksh
+if [[ $? -eq 1 ]]; then
+#
+# Current ksh being executed has a limit
+# of 25 background processes.
+#
+ return 1
+else
+ return 0
+fi
+}
+
+function init_setup
+{
+
+ typeset disklist=$1
+
+ create_pool $TESTPOOL "$disklist"
+
+ if ! is_global_zone ; then
+ reexport_pool
+ fi
+
+ rm -rf $TESTDIR || log_unresolved Could not remove $TESTDIR
+ mkdir -p $TESTDIR || log_unresolved Could not create $TESTDIR
+
+ rm -rf $TESTDIR_TGT || log_unresolved Could not remove $TESTDIR_TGT
+ mkdir -p $TESTDIR_TGT || log_unresolved Could not create $TESTDIR_TGT
+
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+
+ log_must zfs create $TESTPOOL/$TESTFS_TGT
+ log_must zfs set mountpoint=$TESTDIR_TGT $TESTPOOL/$TESTFS_TGT
+
+ mkdir -p $OLDDIR || log_unresolved Could not create $OLDDIR
+ mkdir -p $NEWDIR_IN_FS || log_unresolved Could not create $NEWDIR_IN_FS
+ mkdir -p $NEWDIR_ACROSS_FS || log_unresolved Could not create $NEWDIR_ACROSS_FS
+
+}
+
+#
+# Generate given number files in a
+# directory of zfs file system
+# $1 - the directory holds the generated files
+# $2 - number of to-be-generated files
+#
+
+function generate_files
+{
+ typeset -i count
+ typeset -i proc_num=0
+
+ if (( $2 == $MVNUMFILES )); then
+ count=1
+ else
+ count=$MVNUMFILES+1
+ fi
+
+ while (( count <= $2 ))
+ do
+ cp /etc/passwd $1/file_$count \
+ > /dev/null 2>&1 &
+
+ (( proc_num = proc_num + 1 ))
+
+ if (( proc_num >= GANGPIDS )); then
+ wait
+ proc_num=0
+ fi
+
+ (( count = count + 1 ))
+ done
+
+ wait
+}
+
+#
+# Move given number files from one directory to
+# another directory in parallel
+# $1 - source directory
+# $2 - target directory
+#
+function mv_files
+{
+ find $1 -type f -print | xargs -I "{}" \
+ mv {} $2 > /dev/null 2>&1
+}
+
+#
+# Count the files number after moving, and
+# compare it with the original number
+# $1 - directory that to be operated
+# $2 - original files number
+#
+function count_files
+{
+ typeset -i file_num
+ file_num=`find $1 -type f -print | \
+ wc -l`
+ (( file_num != $2 )) && \
+ log_fail "The file number of target directory"\
+ "$2 is not equal to that of the source "\
+ "directory $1"
+
+}
+
+#
+# Running the 'mv' test
+# $1 - old directory
+# $2 - new directory
+#
+function mv_test
+{
+ typeset old=$1
+ typeset new=$2
+
+ typeset -i inc_num=$(( MVNUMFILES + MVNUMINCR ))
+ typeset -i num=0
+
+ for num in $MVNUMFILES $inc_num
+ do
+ generate_files $old $num
+
+ mv_files $old $new
+ count_files $new $num
+
+ mv_files $new $old
+ count_files $old $num
+ done
+
+ typeset dir=$(get_device_dir $DISKS)
+ verify_filesys "$TESTPOOL" "$TESTPOOL/$TESTFS" "$dir"
+
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/mv_files/random_creation.ksh b/tests/zfs-tests/tests/functional/mv_files/random_creation.ksh
new file mode 100755
index 000000000000..05ddf6298417
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mv_files/random_creation.ksh
@@ -0,0 +1,48 @@
+#!/bin/ksh -p
+
+source "${STF_SUITE}/include/libtest.shlib"
+source "${STF_SUITE}/tests/functional/mv_files/mv_files.cfg"
+
+# This will test the #7401 regression.
+log_assert "Check that creating many files quickly is safe"
+
+DIR="${TESTDIR}/RANDOM_SMALL"
+
+log_must mkdir "${DIR}"
+
+count=0
+for i in $(range_shuffle 1 "${RC_PASS1}") ; do
+ if ! touch "${DIR}/${i}" ; then
+ log_fail "error creating ${i} after ${count} files"
+ fi
+ count=$((count+1))
+done
+
+visible="$(find "${DIR}" -type f|wc -l)"
+
+log_must [ "${visible}" -eq "${RC_PASS1}" ]
+
+log_assert "Check that creating them in another order is safe"
+
+DIR1="${TESTDIR}/RANDOM2"
+
+log_must mv "${DIR}" "${DIR1}"
+
+log_must mkdir "${DIR}"
+
+count=0
+for i in $(cd "${DIR1}" ; ls -U . ) ; do
+ if ! touch "${DIR}/${i}" ; then
+ log_fail "error creating ${i} after ${count} files"
+ fi
+ count=$((count+1))
+ [ "${count}" -eq "${RC_PASS2}" ] && break
+done
+
+visible="$(find "${DIR}" -type f|wc -l)"
+
+if [ "${visible}" -eq "${RC_PASS2}" ] ; then
+ log_pass "Created all ${RC_PASS2} files"
+else
+ log_fail "Number of created files ${visible} is not ${RC_PASS2}"
+fi
diff --git a/tests/zfs-tests/tests/functional/mv_files/setup.ksh b/tests/zfs-tests/tests/functional/mv_files/setup.ksh
new file mode 100755
index 000000000000..e4e97b16d5d4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/mv_files/setup.ksh
@@ -0,0 +1,47 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/mv_files/mv_files_common.kshlib
+
+verify_runnable "global"
+
+check_bg_procs_limit_num
+if [[ $? -ne 0 ]]; then
+ log_note "ksh background process limit number is 25"
+ export GANGPIDS=25
+fi
+
+export PIDS=""
+
+init_setup $DISK
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/nestedfs/Makefile.am b/tests/zfs-tests/tests/functional/nestedfs/Makefile.am
new file mode 100644
index 000000000000..6a5ecf2d9a7f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nestedfs/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/nestedfs
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ nestedfs_001_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/nestedfs/cleanup.ksh b/tests/zfs-tests/tests/functional/nestedfs/cleanup.ksh
new file mode 100755
index 000000000000..c4c369145dfc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nestedfs/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_container_cleanup
diff --git a/tests/zfs-tests/tests/functional/nestedfs/nestedfs_001_pos.ksh b/tests/zfs-tests/tests/functional/nestedfs/nestedfs_001_pos.ksh
new file mode 100755
index 000000000000..b576b78c8aa5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nestedfs/nestedfs_001_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.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Given a pool create a nested file system and a ZFS file system
+# in the nested file system. Populate the file system.
+#
+# As a sub-assertion, the test verifies that a nested file system with
+# a mounted file system cannot be destroyed.
+#
+# STRATEGY:
+# 1. Create a file in the new mountpoint
+# 2. Unmount the new mountpoint
+# 3. Show a nested file system with file systems cannot be destroyed
+#
+
+verify_runnable "both"
+
+log_assert "Verify a nested file system can be created/destroyed."
+
+log_must file_write -o create -f $TESTDIR1/file -b 8192 -c 600 -d 0
+log_must zfs unmount $TESTDIR1
+
+log_note "Verify that a nested file system with a mounted file system "\
+ "cannot be destroyed."
+log_mustnot zfs destroy $TESTPOOL/$TESTCTR
+
+log_pass "A nested file system was successfully populated."
diff --git a/tests/zfs-tests/tests/functional/nestedfs/setup.ksh b/tests/zfs-tests/tests/functional/nestedfs/setup.ksh
new file mode 100755
index 000000000000..677cb12d79ac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nestedfs/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_container_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/no_space/Makefile.am b/tests/zfs-tests/tests/functional/no_space/Makefile.am
new file mode 100644
index 000000000000..c2e42bc2ada4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/Makefile.am
@@ -0,0 +1,11 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/no_space
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ enospc_001_pos.ksh \
+ enospc_002_pos.ksh \
+ enospc_003_pos.ksh \
+ enospc_df.ksh
+
+dist_pkgdata_DATA = \
+ enospc.cfg
diff --git a/tests/zfs-tests/tests/functional/no_space/cleanup.ksh b/tests/zfs-tests/tests/functional/no_space/cleanup.ksh
new file mode 100755
index 000000000000..62b28df8ef5a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/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 2009 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/no_space/enospc.cfg
+
+verify_runnable "global"
+
+default_cleanup_noexit
+log_must rm -f $DISK_SMALL $DISK_LARGE
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc.cfg b/tests/zfs-tests/tests/functional/no_space/enospc.cfg
new file mode 100644
index 000000000000..0b8298c03165
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/enospc.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) 2013 by Delphix. All rights reserved.
+#
+
+DISK_SMALL=${TEST_BASE_DIR%%/}/vdev_small
+DISK_LARGE=${TEST_BASE_DIR%%/}/vdev_large
+
+export SIZE_SMALL=100m
+export SIZE_LARGE=512m
+export ENOSPC=28
+export BLOCKSZ=8192
+export NUM_WRITES=65536
+export DATA=0
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc_001_pos.ksh b/tests/zfs-tests/tests/functional/no_space/enospc_001_pos.ksh
new file mode 100755
index 000000000000..56beb4e71e17
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/enospc_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 2007 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/no_space/enospc.cfg
+
+#
+# DESCRIPTION:
+# ENOSPC is returned on an attempt to write a second file
+# to a file system after a first file was written that terminated
+# with ENOSPC on a cleanly initialized file system.
+#
+# STRATEGY:
+# 1. Write a file until the file system is full.
+# 2. Ensure that ENOSPC is returned.
+# 3. Write a second file while the file system remains full.
+# 4. Verify the return code is ENOSPC.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ default_cleanup_noexit
+}
+
+log_onexit cleanup
+
+log_assert "ENOSPC is returned when file system is full."
+
+default_setup_noexit $DISK_SMALL
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+
+log_note "Writing file: $TESTFILE0 until ENOSPC."
+file_write -o create -f $TESTDIR/$TESTFILE0 -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+ret=$?
+
+(( $ret != $ENOSPC )) && \
+ log_fail "$TESTFILE0 returned: $ret rather than ENOSPC."
+
+log_note "Write another file: $TESTFILE1 but expect ENOSPC."
+file_write -o create -f $TESTDIR/$TESTFILE1 -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+ret=$?
+
+(( $ret != $ENOSPC )) && \
+ log_fail "$TESTFILE1 returned: $ret rather than ENOSPC."
+
+log_pass "ENOSPC returned as expected."
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc_002_pos.ksh b/tests/zfs-tests/tests/functional/no_space/enospc_002_pos.ksh
new file mode 100755
index 000000000000..db6ee6ba7ca5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/enospc_002_pos.ksh
@@ -0,0 +1,92 @@
+#!/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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/no_space/enospc.cfg
+
+#
+# DESCRIPTION:
+# After filling a filesystem, certain zfs commands are allowed.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must_busy zpool destroy -f $TESTPOOL
+}
+
+log_onexit cleanup
+
+log_assert "ENOSPC is returned when file system is full."
+
+default_setup_noexit $DISK_SMALL
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap
+
+#
+# Completely fill the pool in order to ensure the commands below will more
+# reliably succeed or fail as a result of lack of space. Care is taken to
+# force multiple transaction groups to ensure as many recently freed blocks
+# as possible are reallocated.
+#
+log_note "Writing files until ENOSPC."
+
+for i in $(seq 30); do
+ file_write -o create -f $TESTDIR/file.$i -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+ ret=$?
+ (( $ret != $ENOSPC )) && \
+ log_fail "file.$i returned: $ret rather than ENOSPC."
+
+ log_must zpool sync -f
+done
+
+log_mustnot_expect space zfs create $TESTPOOL/$TESTFS/subfs
+log_mustnot_expect space zfs clone $TESTPOOL/$TESTFS@snap $TESTPOOL/clone
+log_mustnot_expect space zfs snapshot $TESTPOOL/$TESTFS@snap2
+log_mustnot_expect space zfs bookmark \
+ $TESTPOOL/$TESTFS@snap $TESTPOOL/$TESTFS#bookmark
+
+log_must zfs send $TESTPOOL/$TESTFS@snap > $TEST_BASE_DIR/stream.$$
+log_mustnot_expect space zfs receive $TESTPOOL/$TESTFS/recvd < $TEST_BASE_DIR/stream.$$
+log_must rm $TEST_BASE_DIR/stream.$$
+
+log_must zfs rename $TESTPOOL/$TESTFS@snap $TESTPOOL/$TESTFS@snap_newname
+log_must zfs rename $TESTPOOL/$TESTFS@snap_newname $TESTPOOL/$TESTFS@snap
+log_must zfs rename $TESTPOOL/$TESTFS $TESTPOOL/${TESTFS}_newname
+log_must zfs rename $TESTPOOL/${TESTFS}_newname $TESTPOOL/$TESTFS
+log_must zfs allow staff snapshot $TESTPOOL/$TESTFS
+log_must zfs unallow staff snapshot $TESTPOOL/$TESTFS
+log_must zfs set user:prop=value $TESTPOOL/$TESTFS
+log_must zfs set quota=1EB $TESTPOOL/$TESTFS
+log_must zfs set quota=none $TESTPOOL/$TESTFS
+log_must zfs set reservation=1KB $TESTPOOL/$TESTFS
+log_must zfs set reservation=none $TESTPOOL/$TESTFS
+log_must zpool scrub $TESTPOOL
+zpool scrub -s $TESTPOOL
+log_must zpool set comment="Use the force, Luke." $TESTPOOL
+log_must zpool set comment="" $TESTPOOL
+
+# destructive tests must come last
+log_must zfs rollback $TESTPOOL/$TESTFS@snap
+log_must zfs destroy $TESTPOOL/$TESTFS@snap
+
+log_pass "ENOSPC returned as expected."
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc_003_pos.ksh b/tests/zfs-tests/tests/functional/no_space/enospc_003_pos.ksh
new file mode 100755
index 000000000000..496e2a029c5c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/enospc_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 2017, loli10K. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/no_space/enospc.cfg
+. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib
+
+#
+# DESCRIPTION:
+# ENOSPC is returned on pools with large physical block size and small
+# recordsize.
+#
+# STRATEGY:
+# 1. Create a pool with property ashift=13 (8K block size)
+# 2. Set property recordsize=512 and copies=3 on the root dataset
+# 3. Write a file until the file system is full
+# 4. Verify the return code is ENOSPC
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ rm -f $testfile0
+}
+
+log_onexit cleanup
+
+log_assert "ENOSPC is returned on pools with large physical block size"
+
+typeset testfile0=${TESTDIR}/testfile0
+
+log_must zpool create -o ashift=13 $TESTPOOL1 $DISK_LARGE
+log_must zfs set mountpoint=$TESTDIR $TESTPOOL1
+log_must zfs set compression=off $TESTPOOL1
+log_must zfs set recordsize=512 $TESTPOOL1
+log_must zfs set copies=3 $TESTPOOL1
+
+log_note "Writing file: $testfile0 until ENOSPC."
+file_write -o create -f $testfile0 -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+ret=$?
+
+(( $ret != $ENOSPC )) && \
+ log_fail "$testfile0 returned: $ret rather than ENOSPC."
+
+log_pass "ENOSPC returned as expected."
diff --git a/tests/zfs-tests/tests/functional/no_space/enospc_df.ksh b/tests/zfs-tests/tests/functional/no_space/enospc_df.ksh
new file mode 100755
index 000000000000..b1eeaf2cc569
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/enospc_df.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) 2014, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2019 by Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/no_space/enospc.cfg
+
+#
+# DESCRIPTION:
+# After filling a filesystem, the df command produces the
+# expected result against the pool root filesystem.
+#
+# STRATEGY:
+# 1. Write a file until the child file system is full.
+# 2. Ensure that ENOSPC is returned.
+# 3. Unmount the child file system.
+# 4. Issue df -h command.
+# 5. Ensure pool root filesystem is included (issue #8253).
+# 6. Issue df -h <filesystem>.
+# 7. Ensure size and used are non-zero.
+#
+
+verify_runnable "both"
+
+log_onexit default_cleanup_noexit
+
+log_assert "Correct df output is returned when file system is full."
+
+default_setup_noexit $DISK_SMALL
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+
+log_note "Writing file: $TESTFILE0 until ENOSPC."
+file_write -o create -f $TESTDIR/$TESTFILE0 -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+ret=$?
+
+(( $ret != $ENOSPC )) && \
+ log_fail "$TESTFILE0 returned: $ret rather than ENOSPC."
+
+log_must zfs umount $TESTPOOL/$TESTFS
+
+# Ensure the pool root filesystem shows in df output.
+# If the pool was full (available == 0) and the pool
+# root filesystem had very little in it (used < 1 block),
+# the size reported to df was zero (issue #8253) and
+# df skipped the filesystem in its output.
+log_must eval "df -h | grep $TESTPOOL"
+
+# Confirm df size and used are non-zero.
+size=$(df -h /$TESTPOOL | grep $TESTPOOL | awk '{print $2}')
+used=$(df -h /$TESTPOOL | grep $TESTPOOL | awk '{print $3}')
+if [[ "$size" = "0" ]] || [[ "$used" = "0" ]]
+then
+ log_fail "df failed with size $size and used $used."
+fi
+log_pass "df after ENOSPC works as expected."
diff --git a/tests/zfs-tests/tests/functional/no_space/setup.ksh b/tests/zfs-tests/tests/functional/no_space/setup.ksh
new file mode 100755
index 000000000000..7ab8f1473d66
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/no_space/setup.ksh
@@ -0,0 +1,40 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/no_space/enospc.cfg
+
+verify_runnable "global"
+
+log_must truncate -s $SIZE_SMALL $DISK_SMALL
+log_must truncate -s $SIZE_LARGE $DISK_LARGE
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/nopwrite/Makefile.am b/tests/zfs-tests/tests/functional/nopwrite/Makefile.am
new file mode 100644
index 000000000000..3f893c6382e6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/Makefile.am
@@ -0,0 +1,15 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/nopwrite
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ nopwrite_copies.ksh \
+ nopwrite_mtime.ksh \
+ nopwrite_negative.ksh \
+ nopwrite_promoted_clone.ksh \
+ nopwrite_recsize.ksh \
+ nopwrite_sync.ksh \
+ nopwrite_varying_compression.ksh \
+ nopwrite_volume.ksh
+
+dist_pkgdata_DATA = \
+ nopwrite.shlib
diff --git a/tests/zfs-tests/tests/functional/nopwrite/cleanup.ksh b/tests/zfs-tests/tests/functional/nopwrite/cleanup.ksh
new file mode 100755
index 000000000000..2d7b69aac8e0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/cleanup.ksh
@@ -0,0 +1,20 @@
+#!/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 by Delphix. All rights reserved.
+#
+
+. ${STF_SUITE}/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib b/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib
new file mode 100644
index 000000000000..139b4b26e5ed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite.shlib
@@ -0,0 +1,68 @@
+#
+# 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/math.shlib
+
+export TESTVOL="testvol.nopwrite"
+export VOLSIZE="256M"
+export MEGS="64"
+
+function verify_nopwrite
+{
+ typeset origin=$1
+ typeset snap=$2
+ typeset clone=$3
+ typeset low=1
+ typeset high=99
+
+ sync_pool
+ for i in origin snap clone; do
+ for j in used refer usedbychildren written; do
+ typeset ${i}_$j=$(get_prop $j $(eval echo \$$i))
+ done
+ done
+
+ #
+ # If we are dealing with a volume, deduct the refreserv from the used
+ # value to prevent real failures from being masked by the unexpected
+ # extra space. Also, volumes use more space for metadata, so adjust the
+ # percentages to be more forgiving.
+ #
+ if [[ "$(get_prop type $origin)" = "volume" ]]; then
+ typeset rr=$(get_prop refreserv $origin)
+ ((origin_used -= rr ))
+ low=2
+ high=98
+ fi
+
+ # These values should differ greatly with nopwrite.
+ within_percent $origin_used $clone_used $low && return 1
+ within_percent $origin_refer $origin_usedbychildren $low && return 1
+ within_percent $snap_written $clone_written $low && return 1
+
+ # These values should be nearly the same with nopwrite.
+ within_percent $origin_used $clone_refer $high || return 1
+ within_percent $origin_used $snap_refer $high || return 1
+
+ #
+ # The comparisons below should pass regardless of nopwrite. They're
+ # here for sanity.
+ #
+ typeset deadlist=$(zdb -Pddd $clone | awk '/Deadlist:/ {print $2}')
+ within_percent $deadlist $clone_written $high || return 1
+ within_percent $snap_refer $snap_written $high || return 1
+
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite_copies.ksh b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_copies.ksh
new file mode 100755
index 000000000000..3971820966f1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_copies.ksh
@@ -0,0 +1,71 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+#
+# Description:
+# Verify that nopwrite is not enabled if the copies property changes
+#
+# Strategy:
+# 1. Create a clone with copies set higher than the origin fs
+# 2. Verify that nopwrite is in use.
+# 3. Repeat with the number of copies decreased.
+#
+
+verify_runnable "global"
+origin="$TESTPOOL/$TESTFS"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $origin && log_must zfs destroy -R $origin
+ log_must zfs create -o mountpoint=$TESTDIR $origin
+}
+
+log_assert "nopwrite requires copies property to remain constant"
+
+# Verify nopwrite is disabled with increased redundancy
+log_must zfs set compress=on $origin
+log_must zfs set checksum=sha256 $origin
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $origin/clone
+zfs set copies=3 $origin/clone
+dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+
+# Verify nopwrite is disabled with decreased redundancy
+zfs destroy -R $origin || log_fail "Couldn't destroy $origin"
+zfs create -o mountpoint=$TESTDIR $origin || \
+ log_fail "Couldn't recreate $origin"
+log_must zfs set compress=on $origin
+log_must zfs set copies=3 $origin
+log_must zfs set checksum=sha256 $origin
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $origin/clone
+zfs set copies=1 $origin/clone
+dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+
+log_pass "nopwrite requires copies property to remain constant"
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite_mtime.ksh b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_mtime.ksh
new file mode 100755
index 000000000000..039b661e2fb9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_mtime.ksh
@@ -0,0 +1,89 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+#
+# Description:
+# Verify that nopwrite still updates file metadata correctly
+#
+# Strategy:
+# 1. Create a clone with nopwrite enabled.
+# 2. Write to the file in that clone and verify the mtime and ctime change,
+# but the atime does not.
+#
+
+verify_runnable "global"
+origin="$TESTPOOL/$TESTFS"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $origin && log_must zfs destroy -R $origin
+ log_must zfs create -o mountpoint=$TESTDIR $origin
+}
+
+log_assert "nopwrite updates file metadata correctly"
+
+log_must zfs set compress=on $origin
+log_must zfs set checksum=sha256 $origin
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $origin/clone
+
+if is_linux; then
+ o_atime=$(stat -c %X $TESTDIR/clone/file)
+ o_ctime=$(stat -c %Z $TESTDIR/clone/file)
+ o_mtime=$(stat -c %Y $TESTDIR/clone/file)
+elif is_freebsd; then
+ o_atime=$(stat -f "%a" $TESTDIR/clone/file)
+ o_ctime=$(stat -f "%c" $TESTDIR/clone/file)
+ o_mtime=$(stat -f "%m" $TESTDIR/clone/file)
+else
+ o_atime=$(ls -E% all $TESTDIR/clone/file | awk '/atime/ {print $4}')
+ o_ctime=$(ls -E% all $TESTDIR/clone/file | awk '/ctime/ {print $4}')
+ o_mtime=$(ls -E% all $TESTDIR/clone/file | awk '/mtime/ {print $4}')
+fi
+
+sleep 1
+dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+sleep 1
+
+if is_linux; then
+ atime=$(stat -c %X $TESTDIR/clone/file)
+ ctime=$(stat -c %Z $TESTDIR/clone/file)
+ mtime=$(stat -c %Y $TESTDIR/clone/file)
+elif is_freebsd; then
+ atime=$(stat -f "%a" $TESTDIR/clone/file)
+ ctime=$(stat -f "%c" $TESTDIR/clone/file)
+ mtime=$(stat -f "%m" $TESTDIR/clone/file)
+else
+ atime=$(ls -E% all $TESTDIR/clone/file | awk '/atime/ {print $4}')
+ ctime=$(ls -E% all $TESTDIR/clone/file | awk '/ctime/ {print $4}')
+ mtime=$(ls -E% all $TESTDIR/clone/file | awk '/mtime/ {print $4}')
+fi
+
+[[ $o_atime = $atime ]] || log_fail "atime changed: $o_atime $atime"
+[[ $o_ctime = $ctime ]] && log_fail "ctime unchanged: $o_ctime $ctime"
+[[ $o_mtime = $mtime ]] && log_fail "mtime unchanged: $o_mtime $mtime"
+
+log_must verify_nopwrite $origin $origin@a $origin/clone
+
+log_pass "nopwrite updates file metadata correctly"
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite_negative.ksh b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_negative.ksh
new file mode 100755
index 000000000000..8b0b9b549920
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_negative.ksh
@@ -0,0 +1,90 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+#
+# Description:
+# Verify that duplicate writes to a clone are accounted as new data if the
+# prerequisites for nopwrite are not met.
+#
+# Scenarios:
+# 1. The file in the origin ds is written without compression or sha256.
+# 2. The file in the origin ds is written before sha256 checksum is turned on.
+# 3. The clone does not have compression.
+# 4. The clone does not have the appropriate checksum.
+#
+
+verify_runnable "global"
+origin="$TESTPOOL/$TESTFS"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $origin && log_must zfs destroy -R $origin
+ log_must zfs create -o mountpoint=$TESTDIR $origin
+}
+
+log_assert "nopwrite isn't enabled without the prerequisites"
+
+# Data written into origin fs without compression or sha256
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd of $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone -o compress=on $origin@a $origin/clone
+log_must zfs set checksum=sha256 $origin/clone
+dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+zfs destroy -R $origin@a || log_fail "zfs destroy failed"
+log_must rm -f $TESTDIR/file
+
+# Data written to origin fs before checksum enabled
+log_must zfs set compress=on $origin
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+log_must zfs set checksum=sha256 $origin
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $origin/clone
+dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+zfs destroy -R $origin@a || log_fail "zfs destroy failed"
+log_must rm -f $TESTDIR/file
+
+# Clone with compression=off
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone -o compress=off $origin@a $origin/clone
+dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+zfs destroy -R $origin@a || log_fail "zfs destroy failed"
+log_must rm -f $TESTDIR/file
+
+# Clone with fletcher4, rather than sha256
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone -o checksum=fletcher4 $origin@a $origin/clone
+dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+
+log_pass "nopwrite isn't enabled without the prerequisites"
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite_promoted_clone.ksh b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_promoted_clone.ksh
new file mode 100755
index 000000000000..f9e6e83b7a8d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_promoted_clone.ksh
@@ -0,0 +1,58 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+#
+# Description:
+# Verify that nopwrite still works for a dataset that becomes a clone via
+# promotion.
+#
+# Strategy:
+# 1. Create a clone suitable for nopwrite.
+# 2. Disable compression and checksum on the clone, and promote it.
+# 3. Overwrite the file in the clone (former origin fs) and verify it
+# consumes no additional space.
+#
+
+verify_runnable "global"
+origin="$TESTPOOL/$TESTFS"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $origin && log_must zfs destroy -R $TESTPOOL/clone
+ log_must zfs create -o mountpoint=$TESTDIR $origin
+}
+
+log_assert "nopwrite works on a dataset that becomes a clone via promotion."
+
+log_must zfs set compress=on $origin
+log_must zfs set checksum=sha256 $origin
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $TESTPOOL/clone
+log_must zfs set compress=off $TESTPOOL/clone
+log_must zfs set checksum=off $TESTPOOL/clone
+log_must zfs promote $TESTPOOL/clone
+dd if=/$TESTPOOL/clone/file of=/$TESTDIR/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_must verify_nopwrite $TESTPOOL/clone $TESTPOOL/clone@a $origin
+
+log_pass "nopwrite works on a dataset that becomes a clone via promotion."
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite_recsize.ksh b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_recsize.ksh
new file mode 100755
index 000000000000..14caedbf204a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_recsize.ksh
@@ -0,0 +1,57 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+#
+# Description:
+# Verify that nopwrite works regardless of recsize property setting.
+#
+# Strategy:
+# 1. Create an origin fs that's suitable to make nopwrite clones.
+# 2. For each possible recsize, create a clone that inherits the compress and
+# checksum, and verify overwriting the origin file consumes no new space.
+#
+
+verify_runnable "global"
+origin="$TESTPOOL/$TESTFS"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $origin && log_must zfs destroy -R $origin
+ log_must zfs create -o mountpoint=$TESTDIR $origin
+}
+
+log_assert "nopwrite updates file metadata correctly"
+
+log_must zfs set compress=on $origin
+log_must zfs set checksum=sha256 $origin
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $origin/clone
+
+for rs in 512 1024 2048 4096 8192 16384 32768 65536 131072 ; do
+ log_must zfs set recsize=$rs $origin/clone
+ dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc > $TEST_BASE_DIR/null 2>&1 || log_fail "dd failed."
+ log_must verify_nopwrite $origin $origin@a $origin/clone
+done
+
+log_pass "nopwrite updates file metadata correctly"
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh
new file mode 100755
index 000000000000..bd38883d7578
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_sync.ksh
@@ -0,0 +1,55 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+#
+# Description:
+# Verify that nopwrite works for sync writes
+#
+# Strategy:
+# 1. Create an origin fs with compression and sha256.
+# 2. Clone origin such that it inherits the properties.
+# 3. Use dd with the sync flag to test the sync write path.
+#
+
+verify_runnable "global"
+origin="$TESTPOOL/$TESTFS"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $origin && log_must zfs destroy -R $origin
+ log_must zfs create -o mountpoint=$TESTDIR $origin
+}
+
+log_assert "nopwrite works for sync writes"
+
+log_must zfs set compress=on $origin
+log_must zfs set checksum=sha256 $origin
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS oflag=sync \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $origin/clone
+
+dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+
+log_must verify_nopwrite $origin $origin@a $origin/clone
+
+log_pass "nopwrite works for sync writes"
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite_varying_compression.ksh b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_varying_compression.ksh
new file mode 100755
index 000000000000..d256876a9c45
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_varying_compression.ksh
@@ -0,0 +1,65 @@
+#!/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, Delphix. All rights reserved.
+# Copyright (c) 2019, Kjeld Schouten-Lebbing. All Rights Reserved.
+#
+
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+#
+# Description:
+# Verify that if the checksum on the origin and clone is sha256, any compression
+# algorithm enables nopwrite.
+#
+# Strategy:
+# 1. Create an origin dataset with compression and sha256 checksum.
+# 2. Write a 64M file into the origin dataset.
+# 3. For each of 4 randomly chosen compression types:
+# 3a. Create a snap and clone (inheriting the checksum property) of the origin.
+# 3b. Apply the compression property to the clone.
+# 3c. Write the same 64M of data into the file that exists in the clone.
+# 3d. Verify that no new space was consumed.
+#
+
+verify_runnable "global"
+origin="$TESTPOOL/$TESTFS"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $origin && log_must zfs destroy -R $origin
+ log_must zfs create -o mountpoint=$TESTDIR $origin
+}
+
+log_assert "nopwrite works with sha256 and any compression algorithm"
+
+log_must zfs set compress=on $origin
+log_must zfs set checksum=sha256 $origin
+dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=$MEGS conv=notrunc \
+ >/dev/null 2>&1 || log_fail "initial dd failed."
+
+# Verify nop_write for all compression algorithms except "off"
+for i in "${compress_prop_vals[@]:1}"; do
+ zfs snapshot $origin@a || log_fail "zfs snap failed"
+ log_must zfs clone -o compress=$i $origin@a $origin/clone
+ dd if=/$TESTDIR/file of=/$TESTDIR/clone/file bs=1024k count=$MEGS \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+ log_must verify_nopwrite $origin $origin@a $origin/clone
+ zfs destroy -R $origin@a || log_fail "zfs destroy failed"
+done
+
+log_pass "nopwrite works with sha256 and any compression algorithm"
diff --git a/tests/zfs-tests/tests/functional/nopwrite/nopwrite_volume.ksh b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_volume.ksh
new file mode 100755
index 000000000000..a118b982240c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/nopwrite_volume.ksh
@@ -0,0 +1,59 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+#
+# Description:
+# Verify that nopwrite cannot be enabled on volumes
+#
+# Strategy:
+# 1. Create a clone of a volume that fits the criteria for nopwrite.
+# 2. Overwrite the same blocks from the origin vol and verify that
+# new space is consumed.
+#
+
+verify_runnable "global"
+origin="$TESTPOOL/$TESTVOL"
+clone="$TESTPOOL/clone"
+vol="${ZVOL_RDEVDIR}/$origin"
+volclone="${ZVOL_RDEVDIR}/$clone"
+log_onexit cleanup
+
+function cleanup
+{
+ datasetexists $origin && log_must zfs destroy -R $origin
+ # No need to recreate the volume as no other tests expect it.
+}
+
+log_assert "nopwrite works on volumes"
+
+log_must zfs set compress=on $origin
+log_must zfs set checksum=sha256 $origin
+dd if=/dev/urandom of=$vol bs=8192 count=4096 conv=notrunc >/dev/null \
+ 2>&1 || log_fail "dd into $origin failed."
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $clone
+log_must zfs set compress=on $clone
+log_must zfs set checksum=sha256 $clone
+block_device_wait
+dd if=$vol of=$volclone bs=8192 count=4096 conv=notrunc >/dev/null 2>&1 || \
+ log_fail "dd into $clone failed."
+log_must verify_nopwrite $origin $origin@a $clone
+
+log_pass "nopwrite works on volumes"
diff --git a/tests/zfs-tests/tests/functional/nopwrite/setup.ksh b/tests/zfs-tests/tests/functional/nopwrite/setup.ksh
new file mode 100755
index 000000000000..17c68a6381b9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/nopwrite/setup.ksh
@@ -0,0 +1,23 @@
+#!/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 by Delphix. All rights reserved.
+#
+
+. ${STF_SUITE}/include/libtest.shlib
+. ${STF_SUITE}/tests/functional/nopwrite/nopwrite.shlib
+
+disk=${DISKS%% *}
+
+default_volume_setup $disk
diff --git a/tests/zfs-tests/tests/functional/online_offline/Makefile.am b/tests/zfs-tests/tests/functional/online_offline/Makefile.am
new file mode 100644
index 000000000000..bd23f89e538a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/online_offline/Makefile.am
@@ -0,0 +1,10 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/online_offline
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ online_offline_001_pos.ksh \
+ online_offline_002_neg.ksh \
+ online_offline_003_neg.ksh
+
+dist_pkgdata_DATA = \
+ online_offline.cfg
diff --git a/tests/zfs-tests/tests/functional/online_offline/cleanup.ksh b/tests/zfs-tests/tests/functional/online_offline/cleanup.ksh
new file mode 100755
index 000000000000..b81a372638e3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/online_offline/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/online_offline/online_offline.cfg b/tests/zfs-tests/tests/functional/online_offline/online_offline.cfg
new file mode 100644
index 000000000000..ae4cb69adcb0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/online_offline/online_offline.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export TESTFILE=testfile.$$
+export TESTFILE1=testfile1.$$
+export HOLES_FILESIZE=${HOLES_FILESIZE-"67108864"} # 64 Mb
+export HOLES_BLKSIZE=${HOLES_BLKSIZE-"512"}
+export HOLES_SEED=${HOLES_SEED-""}
+export HOLES_FILEOFFSET=${HOLES_FILEOFFSET-""}
+export HOLES_COUNT=${HOLES_COUNT-"16384"} # FILESIZE/BLKSIZE/8
+export STF_TIMEOUT=3600
+
+export DISKSARRAY=$DISKS
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+set_device_dir
diff --git a/tests/zfs-tests/tests/functional/online_offline/online_offline_001_pos.ksh b/tests/zfs-tests/tests/functional/online_offline/online_offline_001_pos.ksh
new file mode 100755
index 000000000000..2fd913f40338
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/online_offline/online_offline_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/online_offline/online_offline.cfg
+
+#
+# DESCRIPTION:
+# Turning a disk offline and back online during I/O completes.
+#
+# STRATEGY:
+# 1. Create a mirror and start some random I/O
+# 2. For each disk in the mirror, set it offline and online
+# 3. Verify the integrity of the file system and the resilvering.
+#
+
+verify_runnable "global"
+log_onexit cleanup
+
+DISKLIST=$(get_disklist $TESTPOOL)
+
+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
+
+ kill $killpid >/dev/null 2>&1
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Turning a disk offline and back online during I/O completes."
+
+file_trunc -f $((64 * 1024 * 1024)) -b 8192 -c 0 -r $TESTDIR/$TESTFILE1 &
+typeset killpid="$! "
+
+for disk in $DISKLIST; do
+ for i in 'do_offline' 'do_offline_while_already_offline'; do
+ log_must zpool offline $TESTPOOL $disk
+ check_state $TESTPOOL $disk "offline"
+ if [[ $? != 0 ]]; then
+ log_fail "$disk of $TESTPOOL is not offline."
+ fi
+ 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
+
+ # Delay for resilver to complete
+ sleep 3
+done
+
+log_must kill $killpid
+sync
+
+typeset dir=$(get_device_dir $DISKS)
+verify_filesys "$TESTPOOL" "$TESTPOOL/$TESTFS" "$dir"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/online_offline/online_offline_002_neg.ksh b/tests/zfs-tests/tests/functional/online_offline/online_offline_002_neg.ksh
new file mode 100755
index 000000000000..19576a82100b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/online_offline/online_offline_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/online_offline/online_offline.cfg
+
+#
+# DESCRIPTION:
+# Turning disks in a pool offline should fail when there is no longer
+# sufficient redundancy.
+#
+# STRATEGY:
+# 1. Start some random I/O on the mirror or raidz.
+# 2. Verify that we can offline as many disks as the redundancy level
+# will support, but not more.
+# 3. Verify the integrity of the file system and the resilvering.
+#
+
+verify_runnable "global"
+
+DISKLIST=$(get_disklist $TESTPOOL)
+
+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
+
+ kill $killpid >/dev/null 2>&1
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Turning both disks offline should fail."
+
+log_onexit cleanup
+
+file_trunc -f $((64 * 1024 * 1024)) -b 8192 -c 0 -r $TESTDIR/$TESTFILE1 &
+typeset killpid="$! "
+
+disks=($DISKLIST)
+
+#
+# The setup script will give us either a mirror or a raidz. The former can have
+# all but one vdev offlined, whereas with raidz there can be only one.
+#
+pooltype='mirror'
+zpool list -v $TESTPOOL | grep raidz >/dev/null 2>&1 && pooltype='raidz'
+
+typeset -i i=0
+while [[ $i -lt ${#disks[*]} ]]; do
+ typeset -i j=0
+ if [[ $pooltype = 'mirror' ]]; then
+ # Hold one disk online, verify the others can be offlined.
+ log_must zpool online $TESTPOOL ${disks[$i]}
+ check_state $TESTPOOL ${disks[$i]} "online" || \
+ log_fail "Failed to set ${disks[$i]} online"
+ log_must zpool wait -t resilver $TESTPOOL
+ log_must zpool clear $TESTPOOL
+ while [[ $j -lt ${#disks[*]} ]]; do
+ if [[ $j -eq $i ]]; then
+ ((j++))
+ continue
+ fi
+ log_must zpool offline $TESTPOOL ${disks[$j]}
+ check_state $TESTPOOL ${disks[$j]} "offline" || \
+ log_fail "Failed to set ${disks[$j]} offline"
+ ((j++))
+ done
+ elif [[ $pooltype = 'raidz' ]]; then
+ # Hold one disk offline, verify the others can't be offlined.
+ log_must zpool offline $TESTPOOL ${disks[$i]}
+ check_state $TESTPOOL ${disks[$i]} "offline" || \
+ log_fail "Failed to set ${disks[$i]} offline"
+ while [[ $j -lt ${#disks[*]} ]]; do
+ if [[ $j -eq $i ]]; then
+ ((j++))
+ continue
+ fi
+ log_mustnot zpool offline $TESTPOOL ${disks[$j]}
+ check_state $TESTPOOL ${disks[$j]} "online" || \
+ log_fail "Failed to set ${disks[$j]} online"
+ check_state $TESTPOOL ${disks[$i]} "offline" || \
+ log_fail "Failed to set ${disks[$i]} offline"
+ ((j++))
+ done
+ log_must zpool online $TESTPOOL ${disks[$i]}
+ check_state $TESTPOOL ${disks[$i]} "online" || \
+ log_fail "Failed to set ${disks[$i]} online"
+ log_must zpool wait -t resilver $TESTPOOL
+ log_must zpool clear $TESTPOOL
+ fi
+ ((i++))
+done
+
+log_must kill $killpid
+sync
+
+typeset dir=$(get_device_dir $DISKS)
+verify_filesys "$TESTPOOL" "$TESTPOOL/$TESTFS" "$dir"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/online_offline/online_offline_003_neg.ksh b/tests/zfs-tests/tests/functional/online_offline/online_offline_003_neg.ksh
new file mode 100755
index 000000000000..0d763ee1b882
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/online_offline/online_offline_003_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 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
+
+#
+# DESCRIPTION:
+# Offlining disks in a non-redundant pool should fail.
+#
+# STRATEGY:
+# 1. Create a multidisk stripe and start some random I/O
+# 2. zpool offline should fail on each disk.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+ fi
+
+ kill $killpid >/dev/null 2>&1
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Offlining disks in a non-redundant pool should fail."
+
+log_onexit cleanup
+
+specials_list=""
+for i in 0 1 2; do
+ mkfile $MINVDEVSIZE $TESTDIR/$TESTFILE1.$i
+ specials_list="$specials_list $TESTDIR/$TESTFILE1.$i"
+done
+disk=($specials_list)
+
+create_pool $TESTPOOL1 $specials_list
+log_must zfs create $TESTPOOL1/$TESTFS1
+log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+file_trunc -f $((64 * 1024 * 1024)) -b 8192 -c 0 -r $TESTDIR/$TESTFILE1 &
+typeset killpid="$! "
+
+for i in 0 1 2; do
+ log_mustnot zpool offline $TESTPOOL1 ${disk[$i]}
+ check_state $TESTPOOL1 ${disk[$i]} "online"
+done
+
+log_must kill $killpid
+sync
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/online_offline/setup.ksh b/tests/zfs-tests/tests/functional/online_offline/setup.ksh
new file mode 100755
index 000000000000..4132392d80a9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/online_offline/setup.ksh
@@ -0,0 +1,47 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+index=`expr $RANDOM % 2`
+case $index in
+0) log_note "Pool Type: Mirror"
+ default_mirror_setup $DISKS
+ ;;
+1) log_note "Pool Type: RAID-Z"
+ default_raidz_setup $DISKS
+ ;;
+esac
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/pam/Makefile.am b/tests/zfs-tests/tests/functional/pam/Makefile.am
new file mode 100644
index 000000000000..4d9ae17084bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pam/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/pam
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ pam_basic.ksh \
+ pam_nounmount.ksh \
+ utilities.kshlib
diff --git a/tests/zfs-tests/tests/functional/pam/cleanup.ksh b/tests/zfs-tests/tests/functional/pam/cleanup.ksh
new file mode 100755
index 000000000000..62131c6d68a7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pam/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
+#
+
+. $STF_SUITE/tests/functional/pam/utilities.kshlib
+
+destroy_pool $TESTPOOL
+del_user ${username}
+del_group pamtestgroup
+
+rm -rf "$runstatedir"
+for dir in $TESTDIRS; do
+ rm -rf $dir
+done
diff --git a/tests/zfs-tests/tests/functional/pam/pam_basic.ksh b/tests/zfs-tests/tests/functional/pam/pam_basic.ksh
new file mode 100755
index 000000000000..96ac59453694
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pam/pam_basic.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
+#
+
+. $STF_SUITE/tests/functional/pam/utilities.kshlib
+
+log_mustnot ismounted "$TESTPOOL/pam/${username}"
+keystatus unavailable
+
+genconfig "homes=$TESTPOOL/pam runstatedir=${runstatedir}"
+echo "testpass" | pamtester pam_zfs_key_test ${username} open_session
+references 1
+log_must ismounted "$TESTPOOL/pam/${username}"
+keystatus available
+
+echo "testpass" | pamtester pam_zfs_key_test ${username} open_session
+references 2
+log_must ismounted "$TESTPOOL/pam/${username}"
+keystatus available
+
+log_must pamtester pam_zfs_key_test ${username} close_session
+references 1
+log_must ismounted "$TESTPOOL/pam/${username}"
+keystatus available
+
+log_must pamtester pam_zfs_key_test ${username} close_session
+references 0
+log_mustnot ismounted "$TESTPOOL/pam/${username}"
+keystatus unavailable
+
+log_pass "done."
diff --git a/tests/zfs-tests/tests/functional/pam/pam_nounmount.ksh b/tests/zfs-tests/tests/functional/pam/pam_nounmount.ksh
new file mode 100755
index 000000000000..8179f398dfaf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pam/pam_nounmount.ksh
@@ -0,0 +1,51 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/pam/utilities.kshlib
+
+log_mustnot ismounted "$TESTPOOL/pam/${username}"
+keystatus unavailable
+
+genconfig "homes=$TESTPOOL/pam runstatedir=${runstatedir} nounmount"
+echo "testpass" | pamtester pam_zfs_key_test ${username} open_session
+references 1
+log_must ismounted "$TESTPOOL/pam/${username}"
+keystatus available
+
+echo "testpass" | pamtester pam_zfs_key_test ${username} open_session
+references 2
+keystatus available
+log_must ismounted "$TESTPOOL/pam/${username}"
+
+log_must pamtester pam_zfs_key_test ${username} close_session
+references 1
+keystatus available
+log_must ismounted "$TESTPOOL/pam/${username}"
+
+log_must pamtester pam_zfs_key_test ${username} close_session
+references 0
+keystatus available
+log_must ismounted "$TESTPOOL/pam/${username}"
+log_must zfs unmount "$TESTPOOL/pam/${username}"
+log_must zfs unload-key "$TESTPOOL/pam/${username}"
+
+log_pass "done."
diff --git a/tests/zfs-tests/tests/functional/pam/setup.ksh b/tests/zfs-tests/tests/functional/pam/setup.ksh
new file mode 100755
index 000000000000..23515a598e72
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pam/setup.ksh
@@ -0,0 +1,41 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/tests/functional/pam/utilities.kshlib
+
+if ! which pamtester; then
+ log_unsupported "pam tests require the pamtester utility to be installed"
+fi
+
+DISK=${DISKS%% *}
+create_pool $TESTPOOL "$DISK"
+
+log_must zfs create -o mountpoint="$TESTDIR" "$TESTPOOL/pam"
+log_must add_group pamtestgroup
+log_must add_user pamtestgroup ${username}
+log_must mkdir -p "$runstatedir"
+
+echo "testpass" | zfs create -o encryption=aes-256-gcm -o keyformat=passphrase -o keylocation=prompt "$TESTPOOL/pam/${username}"
+log_must zfs unmount "$TESTPOOL/pam/${username}"
+log_must zfs unload-key "$TESTPOOL/pam/${username}"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/pam/utilities.kshlib b/tests/zfs-tests/tests/functional/pam/utilities.kshlib
new file mode 100644
index 000000000000..35371d14a26b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pam/utilities.kshlib
@@ -0,0 +1,40 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+username="pamTestuser"
+runstatedir="${TESTDIR}_run"
+function keystatus {
+ log_must [ "$(zfs list -Ho keystatus "$TESTPOOL/pam/${username}")" == "$1" ]
+}
+
+function genconfig {
+ for i in password auth session; do
+ printf "%s\trequired\tpam_permit.so\n%s\toptional\tpam_zfs_key.so\t%s\n" "$i" "$i" "$1"
+ done > /etc/pam.d/pam_zfs_key_test
+}
+
+function references {
+ log_must [ "$(cat "${runstatedir}/$(id -u ${username})")" == "$1" ]
+}
+
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/Makefile.am b/tests/zfs-tests/tests/functional/persist_l2arc/Makefile.am
new file mode 100644
index 000000000000..14a43de9c173
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/Makefile.am
@@ -0,0 +1,15 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/persist_l2arc
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ persist_l2arc_001_pos.ksh \
+ persist_l2arc_002_pos.ksh \
+ persist_l2arc_003_neg.ksh \
+ persist_l2arc_004_pos.ksh \
+ persist_l2arc_005_pos.ksh \
+ persist_l2arc_006_pos.ksh \
+ persist_l2arc_007_pos.ksh \
+ persist_l2arc_008_pos.ksh
+
+dist_pkgdata_DATA = \
+ persist_l2arc.cfg
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/cleanup.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/cleanup.ksh
new file mode 100755
index 000000000000..828de3862508
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/cleanup.ksh
@@ -0,0 +1,31 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+
+verify_runnable "global"
+
+if datasetexists $TESTPOOL ; then
+ log_must zpool destroy -f $TESTPOOL
+fi
+
+log_must rm -rf $VDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc.cfg b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc.cfg
new file mode 100644
index 000000000000..60bb2463760f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc.cfg
@@ -0,0 +1,37 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export SIZE=1G
+export VDIR=$TESTDIR/disk.persist_l2arc
+export VDEV="$VDIR/a"
+export VDEV_CACHE="$VDIR/b"
+
+# fio options
+export DIRECTORY=/$TESTPOOL
+export NUMJOBS=4
+export RUNTIME=30
+export PERF_RANDSEED=1234
+export PERF_COMPPERCENT=66
+export PERF_COMPCHUNK=0
+export BLOCKSIZE=128K
+export SYNC_TYPE=0
+export DIRECT=1
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_001_pos.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_001_pos.ksh
new file mode 100755
index 000000000000..f313923d1469
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_001_pos.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 (c) 2020, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+
+#
+# DESCRIPTION:
+# Persistent L2ARC with an unencrypted ZFS file system succeeds
+#
+# STRATEGY:
+# 1. Create pool with a cache device.
+# 2. Export and re-import pool without writing any data.
+# 3. Create a random file in that pool and random read for 30 sec.
+# 4. Export pool.
+# 5. Read the amount of log blocks written from the header of the
+# L2ARC device.
+# 6. Import pool.
+# 7. Read the amount of log blocks rebuilt in arcstats and compare to
+# (4).
+# 8. Check if the labels of the L2ARC device are intact.
+#
+# * We can predict the minimum bytes of L2ARC restored if we subtract
+# from the effective size of the cache device the bytes l2arc_evict()
+# evicts:
+# l2: L2ARC device size - VDEV_LABEL_START_SIZE - l2ad_dev_hdr_asize
+# wr_sz: l2arc_write_max + l2arc_write_boost (worst case)
+# blk_overhead: wr_sz / SPA_MINBLOCKSIZE / (l2 / SPA_MAXBLOCKSIZE) *
+# sizeof (l2arc_log_blk_phys_t)
+# min restored size: l2 - (wr_sz + blk_overhead)
+#
+
+verify_runnable "global"
+
+log_assert "Persistent L2ARC with an unencrypted ZFS file system succeeds."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+ log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE \
+ $rebuild_blocks_min_l2size
+}
+log_onexit cleanup
+
+# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+typeset rebuild_blocks_min_l2size=$(get_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( floor($fill_mb / 2) ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
+
+log_must zpool export $TESTPOOL
+log_must zpool import -d $VDIR $TESTPOOL
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool export $TESTPOOL
+
+typeset l2_dh_log_blk=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
+ awk '{print $2}')
+
+typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
+
+log_must zpool import -d $VDIR $TESTPOOL
+
+sleep 2
+
+typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $l2_dh_log_blk -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
+log_must test $l2_dh_log_blk -gt 0
+
+log_must zdb -lll $VDEV_CACHE
+
+log_must zpool destroy -f $TESTPOOL
+
+log_pass "Persistent L2ARC with an unencrypted ZFS file system succeeds."
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_002_pos.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_002_pos.ksh
new file mode 100755
index 000000000000..0184f06efa50
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_002_pos.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, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# Persistent L2ARC with an encrypted ZFS file system succeeds
+#
+# STRATEGY:
+# 1. Create pool with a cache device.
+# 2. Create a an encrypted ZFS file system.
+# 3. Create a random file in the encrypted file system and random
+# read for 30 sec.
+# 4. Export pool.
+# 5. Read the amount of log blocks written from the header of the
+# L2ARC device.
+# 5. Import pool.
+# 6. Mount the encrypted ZFS file system.
+# 7. Read the amount of log blocks rebuilt in arcstats and compare to
+# (5).
+# 8. Check if the labels of the L2ARC device are intact.
+#
+# * We can predict the minimum bytes of L2ARC restored if we subtract
+# from the effective size of the cache device the bytes l2arc_evict()
+# evicts:
+# l2: L2ARC device size - VDEV_LABEL_START_SIZE - l2ad_dev_hdr_asize
+# wr_sz: l2arc_write_max + l2arc_write_boost (worst case)
+# blk_overhead: wr_sz / SPA_MINBLOCKSIZE / (l2 / SPA_MAXBLOCKSIZE) *
+# sizeof (l2arc_log_blk_phys_t)
+# min restored size: l2 - (wr_sz + blk_overhead)
+#
+
+verify_runnable "global"
+
+log_assert "Persistent L2ARC with an encrypted ZFS file system succeeds."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+ log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE \
+ $rebuild_blocks_min_l2size
+}
+log_onexit cleanup
+
+# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+typeset rebuild_blocks_min_l2size=$(get_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( floor($fill_mb / 2) ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool export $TESTPOOL
+
+sleep 2
+
+typeset l2_dh_log_blk=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
+ awk '{print $2}')
+
+typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
+
+log_must zpool import -d $VDIR $TESTPOOL
+log_must eval "echo $PASSPHRASE | zfs mount -l $TESTPOOL/$TESTFS1"
+
+sleep 2
+
+typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $l2_dh_log_blk -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
+log_must test $l2_dh_log_blk -gt 0
+
+log_must zdb -lq $VDEV_CACHE
+
+log_must zpool destroy -f $TESTPOOL
+
+log_pass "Persistent L2ARC with an encrypted ZFS file system succeeds."
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_003_neg.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_003_neg.ksh
new file mode 100755
index 000000000000..7824dfe8f1b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_003_neg.ksh
@@ -0,0 +1,87 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+
+#
+# DESCRIPTION:
+# Persistent L2ARC fails as expected when L2ARC_REBUILD_ENABLED = 0
+#
+# STRATEGY:
+# 1. Set L2ARC_REBUILD_ENABLED = 0
+# 2. Create pool with a cache device.
+# 3. Create a random file in that pool and random read for 30 sec.
+# 4. Export pool.
+# 5. Import pool.
+# 6. Check in zpool iostat if the cache device has space allocated.
+# 7. Read the file written in (2) and check if l2_hits in
+# /proc/spl/kstat/zfs/arcstats increased.
+#
+
+verify_runnable "global"
+
+log_assert "Persistent L2ARC fails as expected when L2ARC_REBUILD_ENABLED = 0."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_REBUILD_ENABLED $rebuild_enabled
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+}
+log_onexit cleanup
+
+# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+
+# disable L2ARC rebuild
+typeset rebuild_enabled=$(get_tunable L2ARC_REBUILD_ENABLED)
+log_must set_tunable32 L2ARC_REBUILD_ENABLED 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( 2 * $fill_mb ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool export $TESTPOOL
+
+typeset l2_success_start=$(get_arcstat l2_rebuild_success)
+
+log_must zpool import -d $VDIR $TESTPOOL
+log_mustnot test "$(zpool iostat -Hpv $TESTPOOL $VDEV_CACHE | awk '{print $2}')" -gt 80000000
+
+typeset l2_success_end=$(get_arcstat l2_rebuild_success)
+
+log_mustnot test $l2_success_end -gt $l2_success_start
+
+log_must zpool destroy -f $TESTPOOL
+log_must set_tunable32 L2ARC_REBUILD_ENABLED $rebuild_enabled
+
+log_pass "Persistent L2ARC fails as expected when L2ARC_REBUILD_ENABLED = 0."
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_004_pos.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_004_pos.ksh
new file mode 100755
index 000000000000..6620131d182d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_004_pos.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) 2020, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+
+#
+# DESCRIPTION:
+# Persistent L2ARC restores all written log blocks
+#
+# STRATEGY:
+# 1. Create pool with a cache device.
+# 2. Create a random file in that pool, smaller than the cache device
+# and random read for 30 sec.
+# 3. Export pool.
+# 4. Read amount of log blocks written.
+# 5. Import pool.
+# 6. Read amount of log blocks built.
+# 7. Compare the two amounts
+# 8. Read the file written in (2) and check if l2_hits in
+# /proc/spl/kstat/zfs/arcstats increased.
+# 9. Check if the labels of the L2ARC device are intact.
+#
+
+verify_runnable "global"
+
+log_assert "Persistent L2ARC restores all written log blocks."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+}
+log_onexit cleanup
+
+# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( 2 * $fill_mb ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+typeset log_blk_start=$(get_arcstat l2_log_blk_writes)
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool export $TESTPOOL
+
+sleep 2
+
+typeset log_blk_end=$(get_arcstat l2_log_blk_writes)
+
+typeset log_blk_rebuild_start=$(get_arcstat l2_rebuild_log_blks)
+
+log_must zpool import -d $VDIR $TESTPOOL
+
+typeset l2_hits_start=$(get_arcstat l2_hits)
+
+export RUNTIME=10
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+typeset l2_hits_end=$(get_arcstat l2_hits)
+
+typeset log_blk_rebuild_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $(( $log_blk_rebuild_end - $log_blk_rebuild_start )) -eq \
+ $(( $log_blk_end - $log_blk_start ))
+
+log_must test $l2_hits_end -gt $l2_hits_start
+
+log_must zdb -lq $VDEV_CACHE
+
+log_must zpool destroy -f $TESTPOOL
+
+log_pass "Persistent L2ARC restores all written log blocks."
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_005_pos.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_005_pos.ksh
new file mode 100755
index 000000000000..9fc6a5923864
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_005_pos.ksh
@@ -0,0 +1,108 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# Persistent L2ARC restores all written log blocks with encryption
+#
+# STRATEGY:
+# 1. Create pool with a cache device.
+# 2. Create a an encrypted ZFS file system.
+# 3. Create a random file in the entrypted file system,
+# smaller than the cache device, and random read for 30 sec.
+# 4. Export pool.
+# 5. Read amount of log blocks written.
+# 6. Import pool.
+# 7. Mount the encrypted ZFS file system.
+# 8. Read amount of log blocks built.
+# 9. Compare the two amounts
+# 10. Read the file written in (3) and check if l2_hits in
+# /proc/spl/kstat/zfs/arcstats increased.
+# 11. Check if the labels of the L2ARC device are intact.
+#
+
+verify_runnable "global"
+
+log_assert "Persistent L2ARC restores all written log blocks with encryption."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+}
+log_onexit cleanup
+
+# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( 2 * $fill_mb ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+typeset log_blk_start=$(get_arcstat l2_log_blk_writes)
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
+
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool export $TESTPOOL
+
+sleep 2
+
+typeset log_blk_end=$(get_arcstat l2_log_blk_writes)
+
+typeset log_blk_rebuild_start=$(get_arcstat l2_rebuild_log_blks)
+
+log_must zpool import -d $VDIR $TESTPOOL
+log_must eval "echo $PASSPHRASE | zfs mount -l $TESTPOOL/$TESTFS1"
+
+typeset l2_hits_start=$(get_arcstat l2_hits)
+
+export RUNTIME=10
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+typeset l2_hits_end=$(get_arcstat l2_hits)
+
+typeset log_blk_rebuild_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $(( $log_blk_rebuild_end - $log_blk_rebuild_start )) -eq \
+ $(( $log_blk_end - $log_blk_start ))
+
+log_must test $l2_hits_end -gt $l2_hits_start
+
+log_must zdb -lq $VDEV_CACHE
+
+log_must zpool destroy -f $TESTPOOL
+
+log_pass "Persistent L2ARC restores all written log blocks with encryption."
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_006_pos.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_006_pos.ksh
new file mode 100755
index 000000000000..55e9f9585c0e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_006_pos.ksh
@@ -0,0 +1,98 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+
+#
+# DESCRIPTION:
+# Off/onlining an L2ARC device results in rebuilding L2ARC, vdev not
+# present.
+#
+# STRATEGY:
+# 1. Create pool with a cache device.
+# 2. Create a random file in that pool and random read for 30 sec.
+# 3. Read the amount of log blocks written from the header of the
+# L2ARC device.
+# 4. Offline the L2ARC device and export pool.
+# 5. Import pool and online the L2ARC device.
+# 6. Read the amount of log blocks rebuilt in arcstats and compare to
+# (3).
+# 7. Check if the labels of the L2ARC device are intact.
+#
+
+verify_runnable "global"
+
+log_assert "Off/onlining an L2ARC device results in rebuilding L2ARC, vdev not present."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+ log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE \
+ $rebuild_blocks_min_l2size
+}
+log_onexit cleanup
+
+# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+typeset rebuild_blocks_min_l2size=$(get_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( floor($fill_mb / 2) ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool offline $TESTPOOL $VDEV_CACHE
+log_must zpool export $TESTPOOL
+
+sleep 5
+
+typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
+
+typeset l2_dh_log_blk=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
+ awk '{print $2}')
+
+log_must zpool import -d $VDIR $TESTPOOL
+log_must zpool online $TESTPOOL $VDEV_CACHE
+
+sleep 5
+
+typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $l2_dh_log_blk -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
+log_must test $l2_dh_log_blk -gt 0
+
+log_must zdb -lq $VDEV_CACHE
+
+log_must zpool destroy -f $TESTPOOL
+
+log_pass "Off/onlining an L2ARC device results in rebuilding L2ARC, vdev not present."
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_007_pos.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_007_pos.ksh
new file mode 100755
index 000000000000..c79c3927652d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_007_pos.ksh
@@ -0,0 +1,95 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+
+#
+# DESCRIPTION:
+# Off/onlining an L2ARC device results in rebuilding L2ARC, vdev present.
+#
+# STRATEGY:
+# 1. Create pool with a cache device.
+# 2. Create a random file in that pool and random read for 30 sec.
+# 3. Read the amount of log blocks written from the header of the
+# L2ARC device.
+# 4. Offline the L2ARC device.
+# 5. Online the L2ARC device.
+# 6. Read the amount of log blocks rebuilt in arcstats and compare to
+# (3).
+# 7. Check if the labels of the L2ARC device are intact.
+#
+
+verify_runnable "global"
+
+log_assert "Off/onlining an L2ARC device results in rebuilding L2ARC, vdev present."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+ log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE \
+ $rebuild_blocks_min_l2size
+}
+log_onexit cleanup
+
+# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+typeset rebuild_blocks_min_l2size=$(get_tunable L2ARC_REBUILD_BLOCKS_MIN_L2SIZE)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+log_must set_tunable32 L2ARC_REBUILD_BLOCKS_MIN_L2SIZE 0
+
+typeset fill_mb=800
+typeset cache_sz=$(( floor($fill_mb / 2) ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool offline $TESTPOOL $VDEV_CACHE
+
+sleep 10
+
+typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
+
+typeset l2_dh_log_blk=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
+ awk '{print $2}')
+
+log_must zpool online $TESTPOOL $VDEV_CACHE
+
+sleep 10
+
+typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $l2_dh_log_blk -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
+log_must test $l2_dh_log_blk -gt 0
+
+log_must zdb -lq $VDEV_CACHE
+
+log_must zpool destroy -f $TESTPOOL
+
+log_pass "Off/onlining an L2ARC device results in rebuilding L2ARC, vdev present."
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_008_pos.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_008_pos.ksh
new file mode 100755
index 000000000000..a64bd94d3169
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/persist_l2arc_008_pos.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) 2020, George Amanakis. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+
+#
+# DESCRIPTION:
+# Off/onlining an L2ARC device restores all written blocks, vdev present.
+#
+# STRATEGY:
+# 1. Create pool with a cache device.
+# 2. Create a random file in that pool and random read for 30 sec.
+# 3. Read the amount of log blocks written from the header of the
+# L2ARC device.
+# 4. Offline the L2ARC device.
+# 5. Online the L2ARC device.
+# 6. Read the amount of log blocks rebuilt in arcstats and compare to
+# (3).
+# 7. Create another random file in that pool and random read for 30 sec.
+# 8. Read the amount of log blocks written from the header of the
+# L2ARC device.
+# 9. Offline the L2ARC device.
+# 10. Online the L2ARC device.
+# 11. Read the amount of log blocks rebuilt in arcstats and compare to
+# (7).
+# 12. Check if the amount of log blocks on the cache device has
+# increased.
+# 13. Export the pool.
+# 14. Read the amount of log blocks on the cache device.
+# 15. Import the pool.
+# 16. Read the amount of log blocks rebuilt in arcstats and compare to
+# (14).
+# 17. Check if the labels of the L2ARC device are intact.
+#
+
+verify_runnable "global"
+
+log_assert "Off/onlining an L2ARC device restores all written blocks , vdev present."
+
+function cleanup
+{
+ if poolexists $TESTPOOL ; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must set_tunable32 L2ARC_NOPREFETCH $noprefetch
+}
+log_onexit cleanup
+
+# L2ARC_NOPREFETCH is set to 0 to let L2ARC handle prefetches
+typeset noprefetch=$(get_tunable L2ARC_NOPREFETCH)
+log_must set_tunable32 L2ARC_NOPREFETCH 0
+
+typeset fill_mb=400
+typeset cache_sz=$(( 3 * $fill_mb ))
+export FILE_SIZE=$(( floor($fill_mb / $NUMJOBS) ))M
+
+log_must truncate -s ${cache_sz}M $VDEV_CACHE
+
+log_must zpool create -f $TESTPOOL $VDEV cache $VDEV_CACHE
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool offline $TESTPOOL $VDEV_CACHE
+
+sleep 2
+
+typeset l2_dh_log_blk1=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
+ awk '{print $2}')
+
+typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
+
+log_must zpool online $TESTPOOL $VDEV_CACHE
+
+sleep 5
+
+typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $l2_dh_log_blk1 -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
+log_must test $l2_dh_log_blk1 -gt 0
+
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+log_must zpool offline $TESTPOOL $VDEV_CACHE
+
+sleep 2
+
+typeset l2_dh_log_blk2=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
+ awk '{print $2}')
+
+typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
+
+log_must zpool online $TESTPOOL $VDEV_CACHE
+
+sleep 5
+
+typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $l2_dh_log_blk2 -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
+
+log_must test $l2_dh_log_blk2 -gt $l2_dh_log_blk1
+
+log_must zpool export $TESTPOOL
+
+typeset l2_dh_log_blk3=$(zdb -l $VDEV_CACHE | grep log_blk_count | \
+ awk '{print $2}')
+
+typeset l2_rebuild_log_blk_start=$(get_arcstat l2_rebuild_log_blks)
+
+log_must zpool import -d $VDIR $TESTPOOL
+
+sleep 5
+
+typeset l2_rebuild_log_blk_end=$(get_arcstat l2_rebuild_log_blks)
+
+log_must test $l2_dh_log_blk3 -eq $(( $l2_rebuild_log_blk_end - $l2_rebuild_log_blk_start ))
+log_must test $l2_dh_log_blk3 -gt 0
+
+log_must zdb -lq $VDEV_CACHE
+
+log_must zpool destroy -f $TESTPOOL
+
+log_pass "Off/onlining an L2ARC device restores all written blocks, vdev present."
diff --git a/tests/zfs-tests/tests/functional/persist_l2arc/setup.ksh b/tests/zfs-tests/tests/functional/persist_l2arc/setup.ksh
new file mode 100755
index 000000000000..ef95c84cdd6a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/persist_l2arc/setup.ksh
@@ -0,0 +1,29 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/persist_l2arc/persist_l2arc.cfg
+
+verify_runnable "global"
+
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must mkfile $SIZE $VDEV
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/Makefile.am b/tests/zfs-tests/tests/functional/pool_checkpoint/Makefile.am
new file mode 100644
index 000000000000..cc1c1183db79
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/Makefile.am
@@ -0,0 +1,26 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/pool_checkpoint
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ checkpoint_after_rewind.ksh \
+ checkpoint_big_rewind.ksh \
+ checkpoint_capacity.ksh \
+ checkpoint_conf_change.ksh \
+ checkpoint_discard_busy.ksh \
+ checkpoint_discard.ksh \
+ checkpoint_discard_many.ksh \
+ checkpoint_indirect.ksh \
+ checkpoint_invalid.ksh \
+ checkpoint_lun_expsz.ksh \
+ checkpoint_open.ksh \
+ checkpoint_removal.ksh \
+ checkpoint_rewind.ksh \
+ checkpoint_ro_rewind.ksh \
+ checkpoint_sm_scale.ksh \
+ checkpoint_twice.ksh \
+ checkpoint_vdev_add.ksh \
+ checkpoint_zdb.ksh \
+ checkpoint_zhack_feat.ksh
+
+dist_pkgdata_DATA = \
+ pool_checkpoint.kshlib
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_after_rewind.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_after_rewind.ksh
new file mode 100755
index 000000000000..c1dec30aa50d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_after_rewind.ksh
@@ -0,0 +1,55 @@
+#!/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/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we can checkpoint a pool that we just rewound.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Modify data (include at least one destructive change)
+# 5. Rewind to checkpoint
+# 6. Verify that the data before the checkpoint are present
+# and the data after the checkpoint is gone
+# 7. Take another checkpoint
+# 8. Change state again
+# 9. Verify the state at that time
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+populate_test_pool
+log_must zpool checkpoint $TESTPOOL
+test_change_state_after_checkpoint
+
+log_must zpool export $TESTPOOL
+log_must zpool import --rewind-to-checkpoint $TESTPOOL
+test_verify_pre_checkpoint_state
+
+log_must zpool checkpoint $TESTPOOL
+test_change_state_after_checkpoint
+
+test_verify_post_checkpoint_state
+
+log_pass "Checkpoint a pool that we just rewound."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_big_rewind.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_big_rewind.ksh
new file mode 100755
index 000000000000..f915d2ad418c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_big_rewind.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) 2017, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Rewind to checkpoint on a stressed pool. We basically try to
+# fragment the pool before and after taking a checkpoint and
+# see if zdb finds any checksum or other errors that imply that
+# blocks from the checkpoint have been reused.
+#
+# STRATEGY:
+# 1. Import pool that's slightly fragmented
+# 2. Take checkpoint
+# 3. Apply a destructive action and do more random writes
+# 4. Run zdb on both current and checkpointed data and make
+# sure that zdb returns with no errors
+# 5. Rewind to checkpoint
+# 6. Run zdb again
+#
+
+verify_runnable "global"
+
+setup_nested_pool_state
+log_onexit cleanup_nested_pools
+
+log_must zpool checkpoint $NESTEDPOOL
+
+#
+# Destroy one dataset, modify an existing one and create a
+# a new one. Do more random writes in an attempt to raise
+# more fragmentation. Then verify both current and checkpointed
+# states.
+#
+fragment_after_checkpoint_and_verify
+
+log_must zpool export $NESTEDPOOL
+log_must zpool import -d $FILEDISKDIR --rewind-to-checkpoint $NESTEDPOOL
+
+log_must zdb $NESTEDPOOL
+
+log_pass "Rewind to checkpoint on a stressed pool."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_capacity.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_capacity.ksh
new file mode 100755
index 000000000000..15afc4adf4bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_capacity.ksh
@@ -0,0 +1,92 @@
+#!/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/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we don't reuse checkpointed blocks when the
+# pool hits ENOSPC errors because of the slop space limit.
+# This test also ensures that the DSL layer correctly takes
+# into account the space used by the checkpoint when deciding
+# whether to allow operations based on the reserved slop
+# space.
+#
+# STRATEGY:
+# 1. Create pool with one disk of 1G size
+# 2. Create a file with random data of 700M in size.
+# leaving ~200M left in pool capacity.
+# 3. Checkpoint the pool
+# 4. Remove the file. All of its blocks should stay around
+# in ZFS as they are part of the checkpoint.
+# 5. Create a new empty file and attempt to write ~300M
+# of data to it. This should fail, as the reserved
+# SLOP space for the pool should be ~128M, and we should
+# be hitting that limit getting ENOSPC.
+# 6. Use zdb to traverse and checksum all the checkpointed
+# data to ensure its integrity.
+# 7. Export the pool and rewind to ensure that everything
+# is actually there as expected.
+#
+
+function test_cleanup
+{
+ poolexists $NESTEDPOOL && destroy_pool $NESTEDPOOL
+ set_tunable32 SPA_ASIZE_INFLATION 24
+ cleanup_test_pool
+}
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit test_cleanup
+log_must set_tunable32 SPA_ASIZE_INFLATION 4
+
+log_must zfs create $DISKFS
+
+log_must mkfile $FILEDISKSIZE $FILEDISK1
+log_must zpool create $NESTEDPOOL $FILEDISK1
+
+log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS0
+log_must dd if=/dev/urandom of=$NESTEDFS0FILE bs=1M count=700
+FILE0INTRO=$(head -c 100 $NESTEDFS0FILE)
+
+log_must zpool checkpoint $NESTEDPOOL
+log_must rm $NESTEDFS0FILE
+
+#
+# only for debugging purposes
+#
+log_must zpool list $NESTEDPOOL
+
+log_mustnot dd if=/dev/urandom of=$NESTEDFS0FILE bs=1M count=300
+
+#
+# only for debugging purposes
+#
+log_must zpool list $NESTEDPOOL
+
+log_must zdb -kc $NESTEDPOOL
+
+log_must zpool export $NESTEDPOOL
+log_must zpool import -d $FILEDISKDIR --rewind-to-checkpoint $NESTEDPOOL
+
+log_must [ "$(head -c 100 $NESTEDFS0FILE)" = "$FILE0INTRO" ]
+
+log_must zdb $NESTEDPOOL
+
+log_pass "Do not reuse checkpointed space at low capacity."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_conf_change.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_conf_change.ksh
new file mode 100755
index 000000000000..4f783108a93a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_conf_change.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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# It shouldn't be possible to change pool's vdev config when
+# it has a checkpoint.
+#
+# STRATEGY:
+# 1. Create pool and take checkpoint
+# 2. Attempt to change guid
+# 3. Attempt to attach/replace/remove device
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+log_must zpool checkpoint $TESTPOOL
+
+log_mustnot zpool reguid $TESTPOOL
+log_mustnot zpool attach -f $TESTPOOL $TESTDISK $EXTRATESTDISK
+log_mustnot zpool replace $TESTPOOL $TESTDISK $EXTRATESTDISK
+log_mustnot zpool remove $TESTPOOL $TESTDISK
+
+log_pass "Cannot change pool's config when pool has checkpoint."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard.ksh
new file mode 100755
index 000000000000..efd46a69b9d7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard.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) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we can discard the checkpoint from a pool.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Modify data (include at least one destructive change)
+# 5. Discard checkpoint
+# 6. Export and attempt to rewind. Rewinding should fail
+# 7. Import pool normally and verify state
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+populate_test_pool
+
+log_must zpool checkpoint $TESTPOOL
+
+test_change_state_after_checkpoint
+
+log_must zpool checkpoint -d $TESTPOOL
+
+log_must zpool export $TESTPOOL
+log_mustnot zpool import --rewind-to-checkpoint $TESTPOOL
+
+log_must zpool import $TESTPOOL
+test_verify_post_checkpoint_state
+
+log_pass "Discard checkpoint from pool."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh
new file mode 100755
index 000000000000..ae099ff270f1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_busy.ksh
@@ -0,0 +1,110 @@
+#!/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, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Discard checkpoint on a stressed pool. Ensure that we can
+# export and import the pool while discarding but not run any
+# operations that have to do with the checkpoint or change the
+# pool's config.
+#
+# STRATEGY:
+# 1. Import pools that's slightly fragmented
+# 2. Take checkpoint
+# 3. Do more random writes to "free" checkpointed blocks
+# 4. Start discarding checkpoint
+# 5. Export pool while discarding checkpoint
+# 6. Attempt to rewind (should fail)
+# 7. Import pool and ensure that discard is still running
+# 8. Attempt to run checkpoint commands, or commands that
+# change the pool's config (should fail)
+#
+
+verify_runnable "global"
+
+function test_cleanup
+{
+ # reset memory limit to 16M
+ set_tunable64 SPA_DISCARD_MEMORY_LIMIT 1000000
+ cleanup_nested_pools
+}
+
+setup_nested_pool_state
+log_onexit test_cleanup
+
+#
+# Force discard to happen slower so it spans over
+# multiple txgs.
+#
+# Set memory limit to 128 bytes. Assuming that we
+# use 64-bit words for encoding space map entries,
+# ZFS will discard 8 non-debug entries per txg
+# (so at most 16 space map entries in debug-builds
+# due to debug entries).
+#
+# That should give us more than enough txgs to be
+# discarding the checkpoint for a long time as with
+# the current setup the checkpoint space maps should
+# have tens of thousands of entries.
+#
+# Note: If two-words entries are used in the space
+# map, we should have even more time to
+# verify this.
+#
+set_tunable64 SPA_DISCARD_MEMORY_LIMIT 128
+
+log_must zpool checkpoint $NESTEDPOOL
+
+fragment_after_checkpoint_and_verify
+
+log_must zpool checkpoint -d $NESTEDPOOL
+
+log_must zpool export $NESTEDPOOL
+
+#
+# Verify on-disk state while pool is exported
+#
+log_must zdb -e -p $FILEDISKDIR $NESTEDPOOL
+
+#
+# Attempt to rewind on a pool that is discarding
+# a checkpoint.
+#
+log_mustnot zpool import -d $FILEDISKDIR --rewind-to-checkpoint $NESTEDPOOL
+
+log_must zpool import -d $FILEDISKDIR $NESTEDPOOL
+
+#
+# Discarding should continue after import, so
+# all the following operations should fail.
+#
+log_mustnot zpool checkpoint $NESTEDPOOL
+log_mustnot zpool checkpoint -d $NESTEDPOOL
+log_mustnot zpool remove $NESTEDPOOL $FILEDISK1
+log_mustnot zpool reguid $NESTEDPOOL
+
+# reset memory limit to 16M
+set_tunable64 SPA_DISCARD_MEMORY_LIMIT 16777216
+
+nested_wait_discard_finish
+
+log_must zdb $NESTEDPOOL
+
+log_pass "Can export/import but not rewind/checkpoint/discard or " \
+ "change pool's config while discarding."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_many.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_many.ksh
new file mode 100755
index 000000000000..cf0cf6ce9eea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_discard_many.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) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Take a checkpoint and discard checkpointed data twice. The
+# idea is to ensure that the background discard zfs thread is
+# always running and works as expected.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it and then take a checkpoint
+# 3. Do some changes afterwards, and then discard checkpoint
+# 4. Repeat steps 2 and 3
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+populate_test_pool
+log_must zpool checkpoint $TESTPOOL
+test_change_state_after_checkpoint
+log_must zpool checkpoint -d $TESTPOOL
+test_wait_discard_finish
+
+log_must mkfile -n 100M $FS2FILE
+log_must randwritecomp $FS2FILE 100
+log_must zpool checkpoint $TESTPOOL
+
+log_must randwritecomp $FS2FILE 100
+log_must zpool checkpoint -d $TESTPOOL
+test_wait_discard_finish
+
+log_pass "Background discarding works as expected."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_indirect.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_indirect.ksh
new file mode 100755
index 000000000000..aa14d8ed27fc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_indirect.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 (c) 2017, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that checkpoint plays well with indirect mappings
+# and blocks.
+#
+# STRATEGY:
+# 1. Import pool that's slightly fragmented
+# 2. Introduce indirection by removing and re-adding devices
+# 3. Take checkpoint
+# 4. Apply a destructive action and do more random writes
+# 5. Run zdb on both current and checkpointed data and make
+# sure that zdb returns with no errors
+#
+
+verify_runnable "global"
+
+setup_nested_pool_state
+log_onexit cleanup_nested_pools
+
+#
+# Remove and re-add all disks.
+#
+introduce_indirection
+
+#
+# Display fragmentation after removals
+#
+log_must zpool list -v
+
+log_must zpool checkpoint $NESTEDPOOL
+
+#
+# Destroy one dataset, modify an existing one and create a
+# a new one. Do more random writes in an attempt to raise
+# more fragmentation. Then verify both current and checkpointed
+# states.
+#
+fragment_after_checkpoint_and_verify
+
+log_pass "Running correctly on indirect setups with a checkpoint."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_invalid.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_invalid.ksh
new file mode 100755
index 000000000000..c10f0550c6b8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_invalid.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 (c) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Try each 'zpool checkpoint' and relevant 'zpool import' with
+# invalid inputs to ensure it returns an error. That includes:
+# * A non-existent pool name or no pool name at all is supplied
+# * Pool supplied for discarding or rewinding but the pool
+# does not have a checkpoint
+# * A dataset or a file/directory are supplied instead of a pool
+#
+# STRATEGY:
+# 1. Create an array of parameters for the different scenarios
+# 2. For each parameter, execute the scenarios sub-command
+# 3. Verify that an error was returned
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+populate_test_pool
+
+#
+# Argument groups below. Note that all_args also includes
+# an empty string as "run command with no argument".
+#
+set -A all_args "" "-d" "--discard"
+
+#
+# Target groups below. Note that invalid_targets includes
+# an empty string as "do not supply a pool name".
+#
+set -A invalid_targets "" "iDontExist" "$FS0" "$FS0FILE"
+non_checkpointed="$TESTPOOL"
+
+#
+# Scenario 1
+# Trying all checkpoint args with all invalid targets
+#
+typeset -i i=0
+while (( i < ${#invalid_targets[*]} )); do
+ typeset -i j=0
+ while (( j < ${#all_args[*]} )); do
+ log_mustnot zpool checkpoint ${all_args[j]} \
+ ${invalid_targets[i]}
+ ((j = j + 1))
+ done
+ ((i = i + 1))
+done
+
+#
+# Scenario 2
+# If the pool does not have a checkpoint, -d nor import rewind
+# should work with it.
+#
+log_mustnot zpool checkpoint -d $non_checkpointed
+log_must zpool export $non_checkpointed
+log_mustnot zpool import --rewind-to-checkpoint $non_checkpointed
+log_must zpool import $non_checkpointed
+
+log_pass "Badly formed checkpoint related commands with " \
+ "invalid inputs fail as expected."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_lun_expsz.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_lun_expsz.ksh
new file mode 100755
index 000000000000..59f64081a977
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_lun_expsz.ksh
@@ -0,0 +1,61 @@
+#!/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/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we can expand a device while the pool has a
+# checkpoint but in the case of a rewind that device rewinds
+# back to its previous size.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Expand the device and modify some data
+# (include at least one destructive change)
+# 5. Rewind to checkpoint
+# 6. Verify that we rewinded successfully and check if the
+# device shows up expanded in the vdev list
+#
+
+verify_runnable "global"
+
+EXPSZ=2G
+
+setup_nested_pools
+log_onexit cleanup_nested_pools
+
+populate_nested_pool
+INITSZ=$(zpool list -v | grep "$FILEDISK1" | awk '{print $2}')
+log_must zpool checkpoint $NESTEDPOOL
+
+log_must truncate -s $EXPSZ $FILEDISK1
+log_must zpool online -e $NESTEDPOOL $FILEDISK1
+NEWSZ=$(zpool list -v | grep "$FILEDISK1" | awk '{print $2}')
+nested_change_state_after_checkpoint
+log_mustnot [ "$INITSZ" = "$NEWSZ" ]
+
+log_must zpool export $NESTEDPOOL
+log_must zpool import -d $FILEDISKDIR --rewind-to-checkpoint $NESTEDPOOL
+
+nested_verify_pre_checkpoint_state
+FINSZ=$(zpool list -v | grep "$FILEDISK1" | awk '{print $2}')
+log_must [ "$INITSZ" = "$FINSZ" ]
+
+log_pass "LUN expansion rewinded correctly."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_open.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_open.ksh
new file mode 100755
index 000000000000..018478af8d61
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_open.ksh
@@ -0,0 +1,48 @@
+#!/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/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we can open a checkpointed pool.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Modify data (include at least one destructive change)
+# 5. Export and import pool
+# 6. Verify that the pool was opened with the most current
+# data and not the checkpointed state.
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+populate_test_pool
+log_must zpool checkpoint $TESTPOOL
+test_change_state_after_checkpoint
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+test_verify_post_checkpoint_state
+
+log_pass "Open a checkpointed pool."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_removal.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_removal.ksh
new file mode 100755
index 000000000000..514a05984160
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_removal.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) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Attempt to take a checkpoint while a removal is
+# in progress. The attempt should fail.
+#
+# STRATEGY:
+# 1. Create pool with one disk
+# 2. Create a big file in the pool, so when the disk
+# is later removed, it will give us enough of a
+# time window to attempt the checkpoint while the
+# removal takes place
+# 3. Add a second disk where all the data will be moved
+# to when the first disk will be removed.
+# 4. Start removal of first disk
+# 5. Attempt to checkpoint (attempt should fail)
+#
+
+verify_runnable "global"
+
+function callback
+{
+ log_mustnot zpool checkpoint $TESTPOOL
+ return 0
+}
+
+#
+# Create pool
+#
+setup_test_pool
+log_onexit cleanup_test_pool
+populate_test_pool
+
+#
+# Create big empty file and do some writes at random
+# offsets to ensure that it takes up space. Note that
+# the implicitly created filesystem ($FS0) does not
+# have compression enabled.
+#
+log_must mkfile $BIGFILESIZE $FS0FILE
+log_must randwritecomp $FS0FILE 1000
+
+#
+# Add second disk
+#
+log_must zpool add $TESTPOOL $EXTRATESTDISK
+
+#
+# Remove disk and attempt to take checkpoint
+#
+log_must attempt_during_removal $TESTPOOL $TESTDISK callback
+log_must zpool status $TESTPOOL
+
+log_pass "Attempting to checkpoint during removal fails as expected."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_rewind.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_rewind.ksh
new file mode 100755
index 000000000000..2a2bb2deed80
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_rewind.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) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we can rewind on a checkpointed pool.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Modify data (include at least one destructive change)
+# 5. Rewind to checkpoint
+# 6. Verify that the data before the checkpoint are present
+# and the data after the checkpoint is gone.
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+populate_test_pool
+
+log_must zpool checkpoint $TESTPOOL
+
+test_change_state_after_checkpoint
+
+log_must zpool export $TESTPOOL
+log_must zpool import --rewind-to-checkpoint $TESTPOOL
+
+test_verify_pre_checkpoint_state
+
+log_pass "Rewind on a checkpointed pool."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_ro_rewind.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_ro_rewind.ksh
new file mode 100755
index 000000000000..fd7416612b7c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_ro_rewind.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) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we can open the checkpointed state of a pool
+# as read-only.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Modify data (include at least one destructive change)
+# 5. Export and import the checkpointed state as readonly
+# 6. Verify that we can see the checkpointed state and not
+# the actual current state.
+# 7. Export and import the current state
+# 8. Verify that we can see the current state and not the
+# checkpointed state.
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+populate_test_pool
+log_must zpool checkpoint $TESTPOOL
+test_change_state_after_checkpoint
+
+log_must zpool export $TESTPOOL
+log_must zpool import -o readonly=on --rewind-to-checkpoint $TESTPOOL
+
+test_verify_pre_checkpoint_state "ro-check"
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+test_verify_post_checkpoint_state
+
+log_pass "Open checkpointed state of the pool as read-only pool."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_sm_scale.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_sm_scale.ksh
new file mode 100755
index 000000000000..e24c4eb55252
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_sm_scale.ksh
@@ -0,0 +1,92 @@
+#!/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, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# The maximum address that can be described by a single-word
+# space map entry limits the maximum allocatable space of any
+# top-level vdev to 64PB whenever a vdev-wide space map is used.
+#
+# Since a vdev-wide space map is introduced for the checkpoint
+# we want to ensure that we cannot checkpoint a pool that does
+# not use the new space map encoding (V2) and has a top-level
+# vdev with more than 64PB of allocatable space.
+#
+# Note: Since this is a pool created from file-based vdevs we
+# are guaranteed that vdev_ashift is SPA_MINBLOCKSHIFT
+# [which is currently 9 and (1 << 9) = 512], so the numbers
+# work out for this test.
+#
+# STRATEGY:
+# 1. Create pool with a disk of exactly 64PB
+# (so ~63.5PB of allocatable space) and
+# ensure that has the checkpoint feature
+# enabled but not space map V2
+# 2. Ensure that you can checkpoint it
+# 3. Create pool with a disk of exactly 65PB
+# (so ~64.5PB of allocatable space) with
+# the same setup
+# 4. Ensure we fail trying to checkpoint it
+#
+# Note:
+# This test used to create the two pools and attempt to checkpoint
+# them at the same time, then destroy them. We later had to change
+# this to test one pool at a time as the metaslabs (even though empty)
+# consumed a lot of memory, especially on a machine that has been
+# running with debug enabled. To give an example, each metaslab
+# structure is ~1712 bytes (at the time of this writing), and each
+# vdev has 128K metaslabs, which means that just the structures
+# consume 131071 * 1712 = ~224M.
+#
+
+verify_runnable "global"
+
+TESTPOOL1=testpool1
+TESTPOOL2=testpool2
+
+DISK64PB=/$DISKFS/disk64PB
+DISK65PB=/$DISKFS/disk65PB
+
+function test_cleanup
+{
+ poolexists $TESTPOOL1 && destroy_pool $TESTPOOL1
+ poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+ log_must rm -f $DISK64PB $DISK65PB
+ cleanup_test_pool
+}
+
+setup_test_pool
+log_onexit test_cleanup
+
+log_must zfs create $DISKFS
+log_must mkfile -n $((64 * 1024 * 1024))g $DISK64PB
+log_must mkfile -n $((65 * 1024 * 1024))g $DISK65PB
+
+log_must zpool create -d $TESTPOOL1 $DISK64PB
+log_must zpool set feature@zpool_checkpoint=enabled $TESTPOOL1
+log_must zpool checkpoint $TESTPOOL1
+destroy_pool $TESTPOOL1
+
+log_must zpool create -d $TESTPOOL2 $DISK65PB
+log_must zpool set feature@zpool_checkpoint=enabled $TESTPOOL2
+log_mustnot zpool checkpoint $TESTPOOL2
+destroy_pool $TESTPOOL2
+
+log_pass "Fail to checkpoint pool with old spacemap encoding" \
+ " and a vdev that's more than 64PB."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_twice.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_twice.ksh
new file mode 100755
index 000000000000..3f1076b94c4e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_twice.ksh
@@ -0,0 +1,40 @@
+#!/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/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Attempt to take a checkpoint for an already
+# checkpointed pool. The attempt should fail.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Checkpoint it
+# 3. Attempt to checkpoint it again (should fail).
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+log_must zpool checkpoint $TESTPOOL
+log_mustnot zpool checkpoint $TESTPOOL
+
+log_pass "Attempting to checkpoint an already checkpointed " \
+ "pool fails as expected."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_vdev_add.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_vdev_add.ksh
new file mode 100755
index 000000000000..efb69b7c0ee9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_vdev_add.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) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we can add a device while the pool has a
+# checkpoint but in the case of a rewind that device does
+# not show up.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Add device and modify data
+# (include at least one destructive change)
+# 5. Rewind to checkpoint
+# 6. Verify that we rewinded successfully and check if the
+# device shows up in the vdev list
+#
+
+verify_runnable "global"
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+populate_test_pool
+
+log_must zpool checkpoint $TESTPOOL
+log_must zpool add $TESTPOOL $EXTRATESTDISK
+
+#
+# Ensure that the vdev shows up
+#
+log_must eval "zpool list -v $TESTPOOL | grep $EXTRATESTDISK"
+test_change_state_after_checkpoint
+
+log_must zpool export $TESTPOOL
+log_must zpool import --rewind-to-checkpoint $TESTPOOL
+
+test_verify_pre_checkpoint_state
+
+#
+# Ensure that the vdev doesn't show up after the rewind
+#
+log_mustnot eval "zpool list -v $TESTPOOL | grep $EXTRATESTDISK"
+
+log_pass "Add device in checkpointed pool."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.ksh
new file mode 100755
index 000000000000..fdefc0c3bdbb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.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) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that checkpoint verification within zdb works as
+# we expect.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Modify data (include at least one destructive change)
+# 5. Verify zdb finds checkpoint when run on current state
+# 6. Verify zdb finds old dataset when run on checkpointed
+# state
+# 7. Export pool, and verify the same things with zdb to
+# test the -e option.
+# 8. Import pool and discard checkpoint
+# 9. Verify zdb does not find the checkpoint anymore in the
+# current state.
+# 10.Verify that zdb cannot find the checkpointed state
+# anymore when trying to open it for verification.
+#
+
+verify_runnable "global"
+
+#
+# zdb does this thing where it imports the checkpointed state of the
+# pool under a new pool with a different name, alongside the pool
+# with the current state. The name of this temporary pool is the
+# name of the actual pool with the suffix below appended to it.
+#
+CHECKPOINT_SUFFIX="_CHECKPOINTED_UNIVERSE"
+CHECKPOINTED_FS1=$TESTPOOL$CHECKPOINT_SUFFIX/$TESTFS1
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+populate_test_pool
+log_must zpool checkpoint $TESTPOOL
+
+test_change_state_after_checkpoint
+
+zdb $TESTPOOL | grep "Checkpointed uberblock found" || \
+ log_fail "zdb could not find checkpointed uberblock"
+
+zdb -k $TESTPOOL | grep "Checkpointed uberblock found" && \
+ log_fail "zdb found checkpointed uberblock in checkpointed state"
+
+zdb $TESTPOOL | grep "Dataset $FS1" && \
+ log_fail "zdb found destroyed dataset in current state"
+
+zdb -k $TESTPOOL | grep "Dataset $CHECKPOINTED_FS1" || \
+ log_fail "zdb could not find destroyed dataset in checkpoint"
+
+log_must zpool export $TESTPOOL
+
+zdb -e $TESTPOOL | grep "Checkpointed uberblock found" || \
+ log_fail "zdb could not find checkpointed uberblock"
+
+zdb -k -e $TESTPOOL | grep "Checkpointed uberblock found" && \
+ log_fail "zdb found checkpointed uberblock in checkpointed state"
+
+zdb -e $TESTPOOL | grep "Dataset $FS1" && \
+ log_fail "zdb found destroyed dataset in current state"
+
+zdb -k -e $TESTPOOL | grep "Dataset $CHECKPOINTED_FS1" || \
+ log_fail "zdb could not find destroyed dataset in checkpoint"
+
+log_must zpool import $TESTPOOL
+
+log_must zpool checkpoint -d $TESTPOOL
+
+zdb $TESTPOOL | grep "Checkpointed uberblock found" && \
+ log_fail "zdb found checkpointed uberblock after discarding " \
+ "the checkpoint"
+
+zdb -k $TESTPOOL && \
+ log_fail "zdb opened checkpointed state that was discarded"
+
+log_pass "zdb can analyze checkpointed pools."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zhack_feat.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zhack_feat.ksh
new file mode 100755
index 000000000000..815fc8573987
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zhack_feat.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) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+#
+# DESCRIPTION:
+# Ensure that we can rewind to a checkpointed state that was
+# before a readonly-compatible feature was introduced.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Populate it
+# 3. Take checkpoint
+# 4. Modify data (include at least one destructive change)
+# 5. Export pool
+# 6. Introduce a new feature in the pool which is unsupported
+# but readonly-compatible and increment its reference
+# number so it is marked active.
+# 7. Verify that the pool can't be opened writeable, but we
+# can rewind to the checkpoint (before the feature was
+# introduced) if we want to.
+#
+
+verify_runnable "global"
+
+#
+# Clear all labels from all vdevs so zhack
+# doesn't get confused
+#
+for disk in ${DISKS[@]}; do
+ zpool labelclear -f $disk
+done
+
+setup_test_pool
+log_onexit cleanup_test_pool
+
+populate_test_pool
+log_must zpool checkpoint $TESTPOOL
+test_change_state_after_checkpoint
+
+log_must zpool export $TESTPOOL
+
+log_must zhack feature enable -r $TESTPOOL 'com.company:future_feature'
+log_must zhack feature ref $TESTPOOL 'com.company:future_feature'
+
+log_mustnot zpool import $TESTPOOL
+log_must zpool import --rewind-to-checkpoint $TESTPOOL
+
+test_verify_pre_checkpoint_state
+
+log_pass "Rewind to checkpoint from unsupported pool feature."
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/cleanup.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/cleanup.ksh
new file mode 100755
index 000000000000..5fa03d74f6b6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/cleanup.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/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+verify_runnable "global"
+
+test_group_destroy_saved_pool
+log_pass
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/pool_checkpoint.kshlib b/tests/zfs-tests/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
new file mode 100644
index 000000000000..ea6c03e9d59d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
@@ -0,0 +1,413 @@
+#
+# 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, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# In general all the tests related to the pool checkpoint can
+# be divided into two categories. TESTS that verify features
+# provided by the checkpoint (e.g. checkpoint_rewind) and tests
+# that stress-test the checkpoint (e.g. checkpoint_big_rewind).
+#
+# For the first group we don't really care about the size of
+# the pool or the individual file sizes within the filesystems.
+# This is why these tests run directly on pools that use a
+# "real disk vdev" (meaning not a file based one). These tests
+# use the $TESTPOOL pool that is created on top of $TESTDISK.
+# This pool is referred to as the "test pool" and thus all
+# the tests of this group use the testpool-related functions of
+# this file (not the nested_pools ones).
+#
+# For the second group we generally try to bring the pool to its
+# limits by increasing fragmentation, filling all allocatable
+# space, attempting to use vdevs that the checkpoint spacemap
+# cannot represent, etc. For these tests we need to control
+# almost all parameters of the pool and the vdevs that back it
+# so we create them based on file-based vdevs that we carefully
+# create within the $TESTPOOL pool. So most of these tests, in
+# order to create this nested pool sctructure, generally start
+# like this:
+# 1] We create the test pool ($TESTPOOL).
+# 2] We create a filesystem and we populate it with files of
+# some predetermined size.
+# 3] We use those files as vdevs for the pool that the test
+# will use ($NESTEDPOOL).
+# 4] Go on and let the test run and operate on $NESTEDPOOL.
+#
+
+#
+# These disks are used to back $TESTPOOL
+#
+TESTDISK="$(echo $DISKS | cut -d' ' -f1)"
+EXTRATESTDISK="$(echo $DISKS | cut -d' ' -f2)"
+
+FS0=$TESTPOOL/$TESTFS
+FS1=$TESTPOOL/$TESTFS1
+FS2=$TESTPOOL/$TESTFS2
+
+FS0FILE=/$FS0/$TESTFILE0
+FS1FILE=/$FS1/$TESTFILE1
+FS2FILE=/$FS2/$TESTFILE2
+
+#
+# The following are created within $TESTPOOL and
+# will be used to back $NESTEDPOOL
+#
+DISKFS=$TESTPOOL/disks
+FILEDISKDIR=/$DISKFS
+FILEDISK1=/$DISKFS/dsk1
+FILEDISK2=/$DISKFS/dsk2
+FILEDISKS="$FILEDISK1 $FILEDISK2"
+
+#
+# $NESTEDPOOL related variables
+#
+NESTEDPOOL=nestedpool
+NESTEDFS0=$NESTEDPOOL/$TESTFS
+NESTEDFS1=$NESTEDPOOL/$TESTFS1
+NESTEDFS2=$NESTEDPOOL/$TESTFS2
+NESTEDFS0FILE=/$NESTEDFS0/$TESTFILE0
+NESTEDFS1FILE=/$NESTEDFS1/$TESTFILE1
+NESTEDFS2FILE=/$NESTEDFS2/$TESTFILE2
+
+#
+# In the tests that stress-test the pool (second category
+# mentioned above), there exist some that need to bring
+# fragmentation at high percentages in a relatively short
+# period of time. In order to do that we set the following
+# parameters:
+#
+# * We use two disks of 1G each, to create a pool of size 2G.
+# The point is that 2G is not small nor large, and we also
+# want to have 2 disks to introduce indirect vdevs on our
+# setup.
+# * We enable compression and set the record size of all
+# filesystems to 8K. The point of compression is to
+# ensure that we are not filling up the whole pool (that's
+# what checkpoint_capacity is for), and the specific
+# record size is set to match the block size of randwritecomp
+# which is used to increase fragmentation by writing on
+# files.
+# * We always have 2 big files present of 512M each, which
+# should account for 40%~50% capacity by the end of each
+# test with fragmentation around 50~60%.
+# * At each file we attempt to do enough random writes to
+# touch every offset twice on average.
+#
+# Note that the amount of random writes per files are based
+# on the following calculation:
+#
+# ((512M / 8K) * 3) * 2 = ~400000
+#
+# Given that the file is 512M and one write is 8K, we would
+# need (512M / 8K) writes to go through the whole file.
+# Assuming though that each write has a compression ratio of
+# 3, then we want 3 times that to cover the same amount of
+# space. Finally, we multiply that by 2 since our goal is to
+# touch each offset twice on average.
+#
+# Examples of those tests are checkpoint_big_rewind and
+# checkpoint_discard_busy.
+#
+FILEDISKSIZE=1g
+DISKSIZE=1g
+BIGFILESIZE=512M
+RANDOMWRITES=400000
+
+
+#
+# Assumes create_test_pool has been called beforehand.
+#
+function setup_nested_pool
+{
+ log_must zfs create $DISKFS
+
+ log_must truncate -s $DISKSIZE $FILEDISK1
+ log_must truncate -s $DISKSIZE $FILEDISK2
+
+ log_must zpool create -O sync=disabled $NESTEDPOOL $FILEDISKS
+}
+
+function setup_test_pool
+{
+ log_must zpool create -O sync=disabled $TESTPOOL "$TESTDISK"
+}
+
+function setup_nested_pools
+{
+ setup_test_pool
+ setup_nested_pool
+}
+
+function cleanup_nested_pool
+{
+ log_must zpool destroy $NESTEDPOOL
+ log_must rm -f $FILEDISKS
+}
+
+function cleanup_test_pool
+{
+ log_must zpool destroy $TESTPOOL
+
+ #
+ # We always clear the labels of all disks
+ # between tests so imports from zpool or
+ # or zdb do not get confused with leftover
+ # data from old pools.
+ #
+ for disk in $DISKS; do
+ zpool labelclear -f $disk
+ done
+}
+
+function cleanup_nested_pools
+{
+ cleanup_nested_pool
+ cleanup_test_pool
+}
+
+#
+# Remove and re-add each vdev to ensure that data is
+# moved between disks and indirect mappings are created
+#
+function introduce_indirection
+{
+ for disk in ${FILEDISKS[@]}; do
+ log_must zpool remove $NESTEDPOOL $disk
+ log_must wait_for_removal $NESTEDPOOL
+ log_mustnot vdevs_in_pool $NESTEDPOOL $disk
+ log_must zpool add $NESTEDPOOL $disk
+ done
+}
+
+FILECONTENTS0="Can't wait to be checkpointed!"
+FILECONTENTS1="Can't wait to be checkpointed too!"
+NEWFILECONTENTS0="I survived after the checkpoint!"
+NEWFILECONTENTS2="I was born after the checkpoint!"
+
+function populate_test_pool
+{
+ log_must zfs create -o compression=lz4 -o recordsize=8k $FS0
+ log_must zfs create -o compression=lz4 -o recordsize=8k $FS1
+
+ echo $FILECONTENTS0 > $FS0FILE
+ echo $FILECONTENTS1 > $FS1FILE
+}
+
+function populate_nested_pool
+{
+ log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS0
+ log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS1
+
+ echo $FILECONTENTS0 > $NESTEDFS0FILE
+ echo $FILECONTENTS1 > $NESTEDFS1FILE
+}
+
+function test_verify_pre_checkpoint_state
+{
+ log_must zfs list $FS0
+ log_must zfs list $FS1
+ log_must [ "$(<$FS0FILE)" = "$FILECONTENTS0" ]
+ log_must [ "$(<$FS1FILE)" = "$FILECONTENTS1" ]
+
+ #
+ # If we've opened the checkpointed state of the
+ # pool as read-only without rewinding on-disk we
+ # can't really use zdb on it.
+ #
+ if [[ "$1" != "ro-check" ]] ; then
+ log_must zdb $TESTPOOL
+ fi
+
+ #
+ # Ensure post-checkpoint state is not present
+ #
+ log_mustnot zfs list $FS2
+ log_mustnot [ "$(<$FS0FILE)" = "$NEWFILECONTENTS0" ]
+}
+
+function nested_verify_pre_checkpoint_state
+{
+ log_must zfs list $NESTEDFS0
+ log_must zfs list $NESTEDFS1
+ log_must [ "$(<$NESTEDFS0FILE)" = "$FILECONTENTS0" ]
+ log_must [ "$(<$NESTEDFS1FILE)" = "$FILECONTENTS1" ]
+
+ #
+ # If we've opened the checkpointed state of the
+ # pool as read-only without rewinding on-disk we
+ # can't really use zdb on it.
+ #
+ if [[ "$1" != "ro-check" ]] ; then
+ log_must zdb $NESTEDPOOL
+ fi
+
+ #
+ # Ensure post-checkpoint state is not present
+ #
+ log_mustnot zfs list $NESTEDFS2
+ log_mustnot [ "$(<$NESTEDFS0FILE)" = "$NEWFILECONTENTS0" ]
+}
+
+function test_change_state_after_checkpoint
+{
+ log_must zfs destroy $FS1
+ log_must zfs create -o compression=lz4 -o recordsize=8k $FS2
+
+ echo $NEWFILECONTENTS0 > $FS0FILE
+ echo $NEWFILECONTENTS2 > $FS2FILE
+}
+
+function nested_change_state_after_checkpoint
+{
+ log_must zfs destroy $NESTEDFS1
+ log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS2
+
+ echo $NEWFILECONTENTS0 > $NESTEDFS0FILE
+ echo $NEWFILECONTENTS2 > $NESTEDFS2FILE
+}
+
+function test_verify_post_checkpoint_state
+{
+ log_must zfs list $FS0
+ log_must zfs list $FS2
+ log_must [ "$(<$FS0FILE)" = "$NEWFILECONTENTS0" ]
+ log_must [ "$(<$FS2FILE)" = "$NEWFILECONTENTS2" ]
+
+ log_must zdb $TESTPOOL
+
+ #
+ # Ensure pre-checkpointed state that was removed post-checkpoint
+ # is not present
+ #
+ log_mustnot zfs list $FS1
+ log_mustnot [ "$(<$FS0FILE)" = "$FILECONTENTS0" ]
+}
+
+function fragment_before_checkpoint
+{
+ populate_nested_pool
+ log_must mkfile -n $BIGFILESIZE $NESTEDFS0FILE
+ log_must mkfile -n $BIGFILESIZE $NESTEDFS1FILE
+ log_must randwritecomp $NESTEDFS0FILE $RANDOMWRITES
+ log_must randwritecomp $NESTEDFS1FILE $RANDOMWRITES
+
+ #
+ # Display fragmentation on test log
+ #
+ log_must zpool list -v
+}
+
+function fragment_after_checkpoint_and_verify
+{
+ log_must zfs destroy $NESTEDFS1
+ log_must zfs create -o compression=lz4 -o recordsize=8k $NESTEDFS2
+ log_must mkfile -n $BIGFILESIZE $NESTEDFS2FILE
+ log_must randwritecomp $NESTEDFS0FILE $RANDOMWRITES
+ log_must randwritecomp $NESTEDFS2FILE $RANDOMWRITES
+
+ #
+ # Display fragmentation on test log
+ #
+ log_must zpool list -v
+
+ #
+ # Typically we would just run zdb at this point and things
+ # would be fine. Unfortunately, if there is still any
+ # background I/O in the pool the zdb command can fail with
+ # checksum errors temporarily.
+ #
+ # Export the pool when running zdb so the pool is idle and
+ # the verification results are consistent.
+ #
+ log_must zpool export $NESTEDPOOL
+ log_must zdb -e -p $FILEDISKDIR $NESTEDPOOL
+ log_must zdb -e -p $FILEDISKDIR -kc $NESTEDPOOL
+ log_must zpool import -d $FILEDISKDIR $NESTEDPOOL
+}
+
+function wait_discard_finish
+{
+ typeset pool="$1"
+
+ typeset status
+ status=$(zpool status $pool | grep "checkpoint:")
+ while [ "" != "$status" ]; do
+ sleep 5
+ status=$(zpool status $pool | grep "checkpoint:")
+ done
+}
+
+function test_wait_discard_finish
+{
+ wait_discard_finish $TESTPOOL
+}
+
+function nested_wait_discard_finish
+{
+ wait_discard_finish $NESTEDPOOL
+}
+
+#
+# Creating the setup for the second group of tests mentioned in
+# block comment of this file can take some time as we are doing
+# random writes to raise capacity and fragmentation before taking
+# the checkpoint. Thus we create this setup once and save the
+# disks of the nested pool in a temporary directory where we can
+# reuse it for each test that requires that setup.
+#
+SAVEDPOOLDIR="$TEST_BASE_DIR/ckpoint_saved_pool"
+
+function test_group_premake_nested_pools
+{
+ setup_nested_pools
+
+ #
+ # Populate and fragment the pool.
+ #
+ fragment_before_checkpoint
+
+ #
+ # Export and save the pool for other tests.
+ #
+ log_must zpool export $NESTEDPOOL
+ log_must mkdir $SAVEDPOOLDIR
+ log_must cp $FILEDISKS $SAVEDPOOLDIR
+
+ #
+ # Reimport pool to be destroyed by
+ # cleanup_nested_pools function
+ #
+ log_must zpool import -d $FILEDISKDIR $NESTEDPOOL
+}
+
+function test_group_destroy_saved_pool
+{
+ log_must rm -rf $SAVEDPOOLDIR
+}
+
+#
+# Recreate nested pool setup from saved pool.
+#
+function setup_nested_pool_state
+{
+ setup_test_pool
+
+ log_must zfs create $DISKFS
+ log_must cp $SAVEDPOOLDIR/* $FILEDISKDIR
+
+ log_must zpool import -d $FILEDISKDIR $NESTEDPOOL
+}
diff --git a/tests/zfs-tests/tests/functional/pool_checkpoint/setup.ksh b/tests/zfs-tests/tests/functional/pool_checkpoint/setup.ksh
new file mode 100755
index 000000000000..118400cb2a00
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_checkpoint/setup.ksh
@@ -0,0 +1,25 @@
+#!/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/tests/functional/pool_checkpoint/pool_checkpoint.kshlib
+
+verify_runnable "global"
+
+test_group_premake_nested_pools
+log_onexit cleanup_nested_pools
+
+log_pass "Successfully saved pool to be reused for tests in the group."
diff --git a/tests/zfs-tests/tests/functional/pool_names/Makefile.am b/tests/zfs-tests/tests/functional/pool_names/Makefile.am
new file mode 100644
index 000000000000..cd874861f0ac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_names/Makefile.am
@@ -0,0 +1,4 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/pool_names
+dist_pkgdata_SCRIPTS = \
+ pool_names_001_pos.ksh \
+ pool_names_002_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/pool_names/pool_names_001_pos.ksh b/tests/zfs-tests/tests/functional/pool_names/pool_names_001_pos.ksh
new file mode 100755
index 000000000000..45ef2fd67a96
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_names/pool_names_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# Test that a set of valid names can be used to create pools. Further
+# verify that the created pools can be destroyed.
+#
+# STRATEGY:
+# 1) For each valid character in the character set, try to create
+# and destroy the pool.
+# 2) Given a list of valid pool names, try to create and destroy
+# pools with the given names.
+#
+
+verify_runnable "global"
+
+log_assert "Ensure that pool names can use the ASCII subset of UTF-8"
+
+function cleanup
+{
+ if [[ -n $name ]] && poolexists $name ; then
+ log_must zpool destroy $name
+ fi
+
+ if [[ -d $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR
+ fi
+
+}
+
+log_onexit cleanup
+
+DISK=${DISKS%% *}
+if [[ ! -e $TESTDIR ]]; then
+ log_must mkdir $TESTDIR
+fi
+
+log_note "Ensure letters of the alphabet are allowable"
+
+typeset name=""
+
+for name in 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 y z
+do
+ log_must zpool create -m $TESTDIR $name $DISK
+ if ! poolexists $name; then
+ log_fail "Could not create a pool called '$name'"
+ fi
+
+ log_must zpool destroy $name
+done
+
+log_note "Ensure a variety of unusual names passes"
+
+name=""
+
+for name in "a.............................." "a_" "a-" "a:" \
+ "a." "a123456" "bc0t0d0" "m1rr0r_p00l" "ra1dz_p00l" \
+ "araidz2" "C0t2d0" "cc0t0" "raid2:-_." "mirr_:-." \
+ "m1rr0r-p00l" "ra1dz-p00l" "spar3_p00l" \
+ "spar3-p00l" "hiddenmirrorpool" "hiddenraidzpool" \
+ "hiddensparepool"
+do
+ log_must zpool create -m $TESTDIR $name $DISK
+ if ! poolexists $name; then
+ log_fail "Could not create a pool called '$name'"
+ fi
+
+ #
+ # Since the naming convention applies to datasets too,
+ # create datasets with the same names as above.
+ #
+ log_must zfs create $name/$name
+ log_must zfs snapshot $name/$name@$name
+ log_must zfs clone $name/$name@$name $name/clone_$name
+ log_must zfs create -V 150m $name/$name/$name
+ block_device_wait
+
+ log_must zpool destroy $name
+done
+
+log_pass "Valid pool names were accepted correctly."
diff --git a/tests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh b/tests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh
new file mode 100755
index 000000000000..0c96e1999ef4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pool_names/pool_names_002_neg.ksh
@@ -0,0 +1,129 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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
+
+#
+# DESCRIPTION:
+#
+# Ensure that a set of invalid names cannot be used to create pools.
+#
+# STRATEGY:
+# 1) For each invalid character in the character set, try to create
+# and destroy the pool. Verify it fails.
+# 2) Given a list of invalid pool names, ensure the pools are not
+# created.
+#
+
+verify_runnable "global"
+
+log_assert "Ensure that a set of invalid names cannot be used to create pools."
+
+# Global variable use to cleanup failures.
+POOLNAME=""
+
+function cleanup
+{
+ if poolexists $POOLNAME; then
+ log_must zpool destroy $POOLNAME
+ fi
+
+ if [[ -d $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR
+ fi
+}
+
+log_onexit cleanup
+
+for pool in $(get_all_pools); do
+ if [[ "$pool" != "$TESTPOOL" ]]; then
+ log_must zpool destroy $pool
+ fi
+done
+
+DISK=${DISKS%% *}
+if [[ ! -e $TESTDIR ]]; then
+ log_must mkdir $TESTDIR
+fi
+
+log_note "Ensure invalid characters fail"
+for POOLNAME in "!" "\"" "#" "$" "%" "&" "'" "(" ")" \
+ "\*" "+" "," "-" "\." "/" "\\" \
+ 0 1 2 3 4 5 6 7 8 9 \
+ ":" ";" "<" "=" ">" "\?" "@" \
+ "[" "]" "^" "_" "\`" "{" "|" "}" "~"
+do
+ log_mustnot zpool create -m $TESTDIR $POOLNAME $DISK
+ if poolexists $POOLNAME; then
+ log_fail "Unexpectedly created pool: '$POOLNAME'"
+ fi
+
+ log_mustnot zpool destroy $POOLNAME
+done
+
+log_note "Check that invalid octal values fail"
+for oct in "\000" "\001" "\002" "\003" "\004" "\005" "\006" "\007" \
+ "\010" "\011" "\012" "\013" "\014" "\015" "\017" \
+ "\020" "\021" "\022" "\023" "\024" "\025" "\026" "\027" \
+ "\030" "\031" "\032" "\033" "\034" "\035" "\036" "\037" \
+ "\040" "\177"
+do
+ POOLNAME=`eval "echo x | tr 'x' '$oct'"`
+ log_mustnot zpool create -m $TESTDIR $POOLNAME $DISK
+ if poolexists $POOLNAME; then
+ log_fail "Unexpectedly created pool: '$POOLNAME'"
+ fi
+
+ log_mustnot zpool destroy $POOLNAME
+done
+
+log_note "Verify invalid pool names fail"
+set -A POOLNAME "c0t0d0s0" "c0t0d0" "c0t0d19" "c0t50000E0108D279d0" \
+ "mirror" "raidz" ",," ",,,,,,,,,,,,,,,,,,,,,,,,," \
+ "2222222222222222222" "mirror_pool" "raidz_pool" \
+ "mirror-pool" "raidz-pool" "spare" "spare_pool" \
+ "spare-pool" "raidz1-" "raidz2:" ":aaa" "-bbb" "_ccc" ".ddd"
+if verify_slog_support ; then
+ POOLNAME[${#POOLNAME[@]}]='log'
+fi
+typeset -i i=0
+while ((i < ${#POOLNAME[@]})); do
+ log_mustnot zpool create -m $TESTDIR ${POOLNAME[$i]} $DISK
+ if poolexists ${POOLNAME[$i]}; then
+ log_fail "Unexpectedly created pool: '${POOLNAME[$i]}'"
+ fi
+
+ log_mustnot zpool destroy ${POOLNAME[$i]}
+
+ ((i += 1))
+done
+
+log_pass "Invalid names and characters were caught correctly"
diff --git a/tests/zfs-tests/tests/functional/poolversion/Makefile.am b/tests/zfs-tests/tests/functional/poolversion/Makefile.am
new file mode 100644
index 000000000000..51c2046457df
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/poolversion/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/poolversion
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ poolversion_001_pos.ksh \
+ poolversion_002_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/poolversion/cleanup.ksh b/tests/zfs-tests/tests/functional/poolversion/cleanup.ksh
new file mode 100755
index 000000000000..c9777b27e406
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/poolversion/cleanup.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.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_must zpool destroy $TESTPOOL
+log_must zpool destroy $TESTPOOL2
+
+log_must rm $TEST_BASE_DIR/zpool_version_1.dat
+log_must rm $TEST_BASE_DIR/zpool2_version_1.dat
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.ksh b/tests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.ksh
new file mode 100755
index 000000000000..048cb29e3217
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/poolversion/poolversion_001_pos.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 2009 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
+
+#
+# DESCRIPTION:
+#
+# zpool set version can upgrade a pool
+#
+# STRATEGY:
+# 1. Taking a version 1 pool
+# 2. For all known versions, set the version of the pool using zpool set
+# 3. Verify that pools version
+#
+
+verify_runnable "global"
+log_assert "zpool set version can upgrade a pool"
+for version in 1 2 3 4 5 6 7 8
+do
+ log_must zpool set version=$version $TESTPOOL
+ ACTUAL=$(zpool get version $TESTPOOL | grep version \
+ | awk '{print $3}')
+ if [ "$ACTUAL" != "$version" ]
+ then
+ log_fail "v. $ACTUAL set for $TESTPOOL, expected v. $version!"
+ fi
+done
+
+log_pass "zpool set version can upgrade a pool"
diff --git a/tests/zfs-tests/tests/functional/poolversion/poolversion_002_pos.ksh b/tests/zfs-tests/tests/functional/poolversion/poolversion_002_pos.ksh
new file mode 100755
index 000000000000..69586473eaab
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/poolversion/poolversion_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# zpool set version can only increment pool version
+#
+# STRATEGY:
+# 1. Set a version 1 pool to be a version 6 pool
+# 2. Verify it's set to version 6
+# 3. Attempt to set prior versions
+# 4. Verify it's still set to version 6
+#
+
+verify_runnable "global"
+log_assert "zpool set version can only increment pool version"
+
+log_must zpool set version=6 $TESTPOOL2
+# verify it's actually that version - by checking the version property
+# and also by trying to set bootfs (which should fail if it is not version 6)
+
+VERSION=$(zpool get version $TESTPOOL2| grep version | awk '{print $3}')
+if [ "$VERSION" != "6" ]
+then
+ log_fail "Version $VERSION set for $TESTPOOL2 expected version 6!"
+fi
+log_must zpool set bootfs=$TESTPOOL2 $TESTPOOL2
+
+# now verify we can't downgrade the version
+log_mustnot zpool set version=5 $TESTPOOL2
+log_mustnot zpool set version=-1 $TESTPOOL2
+
+# verify the version is still 6
+VERSION=$(zpool get version $TESTPOOL2 | grep version | awk '{print $3}')
+if [ "$VERSION" != "6" ]
+then
+ log_fail "Version $VERSION set for $TESTPOOL2, expected version 6!"
+fi
+
+log_pass "zpool set version can only increment pool version"
diff --git a/tests/zfs-tests/tests/functional/poolversion/setup.ksh b/tests/zfs-tests/tests/functional/poolversion/setup.ksh
new file mode 100755
index 000000000000..660083b9fc00
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/poolversion/setup.ksh
@@ -0,0 +1,45 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+# create a version 1 pool
+log_must mkfile $MINVDEVSIZE $TEST_BASE_DIR/zpool_version_1.dat
+log_must zpool create -o version=1 $TESTPOOL $TEST_BASE_DIR/zpool_version_1.dat
+
+
+# create another version 1 pool
+log_must mkfile $MINVDEVSIZE $TEST_BASE_DIR/zpool2_version_1.dat
+log_must zpool create -o version=1 $TESTPOOL2 $TEST_BASE_DIR/zpool2_version_1.dat
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/privilege/Makefile.am b/tests/zfs-tests/tests/functional/privilege/Makefile.am
new file mode 100644
index 000000000000..ef26a750bb00
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/privilege/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/privilege
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ privilege_001_pos.ksh \
+ privilege_002_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/privilege/cleanup.ksh b/tests/zfs-tests/tests/functional/privilege/cleanup.ksh
new file mode 100755
index 000000000000..99985c670f2f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/privilege/cleanup.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 2007 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
+
+if is_linux || is_freebsd; then
+ log_unsupported "Privilege tests require pfexec command"
+fi
+
+verify_runnable "global"
+
+ZFS_USER=$(<$TEST_BASE_DIR/zfs-privs-test-user.txt)
+[[ -z $ZFS_USER ]] && log_fail "no ZFS_USER found"
+
+USES_NIS=$(<$TEST_BASE_DIR/zfs-privs-test-nis.txt)
+
+if [ "${USES_NIS}" == "true" ]
+then
+ svcadm enable svc:/network/nis/client:default
+fi
+
+userdel $ZFS_USER
+[[ -d /export/home/$ZFS_USER ]] && rm -rf /export/home/$ZFS_USER
+rm $TEST_BASE_DIR/zfs-privs-test-nis.txt
+rm $TEST_BASE_DIR/zfs-privs-test-user.txt
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/privilege/privilege_001_pos.ksh b/tests/zfs-tests/tests/functional/privilege/privilege_001_pos.ksh
new file mode 100755
index 000000000000..af4f705679a5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/privilege/privilege_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# The RBAC profile "ZFS Storage Management" works
+#
+# STRATEGY:
+# (create)
+# 1. As a normal user, try to create a pool - which should fail.
+# 2. Assign "ZFS Storage Management" profile, try to create pool again,
+# which should succeed.
+#
+# (works well with other ZFS profile tests)
+# 3. Attempt to create a ZFS filesystem, which should fail.
+# 4. Add the "ZFS File System Management" profile, attempt to create a FS
+# which should succeed.
+#
+# (destroy)
+# 5. Remove the FS profile, then attempt to destroy the pool, which
+# should succeed.
+# 6. Remove the Storage profile, then attempt to recreate the pool, which
+# should fail.
+#
+
+# We can only run this in the global zone
+verify_runnable "global"
+
+if is_linux || is_freebsd; then
+ log_unsupported "Requires pfexec command"
+fi
+
+log_assert "The RBAC profile \"ZFS Storage Management\" works"
+
+ZFS_USER=$(<$TEST_BASE_DIR/zfs-privs-test-user.txt)
+
+# the user shouldn't be able to do anything initially
+log_mustnot user_run $ZFS_USER "zpool create $TESTPOOL $DISKS"
+log_mustnot user_run $ZFS_USER "pfexec zpool create $TESTPOOL $DISKS"
+
+# the first time we assign the profile, we insist it should work
+log_must usermod -P "ZFS Storage Management" $ZFS_USER
+log_must user_run $ZFS_USER "pfexec zpool create -f $TESTPOOL $DISKS"
+
+# ensure the user can't create a filesystem with this profile
+log_mustnot user_run $ZFS_USER "zfs create $TESTPOOL/fs"
+
+# add ZFS File System Management profile, and try to create a fs
+log_must usermod -P "ZFS File System Management" $ZFS_USER
+log_must user_run $ZFS_USER "pfexec zfs create $TESTPOOL/fs"
+
+# revoke File System Management profile
+usermod -P, $ZFS_USER
+usermod -P "ZFS Storage Management" $ZFS_USER
+
+# ensure the user can destroy pools
+log_mustnot user_run $ZFS_USER "zpool destroy $TESTPOOL"
+log_must user_run $ZFS_USER "pfexec zpool destroy $TESTPOOL"
+
+# revoke Storage Management profile
+usermod -P, $ZFS_USER
+log_mustnot user_run $ZFS_USER "pfexec zpool create -f $TESTPOOL $DISKS"
+
+log_pass "The RBAC profile \"ZFS Storage Management\" works"
diff --git a/tests/zfs-tests/tests/functional/privilege/privilege_002_pos.ksh b/tests/zfs-tests/tests/functional/privilege/privilege_002_pos.ksh
new file mode 100755
index 000000000000..ab00e3295250
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/privilege/privilege_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# The RBAC profile "ZFS File System Management" works
+#
+# STRATEGY:
+#
+# The following actions are taken, both using profile execution (pfexec)
+# and without profile execution - we make sure that the latter should
+# always fail.
+#
+# (create)
+# 1. As a normal user, try to create a filesystem - which should fail.
+# 2. Assign "ZFS File System Management" profile, try to create fs again,
+# which should succeed.
+#
+# (pools)
+# 3. Ensure a user with this profile can't perform pool administration
+# by attempting to destroy a pool.
+#
+# (destroy)
+# 5. Remove the FS profile, then attempt to destroy the fs, which
+# should fail.
+# 6. Assign the FS profile, then attempt to destroy the fs, which
+# should succeed.
+#
+
+verify_runnable "both"
+
+if is_linux || is_freebsd; then
+ log_unsupported "Requires pfexec command"
+fi
+
+log_assert "The RBAC profile \"ZFS File System Management\" works"
+
+ZFS_USER=$(<$TEST_BASE_DIR/zfs-privs-test-user.txt)
+
+# Set a $DATASET where we can create child files systems
+if is_global_zone; then
+ log_must zpool create -f $TESTPOOL $DISKS
+ DATASET=$TESTPOOL
+else
+ DATASET=zonepool/zonectr0
+fi
+
+# A user shouldn't be able to create filesystems
+log_mustnot user_run $ZFS_USER "zfs create $DATASET/zfsprivfs"
+
+# Insist this invocation of usermod works
+log_must usermod -P "ZFS File System Management" $ZFS_USER
+
+# Now try to create file systems as the user
+log_mustnot user_run $ZFS_USER "zfs create $DATASET/zfsprivfs"
+log_must user_run $ZFS_USER "pfexec zfs create $DATASET/zfsprivfs"
+
+# Ensure the user can't do anything to pools in this state:
+log_mustnot user_run $ZFS_USER "zpool destroy $DATASET"
+log_mustnot user_run $ZFS_USER "pfexec zpool destroy $DATASET"
+
+# revoke File System Management profile
+usermod -P, $ZFS_USER
+
+# Ensure the user can't create more filesystems
+log_mustnot user_run $ZFS_USER "zfs create $DATASET/zfsprivfs2"
+log_mustnot user_run $ZFS_USER "pfexec zfs create $DATASET/zfsprivfs2"
+
+# assign the profile again and destroy the fs.
+usermod -P "ZFS File System Management" $ZFS_USER
+log_must user_run $ZFS_USER "pfexec zfs destroy $DATASET/zfsprivfs"
+usermod -P, $ZFS_USER
+
+log_pass "The RBAC profile \"ZFS File System Management\" works"
diff --git a/tests/zfs-tests/tests/functional/privilege/setup.ksh b/tests/zfs-tests/tests/functional/privilege/setup.ksh
new file mode 100755
index 000000000000..4eb069394475
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/privilege/setup.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+ZFS_USER=zfsrbac
+USES_NIS=false
+
+# if we're running NIS, turn it off until we clean up
+# (it can cause useradd to take a long time, hitting our TIMEOUT)
+svcs svc:/network/nis/client:default | grep online > /dev/null
+if [ $? -eq 0 ]
+then
+ svcadm disable svc:/network/nis/client:default
+ USES_NIS=true
+fi
+
+
+# create a unique user that we can use to run the tests,
+# making sure not to clobber any existing users.
+FOUND=""
+while [ -z "${FOUND}" ]
+do
+ USER_EXISTS=$( grep $ZFS_USER /etc/passwd )
+ if [ ! -z "${USER_EXISTS}" ]
+ then
+ ZFS_USER="${ZFS_USER}x"
+ else
+ FOUND="true"
+ fi
+done
+
+log_must mkdir -p /export/home/$ZFS_USER
+log_must useradd -c "ZFS Privileges Test User" -d /export/home/$ZFS_USER $ZFS_USER
+
+echo $ZFS_USER > $TEST_BASE_DIR/zfs-privs-test-user.txt
+echo $USES_NIS > $TEST_BASE_DIR/zfs-privs-test-nis.txt
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/procfs/Makefile.am b/tests/zfs-tests/tests/functional/procfs/Makefile.am
new file mode 100644
index 000000000000..a7f022d9f210
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/procfs/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/procfs
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ procfs_list_basic.ksh \
+ procfs_list_concurrent_readers.ksh \
+ procfs_list_stale_read.ksh \
+ pool_state.ksh
diff --git a/tests/zfs-tests/tests/functional/procfs/cleanup.ksh b/tests/zfs-tests/tests/functional/procfs/cleanup.ksh
new file mode 100755
index 000000000000..8fe46577e409
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/procfs/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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/procfs/pool_state.ksh b/tests/zfs-tests/tests/functional/procfs/pool_state.ksh
new file mode 100755
index 000000000000..f4df839be637
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/procfs/pool_state.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 (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+#
+# DESCRIPTION:
+# Test /proc/spl/kstat/zfs/<pool>/state kstat
+#
+# STRATEGY:
+# 1. Create a mirrored pool
+# 2. Check that pool is ONLINE
+# 3. Fault one disk
+# 4. Check that pool is DEGRADED
+# 5. Create a new pool with a single scsi_debug disk
+# 6. Remove the disk
+# 7. Check that pool is SUSPENDED
+# 8. Add the disk back in
+# 9. Clear errors and destroy the pools
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+function cleanup
+{
+ # Destroy the scsi_debug pool
+ if [ -n "$TESTPOOL2" ] ; then
+ if [ -n "$host" ] ; then
+ # Re-enable the disk
+ scan_scsi_hosts $host
+
+ # Device may have changed names after being inserted
+ SDISK=$(get_debug_device)
+ log_must ln $DEV_RDSKDIR/$SDISK $REALDISK
+ fi
+
+ # Restore our working pool image
+ if [ -n "$BACKUP" ] ; then
+ gunzip -c $BACKUP > $REALDISK
+ log_must rm -f $BACKUP
+ fi
+
+ # Our disk is back. Now we can clear errors and destroy the
+ # pool cleanly.
+ log_must zpool clear $TESTPOOL2
+
+ # Now that the disk is back and errors cleared, wait for our
+ # hung 'zpool scrub' to finish.
+ wait
+
+ destroy_pool $TESTPOOL2
+ log_must rm $REALDISK
+ unload_scsi_debug
+ fi
+}
+
+# Check that our pool state values match what's expected
+#
+# $1: pool name
+# $2: expected state ("ONLINE", "DEGRADED", "SUSPENDED", etc)
+function check_all
+{
+ pool=$1
+ expected=$2
+
+ state1=$(zpool status $pool | awk '/state: /{print $2}');
+ state2=$(zpool list -H -o health $pool)
+ state3=$(</proc/spl/kstat/zfs/$pool/state)
+ log_note "Checking $expected = $state1 = $state2 = $state3"
+ if [[ "$expected" == "$state1" && "$expected" == "$state2" && \
+ "$expected" == "$state3" ]] ; then
+ true
+ else
+ false
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "Testing /proc/spl/kstat/zfs/<pool>/state kstat"
+
+# Test that the initial pool is healthy
+check_all $TESTPOOL "ONLINE"
+
+# Fault one of the disks, and check that pool is degraded
+DISK1=$(echo "$DISKS" | awk '{print $2}')
+log_must zpool offline -tf $TESTPOOL $DISK1
+check_all $TESTPOOL "DEGRADED"
+log_must zpool online $TESTPOOL $DISK1
+log_must zpool clear $TESTPOOL
+
+# Create a new pool out of a scsi_debug disk
+TESTPOOL2=testpool2
+MINVDEVSIZE_MB=$((MINVDEVSIZE / 1048576))
+load_scsi_debug $MINVDEVSIZE_MB 1 1 1 '512b'
+
+SDISK=$(get_debug_device)
+host=$(get_scsi_host $SDISK)
+
+# Use $REALDISK instead of $SDISK in our pool because $SDISK can change names
+# as we remove/add the disk (i.e. /dev/sdf -> /dev/sdg).
+REALDISK=/dev/kstat-state-realdisk
+log_must [ ! -e $REALDISK ]
+ln $DEV_RDSKDIR/$SDISK $REALDISK
+
+log_must zpool create $TESTPOOL2 $REALDISK
+
+# Backup the contents of the disk image
+BACKUP=$TEST_BASE_DIR/kstat-state-realdisk.gz
+log_must [ ! -e $BACKUP ]
+gzip -c $REALDISK > $BACKUP
+
+# Yank out the disk from under the pool
+log_must rm $REALDISK
+remove_disk $SDISK
+
+# Run a 'zpool scrub' in the background to suspend the pool. We run it in the
+# background since the command will hang when the pool gets suspended. The
+# command will resume and exit after we restore the missing disk later on.
+zpool scrub $TESTPOOL2 &
+sleep 3 # Give the scrub some time to run before we check if it fails
+
+log_must check_all $TESTPOOL2 "SUSPENDED"
+
+log_pass "/proc/spl/kstat/zfs/<pool>/state test successful"
diff --git a/tests/zfs-tests/tests/functional/procfs/procfs_list_basic.ksh b/tests/zfs-tests/tests/functional/procfs/procfs_list_basic.ksh
new file mode 100755
index 000000000000..88911aac6e8e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/procfs/procfs_list_basic.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 (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Test that we can read from and write to a file in procfs whose contents is
+# backed by a linked list.
+#
+# STRATEGY:
+# 1. Take some snapshots of a filesystem, which will cause some messages to be
+# written to the zfs dbgmsgs.
+# 2. Read the dbgmsgs via procfs and verify that the expected messages are
+# present.
+# 3. Write to the dbgmsgs file to clear the messages.
+# 4. Read the dbgmsgs again, and make sure the messages are no longer present.
+#
+
+function cleanup
+{
+ datasetexists $FS && log_must zfs destroy -r $FS
+}
+
+function count_snap_cmds
+{
+ typeset expected_count=$1
+ count=$(grep -E "command: (lt-)?zfs snapshot $FS@testsnapshot" | wc -l)
+ log_must eval "[[ $count -eq $expected_count ]]"
+}
+
+typeset -r ZFS_DBGMSG=/proc/spl/kstat/zfs/dbgmsg
+typeset -r FS=$TESTPOOL/fs
+typeset snap_msgs
+
+log_onexit cleanup
+
+# Clear out old messages
+echo 0 >$ZFS_DBGMSG || log_fail "failed to write to $ZFS_DBGMSG"
+
+log_must zfs create $FS
+for i in {1..20}; do
+ log_must zfs snapshot "$FS@testsnapshot$i"
+done
+log_must zpool sync $TESTPOOL
+
+#
+# Read the debug message file in small chunks to make sure that the read is
+# split up into multiple syscalls. This tests that when a syscall begins we
+# correctly pick up in the list of messages where the previous syscall left
+# off. The size of the read can affect how many bytes the seq_file code has
+# left in its internal buffer, which in turn can affect the relative pos that
+# the seq_file code picks up at when the next read starts. Try a few
+# different size reads to make sure we can handle each case.
+#
+# Check that the file has the right contents by grepping for some of the
+# messages that we expect to be present.
+#
+for chunk_sz in {1,64,256,1024,4096}; do
+ dd if=$ZFS_DBGMSG bs=$chunk_sz | count_snap_cmds 20
+done
+
+# Clear out old messages and check that they really are gone
+echo 0 >$ZFS_DBGMSG || log_fail "failed to write to $ZFS_DBGMSG"
+cat $ZFS_DBGMSG | count_snap_cmds 0
+#
+# Even though we don't expect any messages in the file, reading should still
+# succeed.
+#
+log_must cat $ZFS_DBGMSG
+
+log_pass "Basic reading/writing of procfs file backed by linked list successful"
diff --git a/tests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.ksh b/tests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.ksh
new file mode 100755
index 000000000000..6ca7fd7d6f42
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/procfs/procfs_list_concurrent_readers.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 (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Make sure that interleaving reads from different readers does not affect the
+# results that are returned.
+#
+# STRATEGY:
+# 1. Make sure a few debug messages have been logged.
+# 2. Open the procfs file and start reading from it.
+# 3. Open the file again, and read its entire contents.
+# 4. Resume reading from the first instance.
+# 5. Check that the contents read by the two instances are identical.
+#
+
+function cleanup
+{
+ [[ -z $msgs1 ]] || log_must rm $msgs1
+ [[ -z $msgs2 ]] || log_must rm $msgs2
+ datasetexists $FS && log_must zfs destroy -r $FS
+}
+
+typeset -r ZFS_DBGMSG=/proc/spl/kstat/zfs/dbgmsg
+typeset -r FS=$TESTPOOL/fs
+typeset msgs1 msgs2
+
+log_onexit cleanup
+
+# Clear out old messages
+echo 0 >$ZFS_DBGMSG || log_fail "failed to write to $ZFS_DBGMSG"
+
+# Add some new messages
+log_must zfs create $FS
+for i in {1..20}; do
+ log_must zfs snapshot "$FS@testsnapshot$i"
+done
+log_must zpool sync $TESTPOOL
+
+msgs1=$(mktemp) || log_fail
+msgs2=$(mktemp) || log_fail
+
+#
+# Start reading file, pause and read it from another process, and then finish
+# reading.
+#
+{ dd bs=512 count=4; cat $ZFS_DBGMSG >$msgs1; cat; } <$ZFS_DBGMSG >$msgs2
+
+#
+# Truncate the result of the read that completed second in case it picked up an
+# extra message that was logged after the first read completed.
+#
+log_must truncate -s $(stat_size $msgs1) $msgs2
+
+log_must diff $msgs1 $msgs2
+
+log_pass "Concurrent readers receive identical results"
diff --git a/tests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.ksh b/tests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.ksh
new file mode 100755
index 000000000000..95a5e5c1ebc6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/procfs/procfs_list_stale_read.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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Make sure errors caused by messages being dropped from the list backing the
+# procfs file are handled gracefully.
+#
+# STRATEGY:
+# 1. Make sure a few entries have been logged.
+# 2. Open the procfs file and start reading from it.
+# 3. Write to the file to cause its contents to be dropped.
+# 4. Resume reading from the first instance, and check that the expected
+# error is received.
+# 5. Repeat steps 1-4, except instead of dropping all the messages by writing
+# to the file, cause enough new messages to be written that the old messages
+# are dropped.
+#
+
+function cleanup
+{
+ echo $default_max_entries >$MAX_ENTRIES_PARAM || log_fail
+}
+
+function sync_n
+{
+ for i in {1..$1}; do
+ log_must zpool sync $TESTPOOL
+ done
+ return 0
+}
+
+function do_test
+{
+ typeset cmd=$1
+
+ # Clear out old entries
+ echo 0 >$TXG_HIST || log_fail
+
+ # Add some new entries
+ sync_n 20
+
+ # Confirm that there actually is something in the file.
+ [[ $(wc -l <$TXG_HIST) -ge 20 ]] || log_fail "expected more entries"
+
+ #
+ # Start reading file, pause and run a command that will cause the
+ # current offset into the file to become invalid, and then try to
+ # finish reading.
+ #
+ {
+ log_must dd bs=512 count=4 >/dev/null
+ log_must eval "$cmd"
+ cat 2>&1 >/dev/null | log_must grep "Input/output error"
+ } <$TXG_HIST
+}
+
+typeset -r TXG_HIST=/proc/spl/kstat/zfs/$TESTPOOL/txgs
+typeset MAX_ENTRIES_PARAM=/sys/module/zfs/parameters/zfs_txg_history
+typeset default_max_entries
+
+log_onexit cleanup
+
+default_max_entries=$(<$MAX_ENTRIES_PARAM) || log_fail
+echo 50 >$MAX_ENTRIES_PARAM || log_fail
+
+# Clear all of the existing entries.
+do_test "echo 0 >$TXG_HIST"
+
+# Add enough new entries to the list that all of the old ones are dropped.
+do_test "sync_n 60"
+
+log_pass "Attempting to read dropped message returns expected error"
diff --git a/tests/zfs-tests/tests/functional/procfs/setup.ksh b/tests/zfs-tests/tests/functional/procfs/setup.ksh
new file mode 100755
index 000000000000..79fa28f4f1ac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/procfs/setup.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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_mirror_setup $DISKS
diff --git a/tests/zfs-tests/tests/functional/projectquota/Makefile.am b/tests/zfs-tests/tests/functional/projectquota/Makefile.am
new file mode 100644
index 000000000000..e98c8672802e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/Makefile.am
@@ -0,0 +1,27 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/projectquota
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ projectid_001_pos.ksh \
+ projectid_002_pos.ksh \
+ projectid_003_pos.ksh \
+ projectquota_001_pos.ksh \
+ projectquota_002_pos.ksh \
+ projectquota_003_pos.ksh \
+ projectquota_004_neg.ksh \
+ projectquota_005_pos.ksh \
+ projectquota_006_pos.ksh \
+ projectquota_007_pos.ksh \
+ projectquota_008_pos.ksh \
+ projectquota_009_pos.ksh \
+ projectspace_001_pos.ksh \
+ projectspace_002_pos.ksh \
+ projectspace_003_pos.ksh \
+ projectspace_004_pos.ksh \
+ projecttree_001_pos.ksh \
+ projecttree_002_pos.ksh \
+ projecttree_003_neg.ksh
+
+dist_pkgdata_DATA = \
+ projectquota.cfg \
+ projectquota_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/projectquota/cleanup.ksh b/tests/zfs-tests/tests/functional/projectquota/cleanup.ksh
new file mode 100755
index 000000000000..0440e3d8af8c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+log_must cleanup_projectquota
+log_must del_user $PUSER
+log_must del_group $PGROUP
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectid_001_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectid_001_pos.ksh
new file mode 100755
index 000000000000..46e79062a0e2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectid_001_pos.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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check project ID/flags can be set/inherited properly
+#
+#
+# STRATEGY:
+# 1. Create a regular file and a directory.
+# 2. Set project ID on both directory and regular file.
+# 3. New created subdir or regular file should inherit its parent's
+# project ID if its parent has project inherit flag.
+# 4. New created subdir should inherit its parent project's inherit flag.
+#
+
+function cleanup
+{
+ log_must rm -f $PRJFILE
+ log_must rm -rf $PRJDIR
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+#
+# e2fsprogs-1.44.4 incorrectly reports verity 'V' bit when the project 'P'
+# bit is set. Skip this test when 1.44.4 is installed to prevent failures.
+#
+# https://github.com/tytso/e2fsprogs/commit/7e5a95e3d
+#
+if lsattr -V 2>&1 | grep "lsattr 1.44.4"; then
+ log_unsupported "Current e2fsprogs incorrectly reports 'V' verity bit"
+fi
+
+log_onexit cleanup
+
+log_assert "Check project ID/flags can be set/inherited properly"
+
+log_must touch $PRJFILE
+log_must mkdir $PRJDIR
+
+log_must chattr -p $PRJID1 $PRJFILE
+log_must eval "lsattr -p $PRJFILE | grep $PRJID1 | grep -v '\-P[- ]* '"
+log_must chattr -p $PRJID1 $PRJDIR
+log_must eval "lsattr -pd $PRJDIR | grep $PRJID1 | grep -v '\-P[- ]* '"
+
+log_must chattr +P $PRJDIR
+log_must eval "lsattr -pd $PRJDIR | grep $PRJID1 | grep '\-P[- ]* '"
+
+# "-1" is invalid project ID, should be denied
+log_mustnot chattr -p -1 $PRJFILE
+log_must eval "lsattr -p $PRJFILE | grep $PRJID1 | grep -v '\-P[- ]* '"
+
+log_must mkdir $PRJDIR/dchild
+log_must eval "lsattr -pd $PRJDIR/dchild | grep $PRJID1 | grep '\-P[- ]* '"
+log_must touch $PRJDIR/fchild
+log_must eval "lsattr -p $PRJDIR/fchild | grep $PRJID1"
+
+log_must touch $PRJDIR/dchild/foo
+log_must eval "lsattr -p $PRJDIR/dchild/foo | grep $PRJID1"
+
+# not support project ID/flag on symlink
+log_must ln -s $PRJDIR/dchild/foo $PRJDIR/dchild/s_foo
+log_mustnot lsattr -p $PRJDIR/dchild/s_foo
+log_mustnot chattr -p 123 $PRJDIR/dchild/s_foo
+log_mustnot chattr +P $PRJDIR/dchild/s_foo
+
+# not support project ID/flag on block special file
+log_must mknod $PRJDIR/dchild/b_foo b 124 124
+log_mustnot lsattr -p $PRJDIR/dchild/b_foo
+log_mustnot chattr -p 123 $PRJDIR/dchild/b_foo
+log_mustnot chattr +P $PRJDIR/dchild/b_foo
+
+# not support project ID/flag on character special file
+log_must mknod $PRJDIR/dchild/c_foo c 125 125
+log_mustnot lsattr -p $PRJDIR/dchild/c_foo
+log_mustnot chattr -p 123 $PRJDIR/dchild/c_foo
+log_mustnot chattr +P $PRJDIR/dchild/c_foo
+
+log_pass "Check project ID/flags can be set/inherited properly"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectid_002_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectid_002_pos.ksh
new file mode 100755
index 000000000000..e382f464046b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectid_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Project ID affects POSIX behavior
+#
+#
+# STRATEGY:
+# 1. Create three directories
+# 2. Set tdir1 and tdir3 project ID as PRJID1,
+# set tdir2 project ID as PRJID2.
+# 3. Create regular file under tdir1. It inherits tdir1 project ID.
+# 4. Hardlink from tdir1's child to tdir2 should be denied,
+# move tdir1's child to tdir2 will be object recreated.
+# 5. Hardlink from tdir1's child to tdir3 should succeed.
+#
+
+function cleanup
+{
+ log_must rm -rf $PRJDIR1
+ log_must rm -rf $PRJDIR2
+ log_must rm -rf $PRJDIR3
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "Project ID affects POSIX behavior"
+
+log_must mkdir $PRJDIR1
+log_must mkdir $PRJDIR2
+log_must mkdir $PRJDIR3
+log_must mkdir $PRJDIR3/dir
+
+log_must chattr +P -p $PRJID1 $PRJDIR1
+log_must chattr +P -p $PRJID2 $PRJDIR2
+
+log_must touch $PRJDIR1/tfile1
+log_must touch $PRJDIR1/tfile2
+log_must eval "lsattr -p $PRJDIR1/tfile1 | grep $PRJID1"
+
+log_mustnot ln $PRJDIR1/tfile1 $PRJDIR2/tfile2
+
+log_must mv $PRJDIR1/tfile1 $PRJDIR2/tfile2
+log_must eval "lsattr -p $PRJDIR2/tfile2 | grep $PRJID2"
+
+log_must mv $PRJDIR3/dir $PRJDIR2/
+log_must eval "lsattr -dp $PRJDIR2/dir | grep $PRJID2"
+
+log_must chattr +P -p $PRJID1 $PRJDIR3
+log_must ln $PRJDIR1/tfile2 $PRJDIR3/tfile3
+
+log_pass "Project ID affects POSIX behavior"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectid_003_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectid_003_pos.ksh
new file mode 100755
index 000000000000..d6dbaafc217a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectid_003_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) 2017 by Fan Yong. Fan rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check changing project ID for the file with directory-based
+# extended attributes.
+#
+#
+# STRATEGY:
+# 1. create new file with default project ID
+# 2. set non-ACL extended attributes on the file
+# 3. use zfs projectspace to check the object usage
+# 4. change the file's project ID
+# 5. use zfs projectspace to check the object usage again
+#
+
+function cleanup
+{
+ log_must rm -f $PRJGUARD
+ log_must rm -f $PRJFILE
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "Check changing project ID with directory-based extended attributes"
+
+log_must zfs set xattr=on $QFS
+
+log_must touch $PRJGUARD
+log_must chattr -p $PRJID1 $PRJGUARD
+log_must touch $PRJFILE
+log_must setfattr -n trusted.ea1 -v val1 $PRJFILE
+log_must setfattr -n trusted.ea2 -v val2 $PRJFILE
+log_must setfattr -n trusted.ea3 -v val3 $PRJFILE
+
+sync_pool
+typeset prj_bef=$(project_obj_count $QFS $PRJID1)
+
+log_must chattr -p $PRJID1 $PRJFILE
+sync_pool
+typeset prj_aft=$(project_obj_count $QFS $PRJID1)
+
+[[ $prj_aft -ge $((prj_bef + 5)) ]] ||
+ log_fail "new value ($prj_aft) is NOT 5 largr than old one ($prj_bef)"
+
+log_pass "Changing project ID with directory-based extended attributes pass"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota.cfg b/tests/zfs-tests/tests/functional/projectquota/projectquota.cfg
new file mode 100644
index 000000000000..564ab3ef9698
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota.cfg
@@ -0,0 +1,46 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 Fan Yong. All rights reserved.
+#
+
+export PUSER=puser
+export PGROUP=pgroup
+
+export PRJID1=1001
+export PRJID2=1002
+
+export QFS=$TESTPOOL/$TESTFS
+export PRJFILE=$TESTDIR/tfile
+export PRJGUARD=$TESTDIR/guard
+export PRJDIR=$TESTDIR/tdir
+export PRJDIR1=$TESTDIR/tdir1
+export PRJDIR2=$TESTDIR/tdir2
+export PRJDIR3=$TESTDIR/tdir3
+
+export PQUOTA_LIMIT=1000000
+export PQUOTA_OBJLIMIT=1000
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_001_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_001_pos.ksh
new file mode 100755
index 000000000000..3f8c3d68ce3e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_001_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check the basic function of the project{obj}quota
+#
+#
+# STRATEGY:
+# 1. Set projectquota and overwrite the quota size.
+# 2. The write operation should fail with Disc quota exceeded
+# 3. Set projectobjquota and overcreate the quota size.
+# 4. More create should fail with Disc quota exceeded
+# 5. More chattr to such project should fail with Disc quota exceeded
+#
+
+function cleanup
+{
+ cleanup_projectquota
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "If operation overwrite project{obj}quota size, it will fail"
+
+mkmount_writable $QFS
+
+log_note "Check the projectquota@$PRJID1"
+log_must user_run $PUSER mkdir $PRJDIR
+log_must chattr +P -p $PRJID1 $PRJDIR
+
+log_must zfs set projectquota@$PRJID1=$PQUOTA_LIMIT $QFS
+log_must user_run $PUSER mkfile $PQUOTA_LIMIT $PRJDIR/qf
+sync_pool
+log_mustnot user_run $PUSER mkfile 1 $PRJDIR/of
+
+log_must rm -rf $PRJDIR
+
+log_note "Check the projectobjquota@$PRJID2"
+log_must zfs set xattr=sa $QFS
+log_must user_run $PUSER mkdir $PRJDIR
+log_must chattr +P -p $PRJID2 $PRJDIR
+
+log_must zfs set projectobjquota@$PRJID2=$PQUOTA_OBJLIMIT $QFS
+log_must user_run $PUSER mkfiles $PRJDIR/qf_ $((PQUOTA_OBJLIMIT - 1))
+sync_pool
+log_mustnot user_run $PUSER mkfile 1 $PRJDIR/of
+
+log_must user_run $PUSER touch $PRJFILE
+log_must user_run $PUSER chattr -p 123 $PRJFILE
+log_mustnot user_run $PUSER chattr -p $PRJID2 $PRJFILE
+
+log_pass "Operation overwrite project{obj}quota size failed as expect"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_002_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_002_pos.ksh
new file mode 100755
index 000000000000..66cd1fb9ef71
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_002_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) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# The project{obj}quota can be set during zpool or zfs creation
+#
+#
+# STRATEGY:
+# 1. Set project{obj}quota via "zpool -O or zfs create -o"
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if poolexists $TESTPOOL1; then
+ log_must zpool destroy $TESTPOOL1
+ fi
+
+ if [[ -f $pool_vdev ]]; then
+ rm -f $pool_vdev
+ fi
+}
+
+log_onexit cleanup
+
+log_assert "The project{obj}quota can be set during zpool,zfs creation"
+
+typeset pool_vdev=$TEST_BASE_DIR/pool_dev.$$
+
+log_must mkfile 500m $pool_vdev
+
+if poolexists $TESTPOOL1; then
+ zpool destroy $TESTPOOL1
+fi
+
+log_must zpool create -O projectquota@$PRJID1=$PQUOTA_LIMIT \
+ -O projectobjquota@$PRJID2=$PQUOTA_OBJLIMIT $TESTPOOL1 $pool_vdev
+
+log_must eval "zfs list -r -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL1 > /dev/null 2>&1"
+
+log_must check_quota "projectquota@$PRJID1" $TESTPOOL1 "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $TESTPOOL1 "$PQUOTA_OBJLIMIT"
+
+log_must zfs create -o projectquota@$PRJID1=$PQUOTA_LIMIT \
+ -o projectobjquota@$PRJID2=$PQUOTA_OBJLIMIT $TESTPOOL1/fs
+
+log_must eval "zfs list -r -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL1 > /dev/null 2>&1"
+
+log_must check_quota "projectquota@$PRJID1" $TESTPOOL1/fs "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $TESTPOOL1/fs "$PQUOTA_OBJLIMIT"
+
+log_pass "The project{obj}quota can be set during zpool,zfs creation"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_003_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_003_pos.ksh
new file mode 100755
index 000000000000..06f360d30b2b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_003_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) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the basic function project{obj}used
+#
+#
+# STRATEGY:
+# 1. Write data to fs with some project then check the project{obj}used
+#
+
+function cleanup
+{
+ cleanup_projectquota
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "Check the basic function of project{obj}used"
+
+sync_pool
+typeset project_used=$(get_value "projectused@$PRJID1" $QFS)
+typeset file_size='10m'
+
+if [[ $project_used != 0 ]]; then
+ log_fail "FAIL: projectused is $project_used, should be 0"
+fi
+
+mkmount_writable $QFS
+log_must user_run $PUSER mkdir $PRJDIR
+log_must chattr +P -p $PRJID1 $PRJDIR
+log_must user_run $PUSER mkfile $file_size $PRJDIR/qf
+sync_pool
+project_used=$(get_value "projectused@$PRJID1" $QFS)
+# get_value() reads the exact byte value which is slightly more than 10m
+if [[ "$(($project_used/1024/1024))m" != "$file_size" ]]; then
+ log_note "project $PRJID1 used is $project_used"
+ log_fail "projectused for project $PRJID1 expected to be $file_size, " \
+ "not $project_used"
+fi
+
+log_must rm -rf $PRJDIR
+typeset project_obj_used=$(get_value "projectobjused@$PRJID2" $QFS)
+typeset file_count=100
+
+if [[ $project_obj_used != 0 ]]; then
+ log_fail "FAIL: projectobjused is $project_obj_used, should be 0"
+fi
+
+log_must zfs set xattr=sa $QFS
+log_must user_run $PUSER mkdir $PRJDIR
+log_must chattr +P -p $PRJID2 $PRJDIR
+# $PRJDIR has already used one object with the $PRJID2
+log_must user_run $PUSER mkfiles $PRJDIR/qf_ $((file_count - 1))
+sync_pool
+project_obj_used=$(get_value "projectobjused@$PRJID2" $QFS)
+if [[ $project_obj_used != $file_count ]]; then
+ log_note "project $PRJID2 used is $project_obj_used"
+ log_fail "projectobjused for project $PRJID2 expected to be " \
+ "$file_count, not $project_obj_used"
+fi
+
+log_pass "Check the basic function of project{obj}used pass as expect"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_004_neg.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_004_neg.ksh
new file mode 100755
index 000000000000..a975d2a19f0c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_004_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) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the invalid parameter of zfs set project{obj}quota
+#
+#
+# STRATEGY:
+# 1. check the invalid zfs set project{obj}quota to fs
+# 2. check the valid zfs set project{obj}quota to snapshots
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_projectquota
+}
+
+log_onexit cleanup
+
+log_assert "Check the invalid parameter of zfs set project{obj}quota"
+typeset snap_fs=$QFS@snap
+
+log_must zfs snapshot $snap_fs
+
+set -A no_prjs "mms1234" "ss@#" "root-122" "-1"
+for prj in "${no_prjs[@]}"; do
+ log_mustnot zfs set projectquota@$prj=100m $QFS
+done
+
+log_note "can set all numeric id even if that id does not exist"
+log_must zfs set projectquota@12345678=100m $QFS
+
+set -A sizes "100mfsd" "m0.12m" "GGM" "-1234-m" "123m-m"
+for size in "${sizes[@]}"; do
+ log_note "can not set projectquota with invalid size parameter"
+ log_mustnot zfs set projectquota@$PRJID1=$size $QFS
+done
+
+log_note "can not set projectquota to snapshot $snap_fs"
+log_mustnot zfs set projectquota@$PRJID1=100m $snap_fs
+
+for prj in "${no_prjs[@]}"; do
+ log_mustnot zfs set projectobjquota@$prj=100 $QFS
+done
+
+log_note "can not set projectobjquota with invalid size parameter"
+log_mustnot zfs set projectobjquota@$PRJID2=100msfsd $QFS
+
+log_note "can not set projectobjquota to snapshot $snap_fs"
+log_mustnot zfs set projectobjquota@$PRJID2=100m $snap_fs
+
+log_pass "Check the invalid parameter of zfs set project{obj}quota"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_005_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_005_pos.ksh
new file mode 100755
index 000000000000..b52f302f7892
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_005_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) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the invalid parameter of zfs get project{obj}quota
+#
+#
+# STRATEGY:
+# 1. check the invalid zfs get project{obj}quota to fs
+# 2. check the valid zfs get project{obj}quota to snapshots
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_projectquota
+}
+
+log_onexit cleanup
+
+log_assert "Check the invalid parameter of zfs get project{obj}quota"
+typeset snap_fs=$QFS@snap
+
+log_must zfs snapshot $snap_fs
+
+set -A no_prjs "mms1234" "ss@#" "root-122"
+for prj in "${no_prjs[@]}"; do
+ log_must eval "zfs get projectquota@$prj $QFS >/dev/null 2>&1"
+ log_must eval "zfs get projectquota@$prj $snap_fs >/dev/null 2>&1"
+ log_must eval "zfs get projectobjquota@$prj $QFS >/dev/null 2>&1"
+ log_must eval "zfs get projectobjquota@$prj $snap_fs >/dev/null 2>&1"
+done
+
+log_pass "Check the invalid parameter of zfs get project{obj}quota"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.ksh
new file mode 100755
index 000000000000..6b375d407e23
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_006_pos.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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Projectquota can be set beyond the fs quota.
+# Pprojectquota can be set at a smaller size than its current usage.
+#
+# STRATEGY:
+# 1. set quota to a fs and set a larger size of projectquota
+# 2. write some data to the fs and set a smaller projectquota
+#
+
+function cleanup
+{
+ log_must cleanup_projectquota
+ log_must zfs set quota=none $QFS
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "Check set projectquota to larger than the quota size of a fs"
+
+log_must zfs set quota=200m $QFS
+log_must zfs set projectquota@$PRJID1=500m $QFS
+
+log_must zfs get projectquota@$PRJID1 $QFS
+
+log_note "write some data to the $QFS"
+mkmount_writable $QFS
+log_must user_run $PUSER mkdir $PRJDIR
+log_must chattr +P -p $PRJID1 $PRJDIR
+log_must user_run $PUSER mkfile 100m $PRJDIR/qf
+sync
+
+log_note "set projectquota at a smaller size than it current usage"
+log_must zfs set projectquota@$PRJID1=90m $QFS
+
+log_must zfs get projectquota@$PRJID1 $QFS
+
+log_pass "set projectquota to larger than quota size of a fs"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.ksh
new file mode 100755
index 000000000000..3572e0118f45
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_007_pos.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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# zfs get all <fs> does not print out project{obj}quota
+#
+# STRATEGY:
+# 1. set project{obj}quota to a fs
+# 2. check zfs get all fs
+#
+
+function cleanup
+{
+ log_must cleanup_projectquota
+}
+
+log_onexit cleanup
+
+log_assert "Check zfs get all will not print out project{obj}quota"
+
+log_must zfs set projectquota@$PRJID1=50m $QFS
+log_must zfs set projectobjquota@$PRJID2=100 $QFS
+
+log_mustnot eval "zfs get all $QFS | grep projectquota"
+log_mustnot eval "zfs get all $QFS | grep projectobjquota"
+
+log_pass "zfs get all will not print out project{obj}quota"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_008_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_008_pos.ksh
new file mode 100755
index 000000000000..365b5627e801
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check project{obj}quota to snapshot that:
+# 1) can not set project{obj}quota to snapshot directly
+# 2) snapshot can inherit the parent fs's project{obj}quota
+# 3) the project{obj}quota will not change even the parent quota changed.
+#
+#
+# STRATEGY:
+# 1. create a snapshot of a fs
+# 2. set the project{obj}quota to snapshot and expect fail
+# 3. set project{obj}quota to fs and check the snapshot
+# 4. re-set project{obj}quota to fs and check the snapshot's value
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_projectquota
+}
+
+log_onexit cleanup
+
+log_assert "Check the snapshot's project{obj}quota"
+typeset snap_fs=$QFS@snap
+
+
+log_must zfs set projectquota@$PRJID1=$PQUOTA_LIMIT $QFS
+log_must check_quota "projectquota@$PRJID1" $QFS "$PQUOTA_LIMIT"
+
+log_must zfs set projectobjquota@$PRJID2=$PQUOTA_OBJLIMIT $QFS
+log_must check_quota "projectobjquota@$PRJID2" $QFS "$PQUOTA_OBJLIMIT"
+
+log_must zfs snapshot $snap_fs
+
+log_note "check the snapshot $snap_fs project{obj}quota"
+log_must check_quota "projectquota@$PRJID1" $snap_fs "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $snap_fs "$PQUOTA_OBJLIMIT"
+
+log_note "set project{obj}quota to $snap_fs which will fail"
+log_mustnot zfs set projectquota@$PRJID1=100m $snap_fs
+log_mustnot zfs set projectobjquota@$PRJID2=100 $snap_fs
+
+log_note "change the parent's project{obj}quota"
+log_must zfs set projectquota@$PRJID1=$((PQUOTA_LIMIT * 2)) $QFS
+log_must zfs set projectobjquota@$PRJID2=50 $QFS
+
+log_must check_quota "projectquota@$PRJID1" $QFS $((PQUOTA_LIMIT * 2))
+log_must check_quota "projectobjquota@$PRJID2" $QFS 50
+
+log_note "check the snapshot $snap_fs project{obj}quota"
+log_must check_quota "projectquota@$PRJID1" $snap_fs "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $snap_fs "$PQUOTA_OBJLIMIT"
+
+log_pass "Check the snapshot's project{obj}quota"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.ksh
new file mode 100755
index 000000000000..a867b538c120
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_009_pos.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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# The project{obj}quota will not change during zfs actions, such as
+# snapshot,clone,rename,upgrade,send,receive.
+#
+#
+# STRATEGY:
+# 1. Create a pool, and create fs with preset project{obj}quota
+# 2. Check set project{obj}quota via zfs snapshot|clone|list -o
+# 3. Check the project{obj}quota can not change during zfs
+# rename|upgrade|promote
+# 4. Check the project{obj}quota can not change during zfs clone
+# 5. Check the project{obj}quota can not change during zfs send/receive
+#
+
+function cleanup
+{
+ for ds in $TESTPOOL/fs $TESTPOOL/fs-rename $TESTPOOL/fs-clone; do
+ if datasetexists $ds; then
+ log_must zfs destroy -rRf $ds
+ fi
+ done
+}
+
+log_onexit cleanup
+
+log_assert "the project{obj}quota can't change during zfs actions"
+
+cleanup
+
+log_must zfs create -o projectquota@$PRJID1=$PQUOTA_LIMIT \
+ -o projectobjquota@$PRJID2=$PQUOTA_OBJLIMIT $TESTPOOL/fs
+
+log_must zfs snapshot $TESTPOOL/fs@snap
+log_must eval "zfs list -r -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "projectquota@$PRJID1" $TESTPOOL/fs@snap "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $TESTPOOL/fs@snap \
+ "$PQUOTA_OBJLIMIT"
+
+
+log_note "clone fs gets its parent's project{obj}quota initially"
+log_must zfs clone -o projectquota@$PRJID1=$PQUOTA_LIMIT \
+ -o projectobjquota@$PRJID2=$PQUOTA_OBJLIMIT \
+ $TESTPOOL/fs@snap $TESTPOOL/fs-clone
+
+log_must eval "zfs list -r -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "projectquota@$PRJID1" $TESTPOOL/fs-clone "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $TESTPOOL/fs-clone \
+ "$PQUOTA_OBJLIMIT"
+
+log_must eval "zfs list -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL/fs-clone >/dev/null 2>&1"
+
+log_note "zfs promote can not change the previously set project{obj}quota"
+log_must zfs promote $TESTPOOL/fs-clone
+
+log_must eval "zfs list -r -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "projectquota@$PRJID1" $TESTPOOL/fs-clone "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $TESTPOOL/fs-clone \
+ "$PQUOTA_OBJLIMIT"
+
+log_note "zfs send receive can not change the previously set project{obj}quota"
+log_must zfs send $TESTPOOL/fs-clone@snap | zfs receive $TESTPOOL/fs-rev
+
+log_must eval "zfs list -r -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "projectquota@$PRJID1" $TESTPOOL/fs-rev "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $TESTPOOL/fs-rev \
+ "$PQUOTA_OBJLIMIT"
+
+log_note "zfs rename can not change the previously set project{obj}quota"
+log_must zfs rename $TESTPOOL/fs-rev $TESTPOOL/fs-rename
+
+log_must eval "zfs list -r -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "projectquota@$PRJID1" $TESTPOOL/fs-rename "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $TESTPOOL/fs-rename \
+ "$PQUOTA_OBJLIMIT"
+
+log_note "zfs upgrade can not change the previously set project{obj}quota"
+log_must zfs upgrade $TESTPOOL/fs-rename
+
+log_must eval "zfs list -r -o projectquota@$PRJID1,projectobjquota@$PRJID2 \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "projectquota@$PRJID1" $TESTPOOL/fs-rename "$PQUOTA_LIMIT"
+log_must check_quota "projectobjquota@$PRJID2" $TESTPOOL/fs-rename \
+ "$PQUOTA_OBJLIMIT"
+
+log_pass "the project{obj}quota can't change during zfs actions"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib b/tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib
new file mode 100644
index 000000000000..23f7c2a50663
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectquota_common.kshlib
@@ -0,0 +1,101 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/projectquota/projectquota.cfg
+
+#
+# reset the projectquota and delete temporary files
+#
+function cleanup_projectquota
+{
+ if datasetexists $QFS; then
+ typeset mntp=$(get_prop mountpoint $QFS)
+
+ log_must zfs set projectquota@$PRJID1=none $QFS
+ log_must zfs set projectobjquota@$PRJID1=none $QFS
+ log_must zfs set projectquota@$PRJID2=none $QFS
+ log_must zfs set projectobjquota@$PRJID2=none $QFS
+ log_must chmod 0755 $mntp
+ fi
+
+ [[ -f $PRJFILE ]] && log_must rm -f $PRJFILE
+ [[ -d $PRJDIR ]] && log_must rm -rf $PRJDIR
+ [[ -d $PRJDIR1 ]] && log_must rm -rf $PRJDIR1
+ [[ -d $PRJDIR2 ]] && log_must rm -rf $PRJDIR2
+ [[ -d $PRJDIR3 ]] && log_must rm -rf $PRJDIR3
+ sync
+
+ return 0
+}
+
+function mkmount_writable
+{
+ typeset fs=$1
+ typeset mntp=$(get_prop mountpoint $fs)
+ log_must chmod 0777 $mntp
+}
+
+function check_quota
+{
+ typeset fs=$2
+ typeset prop=$1
+ typeset expected=$3
+ typeset value=$(get_prop $prop $fs)
+
+ if (($value != $expected)); then
+ return 1
+ fi
+}
+
+function get_value
+{
+ typeset prop_val
+ typeset prop=$1
+ typeset dataset=$2
+
+ prop_val=$(zfs get -H -p -o value $prop $dataset 2>/dev/null)
+ if [[ $? -ne 0 ]]; then
+ log_note "Unable to get $prop property for dataset $dataset"
+ return 1
+ fi
+
+ echo $prop_val
+}
+
+function project_obj_count
+{
+ typeset fs=$1
+ typeset prj=$2
+ typeset cnt=$(zfs projectspace -oname,objused $fs |
+ awk /$prj/'{print $2}')
+ [[ "$cnt" == "-" ]] && cnt=0 || true
+ echo $cnt
+}
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectspace_001_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectspace_001_pos.ksh
new file mode 100755
index 000000000000..a84ff9f89a0d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectspace_001_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) 2017 by Fan Yong. Fan rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the zfs projectspace with kinds of parameters
+#
+#
+# STRATEGY:
+# 1. set zfs projectspace to a fs
+# 2. write some data to the fs with specified project ID
+# 3. use zfs projectspace with all possible parameters to check the result
+# 4. use zfs projectspace with some bad parameters to check the result
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_projectquota
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "Check the zfs projectspace with all possible parameters"
+
+set -A good_params -- "-H" "-p" "-o type,name,used,quota" "-o name,used,quota" \
+ "-o used,quota" "-o objused" "-o quota" "-s type" "-s name" "-s used" \
+ "-s quota" "-S type" "-S name" "-S used" "-S quota"
+
+typeset snap_fs=$QFS@snap
+
+log_must zfs set projectquota@$PRJID1=100m $QFS
+log_must zfs set projectobjquota@$PRJID1=100 $QFS
+mkmount_writable $QFS
+log_must user_run $PUSER mkdir $PRJDIR
+log_must chattr +P -p $PRJID1 $PRJDIR
+log_must user_run $PUSER mkfile 50m $PRJDIR/qf
+sync
+
+log_must zfs snapshot $snap_fs
+
+for param in "${good_params[@]}"; do
+ log_must eval "zfs projectspace $param $QFS >/dev/null 2>&1"
+ log_must eval "zfs projectspace $param $snap_fs >/dev/null 2>&1"
+done
+
+log_assert "Check the zfs projectspace with some bad parameters"
+
+set -A bad_params -- "-i" "-n" "-P" "-t posixuser"
+
+for param in "${bad_params[@]}"; do
+ log_mustnot eval "zfs projectspace $param $QFS >/dev/null 2>&1"
+ log_mustnot eval "zfs projectspace $param $snap_fs >/dev/null 2>&1"
+done
+
+log_pass "zfs projectspace with kinds of parameters pass"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectspace_002_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectspace_002_pos.ksh
new file mode 100755
index 000000000000..216855e94dc9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectspace_002_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) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the project used size and quota in zfs projectspace
+#
+#
+# STRATEGY:
+# 1. set zfs projectquota to a fs
+# 2. write some data to the fs with specified project and size
+# 3. use zfs projectspace to check the used size and quota size
+#
+
+function cleanup
+{
+ if datasetexists $snapfs; then
+ log_must zfs destroy $snapfs
+ fi
+
+ log_must cleanup_projectquota
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "Check the zfs projectspace used and quota"
+
+log_must zfs set projectquota@$PRJID1=100m $QFS
+
+mkmount_writable $QFS
+log_must user_run $PUSER mkdir $PRJDIR
+log_must chattr +P -p $PRJID1 $PRJDIR
+log_must user_run $PUSER mkfile 50m $PRJDIR/qf
+sync
+
+typeset snapfs=$QFS@snap
+
+log_must zfs snapshot $snapfs
+
+log_must eval "zfs projectspace $QFS >/dev/null 2>&1"
+log_must eval "zfs projectspace $snapfs >/dev/null 2>&1"
+
+for fs in "$QFS" "$snapfs"; do
+ log_note "check the quota size in zfs projectspace $fs"
+ log_must eval "zfs projectspace $fs | grep $PRJID1 | grep 100M"
+
+ log_note "check the project used size in zfs projectspace $fs"
+ log_must eval "zfs projectspace $fs | grep $PRJID1 | grep 50\\.\*M"
+done
+
+log_pass "Check the zfs projectspace used and quota"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.ksh
new file mode 100755
index 000000000000..629b3b3e57e2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectspace_003_pos.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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the project used object accounting in zfs projectspace
+#
+#
+# STRATEGY:
+# 1. create a bunch of files by specific project
+# 2. use zfs projectspace to check the used objects
+# 3. change the project ID of test files and verify object count
+# 4. delete files and verify object count
+#
+
+function cleanup
+{
+ if datasetexists $snapfs; then
+ log_must zfs destroy $snapfs
+ fi
+
+ log_must cleanup_projectquota
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "Check the zfs projectspace object used"
+
+mkmount_writable $QFS
+log_must zfs set xattr=sa $QFS
+log_must user_run $PUSER mkdir $PRJDIR1
+log_must user_run $PUSER mkdir $PRJDIR2
+log_must chattr +P -p $PRJID1 $PRJDIR1
+log_must chattr +P -p $PRJID2 $PRJDIR2
+
+((prj_cnt1 = RANDOM % 100 + 2))
+((prj_cnt2 = RANDOM % 100 + 2))
+
+log_must user_run $PUSER mkfiles $PRJDIR1/qf $((prj_cnt1 - 1))
+log_must user_run $PUSER mkfiles $PRJDIR2/qf $((prj_cnt2 - 1))
+sync_pool
+
+typeset snapfs=$QFS@snap
+
+log_must zfs snapshot $snapfs
+
+log_must eval "zfs projectspace $QFS >/dev/null 2>&1"
+log_must eval "zfs projectspace $snapfs >/dev/null 2>&1"
+
+for fs in "$QFS" "$snapfs"; do
+ log_note "check the project used objects in zfs projectspace $fs"
+ prjused=$(project_obj_count $fs $PRJID1)
+ [[ $prjused -eq $prj_cnt1 ]] ||
+ log_fail "($PRJID1) expected $prj_cnt1, got $prjused"
+ prjused=$(project_obj_count $fs $PRJID2)
+ [[ $prjused -eq $prj_cnt2 ]] ||
+ log_fail "($PRJID2) expected $prj_cnt2, got $prjused"
+done
+
+log_note "change the project of files"
+log_must chattr -p $PRJID2 $PRJDIR1/qf*
+sync_pool
+
+prjused=$(project_obj_count $QFS $PRJID1)
+[[ $prjused -eq 1 ]] ||
+ log_fail "expected 1 for project $PRJID1, got $prjused"
+
+prjused=$(project_obj_count $snapfs $PRJID1)
+[[ $prjused -eq $prj_cnt1 ]] ||
+ log_fail "expected $prj_cnt1 for $PRJID1 in snapfs, got $prjused"
+
+prjused=$(project_obj_count $QFS $PRJID2)
+[[ $prjused -eq $((prj_cnt1 + prj_cnt2 - 1)) ]] ||
+ log_fail "($PRJID2) expected $((prj_cnt1 + prj_cnt2 - 1)), got $prjused"
+
+log_note "file removal"
+log_must rm -rf $PRJDIR1
+sync_pool
+
+prjused=$(project_obj_count $QFS $PRJID1)
+[[ $prjused -eq 0 ]] || log_fail "expected 0 for $PRJID1, got $prjused"
+
+cleanup
+log_pass "Check the zfs projectspace object used"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projectspace_004_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projectspace_004_pos.ksh
new file mode 100755
index 000000000000..ec299e0e7f93
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projectspace_004_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) 2017 by Fan Yong. Fan rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check 'df' command on the directory with INHERIT (project ID) flag
+#
+#
+# STRATEGY:
+# 1. set project [obj]quota on the directory
+# 2. set project ID and inherit flag on the directory
+# 3. run 'df [-i]' on the directory and check the result
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_projectquota
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+log_onexit cleanup
+
+log_assert "Check 'df' on dir with inherit project shows the project quota/used"
+
+log_must zfs set projectquota@$PRJID1=100m $QFS
+log_must zfs set projectobjquota@$PRJID1=100 $QFS
+mkmount_writable $QFS
+log_must user_run $PUSER mkdir $PRJDIR
+log_must chattr +P -p $PRJID1 $PRJDIR
+log_must user_run $PUSER mkfile 50m $PRJDIR/qf
+sync_pool
+
+total=$(df $PRJDIR | tail -n 1 | awk '{ print $2 }')
+[[ $total -eq 102400 ]] || log_fail "expect '102400' resource, but got '$total'"
+
+used=$(df -i $PRJDIR | tail -n 1 | awk '{ print $5 }')
+[[ "$used" == "2%" ]] || log_fail "expect '2%' used, but got '$used'"
+
+log_pass "'df' on the directory with inherit project ID flag pass as expect"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projecttree_001_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projecttree_001_pos.ksh
new file mode 100755
index 000000000000..0402e345df2a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projecttree_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check 'zfs project' is compatible with chattr/lsattr
+#
+#
+# STRATEGY:
+# Verify the following:
+# 1. "zfs project -p" behaviours the same as "chattr -p"
+# 2. "zfs project" behaviours the same as "lsattr -p"
+# 3. "zfs project -d" behaviours the same as "lsattr -p -d"
+# 4. "zfs project -s" behaviours the same as "chattr +P"
+# 5. "zfs project -s -p" behaviours the same as "chattr +P -p"
+# 6. "zfs project -C" behaviours the same as "chattr -P"
+#
+
+function cleanup
+{
+ log_must rm -rf $PRJDIR
+}
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current e2fsprogs does not support set/show project ID"
+fi
+
+#
+# e2fsprogs-1.44.4 incorrectly reports verity 'V' bit when the project 'P'
+# bit is set. Skip this test when 1.44.4 is installed to prevent failures.
+#
+# https://github.com/tytso/e2fsprogs/commit/7e5a95e3d
+#
+if lsattr -V 2>&1 | grep "lsattr 1.44.4"; then
+ log_unsupported "Current e2fsprogs incorrectly reports 'V' verity bit"
+fi
+
+log_onexit cleanup
+
+log_assert "Check 'zfs project' is compatible with chattr/lsattr"
+
+log_must mkdir $PRJDIR
+log_must mkdir $PRJDIR/a1
+log_must mkdir $PRJDIR/a2
+log_must touch $PRJDIR/a3
+
+log_must chattr -p $PRJID1 $PRJDIR/a3
+log_must eval "zfs project $PRJDIR/a3 | grep '$PRJID1 \-'"
+
+log_must zfs project -p $PRJID2 $PRJDIR/a3
+log_must eval "lsattr -p $PRJDIR/a3 | grep $PRJID2 | grep -v '\-P[- ]* '"
+
+log_must chattr -p $PRJID1 $PRJDIR/a1
+log_must eval "zfs project -d $PRJDIR/a1 | grep '$PRJID1 \-'"
+
+log_must zfs project -p $PRJID2 $PRJDIR/a1
+log_must eval "lsattr -pd $PRJDIR/a1 | grep $PRJID2 | grep -v '\-P[- ]* '"
+
+log_must chattr +P $PRJDIR/a2
+log_must eval "zfs project -d $PRJDIR/a2 | grep '0 P'"
+
+log_must zfs project -s $PRJDIR/a2
+log_must eval "lsattr -pd $PRJDIR/a2 | grep 0 | grep '\-P[- ]* '"
+
+log_must chattr +P -p $PRJID1 $PRJDIR/a1
+log_must eval "zfs project -d $PRJDIR/a1 | grep '$PRJID1 P'"
+
+log_must zfs project -s -p $PRJID2 $PRJDIR/a2
+log_must eval "lsattr -pd $PRJDIR/a2 | grep $PRJID2 | grep '\-P[- ]* '"
+
+log_must chattr -P $PRJDIR/a1
+log_must eval "zfs project -d $PRJDIR/a1 | grep '$PRJID1 \-'"
+
+log_must zfs project -C -k $PRJDIR/a2
+log_must eval "lsattr -pd $PRJDIR/a2 | grep $PRJID2 | grep -v '\-P[- ]* '"
+
+log_pass "Check 'zfs project' is compatible with chattr/lsattr"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projecttree_002_pos.ksh b/tests/zfs-tests/tests/functional/projectquota/projecttree_002_pos.ksh
new file mode 100755
index 000000000000..d61019242703
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projecttree_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check project ID/flag can be operated via "zfs project"
+#
+#
+# STRATEGY:
+# 1. Create a tree with 4 level directories.
+# 2. Set project ID on both directory and regular file via
+# "zfs project -p".
+# 3. Check the project ID via "zfs project".
+# 4. Set project inherit flag on kinds of level directories (and its
+# descendants for some)) via "zfs project -s [-r]".
+# 5. Check the project ID and inherit flag via "zfs project -r".
+# 6. Clear the project inherit flag from some directories (and its
+# descendants for some) via "zfs project -C [-r]".
+# 7. Check the project ID and inherit flag via "zfs project -r".
+#
+
+function cleanup
+{
+ log_must rm -rf $PRJDIR
+}
+
+log_onexit cleanup
+
+log_assert "Check project ID/flag can be operated via 'zfs project'"
+
+log_must mkdir $PRJDIR
+
+log_must mkdir $PRJDIR/a1
+log_must mkdir $PRJDIR/b1
+log_must touch $PRJDIR/c1
+
+log_must mkdir $PRJDIR/a1/a2
+log_must mkdir $PRJDIR/a1/b2
+log_must touch $PRJDIR/a1/c2
+
+log_must mkdir $PRJDIR/b1/a2
+log_must mkdir $PRJDIR/b1/b2
+log_must touch $PRJDIR/b1/c2
+
+log_must mkdir $PRJDIR/a1/a2/a3
+log_must mkdir $PRJDIR/a1/a2/b3
+log_must touch $PRJDIR/a1/a2/c3
+
+log_must mkdir $PRJDIR/b1/a2/a3
+
+log_must touch $PRJDIR/a1/a2/a3/c4
+log_must touch $PRJDIR/a1/a2/a3/d4
+
+log_must zfs project -p $PRJID1 $PRJDIR/a1/c2
+log_must eval "zfs project $PRJDIR/a1/c2 | grep $PRJID1"
+
+log_must zfs project -p $PRJID2 $PRJDIR/a1/a2/a3
+log_must eval "zfs project -d $PRJDIR/a1/a2/a3 | grep $PRJID2"
+
+log_must zfs project -s $PRJDIR/b1/a2
+log_must eval "zfs project -d $PRJDIR/b1/a2 | grep ' P '"
+log_must eval "zfs project -d $PRJDIR/b1/a2/a3 | grep ' \- '"
+
+log_must zfs project -s -r -p $PRJID2 $PRJDIR/a1/a2
+log_must zfs project -c -r $PRJDIR/a1/a2
+log_must eval "zfs project -d $PRJDIR/a1/a2/a3 | grep ' P '"
+log_must eval "zfs project $PRJDIR/a1/a2/a3/c4 | grep $PRJID2"
+
+log_must zfs project -C $PRJDIR/a1/a2/a3
+log_must eval "zfs project -cr $PRJDIR/a1/a2 | grep 'inherit flag is not set'"
+log_must eval "zfs project $PRJDIR/a1/a2/a3/c4 | grep $PRJID2 | grep -v not"
+log_must zfs project -p 123 $PRJDIR/a1/a2/a3/c4
+log_must eval "zfs project -c -r $PRJDIR/a1/a2 | grep 123 | grep 'not set'"
+log_mustnot eval "zfs project -cr -p 123 $PRJDIR/a1/a2 | grep c4 | grep -v not"
+
+log_must zfs project -C -r $PRJDIR/a1/a2/a3
+log_must eval "zfs project -cr $PRJDIR/a1/a2 | grep a3 | grep 'not set'"
+log_must eval "zfs project -cr $PRJDIR/a1/a2 | grep d4 | grep 'not set'"
+log_must eval "zfs project $PRJDIR/a1/a2/a3/d4 | grep '0 \-'"
+
+log_must eval \
+ "zfs project -cr -0 $PRJDIR/a1/a2 | xargs -0 zfs project -s -p $PRJID2"
+log_mustnot eval "zfs project -cr $PRJDIR/a1/a2 | grep a3 | grep 'not set'"
+log_mustnot eval "zfs project -cr $PRJDIR/a1/a2 | grep d4 | grep 'not set'"
+
+log_must zfs project -C -r -k $PRJDIR/a1/a2
+log_must eval "zfs project -d $PRJDIR/a1/a2/b3 | grep '$PRJID2 \- '"
+
+log_pass "Check project ID/flag can be operated via 'zfs project'"
diff --git a/tests/zfs-tests/tests/functional/projectquota/projecttree_003_neg.ksh b/tests/zfs-tests/tests/functional/projectquota/projecttree_003_neg.ksh
new file mode 100755
index 000000000000..cbc45857f779
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/projecttree_003_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check 'zfs project' invalid options combinations
+#
+#
+# STRATEGY:
+# Verify the following:
+# 1. "-c" only supports "-d", "-p", "-r" and "-0".
+# 2. "-C" only supports "-r" and "-k".
+# 3. "-s" only supports "-r" and "-p".
+# 4. "-c", "-C" and "-s" can NOT be specified together.
+# 5. "-d" can overwrite former "-r".
+# 6. "-r" can overwrite former "-d".
+# 7. "-0" must be together with "-c".
+# 8. "-d" must be on directory.
+# 9. "-r" must be on directory.
+# 10. "-p" must be together with "-c -r" or "-s".
+#
+
+function cleanup
+{
+ log_must rm -rf $PRJDIR
+}
+
+log_onexit cleanup
+
+log_assert "Check 'zfs project' invalid options combinations"
+
+log_must mkdir $PRJDIR
+log_must mkdir $PRJDIR/a1
+log_must touch $PRJDIR/a2
+
+log_mustnot zfs project -c
+log_mustnot zfs project -c -k $PRJDIR/a1
+log_mustnot zfs project -c -C $PRJDIR/a1
+log_mustnot zfs project -c -s $PRJDIR/a1
+log_must zfs project -c -d -r $PRJDIR/a1
+log_must zfs project -c -r -d $PRJDIR/a1
+log_mustnot zfs project -c -d $PRJDIR/a2
+log_mustnot zfs project -c -r $PRJDIR/a2
+
+log_mustnot zfs project -C
+log_mustnot zfs project -C -c $PRJDIR/a1
+log_mustnot zfs project -C -d $PRJDIR/a1
+log_mustnot zfs project -C -p 100 $PRJDIR/a1
+log_mustnot zfs project -C -s $PRJDIR/a1
+log_mustnot zfs project -C -r -0 $PRJDIR/a1
+log_mustnot zfs project -C -0 $PRJDIR/a1
+
+log_mustnot zfs project -s
+log_mustnot zfs project -s -d $PRJDIR/a1
+log_mustnot zfs project -s -k $PRJDIR/a1
+log_mustnot zfs project -s -r -0 $PRJDIR/a1
+log_mustnot zfs project -s -0 $PRJDIR/a1
+log_mustnot zfs project -s -r $PRJDIR/a2
+
+log_mustnot zfs project -p 100
+log_mustnot zfs project -p -1 $PRJDIR/a2
+log_mustnot zfs project -p 100 -d $PRJDIR/a1
+log_mustnot zfs project -p 100 -k $PRJDIR/a1
+log_mustnot zfs project -p 100 -0 $PRJDIR/a1
+log_mustnot zfs project -p 100 -r -0 $PRJDIR/a1
+
+log_mustnot zfs project
+log_mustnot zfs project -0 $PRJDIR/a2
+log_mustnot zfs project -k $PRJDIR/a2
+log_mustnot zfs project -S $PRJDIR/a1
+
+log_pass "Check 'zfs project' invalid options combinations"
diff --git a/tests/zfs-tests/tests/functional/projectquota/setup.ksh b/tests/zfs-tests/tests/functional/projectquota/setup.ksh
new file mode 100755
index 000000000000..c81b300e5e96
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/projectquota/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) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/projectquota/projectquota_common.kshlib
+
+verify_runnable "both"
+
+del_user $PUSER
+del_group $PGROUP
+log_must add_group $PGROUP
+log_must add_user $PGROUP $PUSER
+
+#
+# Verify the test user can execute the zfs utilities. This may not
+# be possible due to default permissions on the user home directory.
+# This can be resolved granting group read access.
+#
+# chmod 0750 $HOME
+#
+user_run $PUSER zfs list
+if [ $? -ne 0 ]; then
+ log_unsupported "Test user $PUSER cannot execute zfs utilities"
+fi
+
+DISK=${DISKS%% *}
+default_setup_noexit $DISK
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/pyzfs/.gitignore b/tests/zfs-tests/tests/functional/pyzfs/.gitignore
new file mode 100644
index 000000000000..bcbe0573e32d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pyzfs/.gitignore
@@ -0,0 +1 @@
+pyzfs_unittest.ksh
diff --git a/tests/zfs-tests/tests/functional/pyzfs/Makefile.am b/tests/zfs-tests/tests/functional/pyzfs/Makefile.am
new file mode 100644
index 000000000000..26c5ac595a5d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pyzfs/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/config/Substfiles.am
+
+pkgpyzfsdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/pyzfs
+pkgpyzfs_SCRIPTS = \
+ pyzfs_unittest.ksh
+
+SUBSTFILES += $(pkgpyzfs_SCRIPTS)
diff --git a/tests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in b/tests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in
new file mode 100755
index 000000000000..4ca610e5f1e9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/pyzfs/pyzfs_unittest.ksh.in
@@ -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 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify the libzfs_core Python test suite can be run successfully
+#
+# STRATEGY:
+# 1. Run the nvlist and libzfs_core Python unittest
+# 2. Verify the exit code is 0 (no errors)
+#
+
+verify_runnable "global"
+
+# Verify that the required dependencies for testing are installed.
+@PYTHON@ -c "import cffi" 2>/dev/null
+if [ $? -eq 1 ]; then
+ log_unsupported "python-cffi not found by Python"
+fi
+
+# We don't just try to "import libzfs_core" because we want to skip these tests
+# only if pyzfs was not installed due to missing, build-time, dependencies; if
+# we cannot load "libzfs_core" due to other reasons, for instance an API/ABI
+# mismatch, we want to report it.
+@PYTHON@ -c '
+import pkgutil, sys
+sys.exit(pkgutil.find_loader("libzfs_core") is None)'
+if [ $? -eq 1 ]; then
+ log_unsupported "libzfs_core not found by Python"
+fi
+
+log_assert "Verify the nvlist and libzfs_core Python unittest run successfully"
+
+# NOTE: don't use log_must() here because it makes output unreadable
+@PYTHON@ -m unittest --verbose \
+ libzfs_core.test.test_nvlist.TestNVList \
+ libzfs_core.test.test_libzfs_core.ZFSTest
+if [ $? -ne 0 ]; then
+ log_fail "Python unittest completed with errors"
+fi
+
+log_pass "Python unittest completed without errors"
diff --git a/tests/zfs-tests/tests/functional/quota/Makefile.am b/tests/zfs-tests/tests/functional/quota/Makefile.am
new file mode 100644
index 000000000000..ba18bff7ecb7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/quota
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ quota_001_pos.ksh \
+ quota_002_pos.ksh \
+ quota_003_pos.ksh \
+ quota_004_pos.ksh \
+ quota_005_pos.ksh \
+ quota_006_neg.ksh
+
+dist_pkgdata_DATA = \
+ quota.cfg \
+ quota.kshlib
diff --git a/tests/zfs-tests/tests/functional/quota/cleanup.ksh b/tests/zfs-tests/tests/functional/quota/cleanup.ksh
new file mode 100755
index 000000000000..c4c369145dfc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_container_cleanup
diff --git a/tests/zfs-tests/tests/functional/quota/quota.cfg b/tests/zfs-tests/tests/functional/quota/quota.cfg
new file mode 100644
index 000000000000..5b19f40163de
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/quota.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export BLOCK_SIZE=8192
+export QUOTA_VALUE=10000000
+export TESTFILE1=file1
+export TESTFILE2=file2
+export TOLERANCE=131071
diff --git a/tests/zfs-tests/tests/functional/quota/quota.kshlib b/tests/zfs-tests/tests/functional/quota/quota.kshlib
new file mode 100644
index 000000000000..0ffe6394b54a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/quota.kshlib
@@ -0,0 +1,97 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/quota/quota.cfg
+
+# BLOCK_SIZE, QUOTA_VALUE and TOLERANCE set in quota.cfg
+if is_linux; then
+ readonly EDQUOT=122
+elif is_freebsd; then
+ readonly EDQUOT=69
+else
+ readonly EDQUOT=49
+fi
+
+#
+# Function to fill the quota of a zfs filesystem
+#
+# $1 - The File system or container to fill.
+# $2 - The mountpoint to use.
+#
+function fill_quota
+{
+ typeset FILESYSTEM="$1"
+ typeset MNTPT="$2"
+
+ log_must zfs set quota=$QUOTA_VALUE $FILESYSTEM
+
+ typeset -i write_size=0
+ (( write_size = 2 * QUOTA_VALUE ))
+
+ typeset -i zret=0
+ file_write -o create -f $MNTPT/$TESTFILE1 -b $BLOCK_SIZE \
+ -c $write_size -d 0
+ zret=$?
+ [[ $zret -ne $EDQUOT ]] && \
+ log_fail "Returned error code: $zret. Expected: $EDQUOT."
+
+ typeset -i file_size=`ls -lsk $MNTPT/$TESTFILE1 | awk '{ print $1 }'`
+ typeset -i limit=0
+ (( file_size = file_size * 1024 ))
+ (( limit = QUOTA_VALUE + TOLERANCE ))
+ (( file_size > limit )) && \
+ log_fail "File was created larger than the quota value, aborting!!!"
+ return 0
+}
+
+#
+# Function attempts to write another file in a ZFS filesystem
+# that has already filled its quota
+#
+function exceed_quota
+{
+ typeset FILESYSTEM="$1"
+ typeset MNTPT="$2"
+
+ log_must fill_quota $FILESYSTEM $MNTPT
+ typeset -i write_size=0
+ (( write_size = 2 * QUOTA_VALUE ))
+ typeset -i zret=0
+ #
+ # Writing a file without API to access return code
+ #
+ log_note "Creating a file in a FS that has already exceeded its quota"
+ file_write -o create -f $MNTPT/$TESTFILE2 \
+ -b $BLOCK_SIZE -c $write_size -d 0
+ zret=$?
+ [[ $zret -ne $EDQUOT ]] && \
+ log_fail "Returned error code: $zret. Expected: $EDQUOT."
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/quota/quota_001_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_001_pos.ksh
new file mode 100755
index 000000000000..d6783e9a43ac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/quota_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 2007 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/quota/quota.kshlib
+
+#
+# DESCRIPTION:
+#
+# A ZFS file system quota limits the amount of pool space
+# available to a file system. Apply a quota and verify
+# that no more file creates are permitted.
+#
+# STRATEGY:
+# 1) Apply quota to ZFS file system
+# 2) Create a file which is larger than the set quota
+# 3) Verify that the resulting file size is less than the quota limit
+#
+
+verify_runnable "both"
+
+log_assert "Verify that file size is limited by the file system quota"
+
+#
+# cleanup to be used internally as otherwise quota assertions cannot be
+# run independently or out of order
+#
+function cleanup
+{
+ [[ -e $TESTDIR/$TESTFILE1 ]] && \
+ log_must rm $TESTDIR/$TESTFILE1
+ #
+ # Need to allow time for space to be released back to
+ # pool, otherwise next test will fail trying to set a
+ # quota which is less than the space used.
+ #
+ wait_freeing $TESTPOOL
+ sync_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+#
+# Sets the quota value and attempts to fill it with a file
+# twice the size of the quota
+#
+log_must fill_quota $TESTPOOL/$TESTFS $TESTDIR
+
+log_pass "File size limited by quota"
diff --git a/tests/zfs-tests/tests/functional/quota/quota_002_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_002_pos.ksh
new file mode 100755
index 000000000000..2f34072dd151
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/quota_002_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 2007 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/quota/quota.kshlib
+
+#
+# DESCRIPTION:
+# A zfs file system quota limits the amount of pool space
+# available to a given ZFS file system. Once exceeded, it is impossible
+# to write any more files to the file system.
+#
+# STRATEGY:
+# 1) Apply quota to the ZFS file system
+# 2) Exceed the quota
+# 3) Attempt to write another file
+# 4) Verify the attempt fails with error code EDQUOTA (linux 122, others 49)
+#
+#
+
+verify_runnable "both"
+
+log_assert "Verify that a file write cannot exceed the file system quota"
+
+#
+# cleanup to be used internally as otherwise quota assertions cannot be
+# run independently or out of order
+#
+function cleanup
+{
+ [[ -e $TESTDIR/$TESTFILE1 ]] && \
+ log_must rm $TESTDIR/$TESTFILE1
+
+ [[ -e $TESTDIR/$TESTFILE2 ]] && \
+ log_must rm $TESTDIR/$TESTFILE2
+
+ wait_freeing $TESTPOOL
+ sync_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+#
+# Fills the quota & attempts to write another file
+#
+log_must exceed_quota $TESTPOOL/$TESTFS $TESTDIR
+
+log_pass "Could not write file. Quota limit enforced as expected"
diff --git a/tests/zfs-tests/tests/functional/quota/quota_003_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_003_pos.ksh
new file mode 100755
index 000000000000..6ab25cf2d463
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/quota_003_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 2007 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/quota/quota.kshlib
+
+#
+# DESCRIPTION:
+# A ZFS file system quota limits the amount of pool space
+# available to a file system dataset. Apply a quota and verify
+# that no more file creates are permitted.
+#
+# NOTE: THis test applies to a dataset rather than a file system.
+#
+# STRATEGY:
+# 1) Apply quota to ZFS file system dataset
+# 2) Create a file which is larger than the set quota
+# 3) Verify that the resulting file size is less than the quota limit
+#
+
+verify_runnable "both"
+
+log_assert "Verify that file size is limited by the file system quota" \
+ "(dataset version)"
+
+#
+# cleanup to be used internally as otherwise quota assertions cannot be
+# run independently or out of order
+#
+function cleanup
+{
+ [[ -e $TESTDIR1/$TESTFILE1 ]] && \
+ log_must rm $TESTDIR1/$TESTFILE1
+
+ #
+ # Need to allow time for space to be released back to
+ # pool, otherwise next test will fail trying to set a
+ # quota which is less than the space used.
+ #
+ wait_freeing $TESTPOOL
+ sync_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+#
+# Sets the quota value and attempts to fill it with a file
+# twice the size of the quota
+#
+log_must fill_quota $TESTPOOL/$TESTCTR/$TESTFS1 $TESTDIR1
+
+log_pass "File size limited by quota"
diff --git a/tests/zfs-tests/tests/functional/quota/quota_004_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_004_pos.ksh
new file mode 100755
index 000000000000..373354438925
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/quota_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 2007 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/quota/quota.kshlib
+
+#
+# DESCRIPTION:
+# A zfs file system quota limits the amount of pool space
+# available to a given ZFS file system dataset. Once exceeded, it
+# is impossible to write any more files to the file system.
+#
+# STRATEGY:
+# 1) Apply quota to the ZFS file system dataset
+# 2) Exceed the quota
+# 3) Attempt to write another file
+# 4) Verify the attempt fails with error code EDQUOTA (linux 122, others 49)
+#
+#
+
+verify_runnable "both"
+
+log_assert "Verify that a file write cannot exceed the file system quota" \
+ "(dataset version)"
+
+#
+# cleanup to be used internally as otherwise quota assertions cannot be
+# run independently or out of order
+#
+function cleanup
+{
+ [[ -e $TESTDIR1/$TESTFILE1 ]] && \
+ log_must rm $TESTDIR1/$TESTFILE1
+
+ [[ -e $TESTDIR1/$TESTFILE2 ]] && \
+ log_must rm $TESTDIR1/$TESTFILE2
+
+ wait_freeing $TESTPOOL
+ sync_pool $TESTPOOL
+}
+
+log_onexit cleanup
+
+#
+# Fills the quota & attempts to write another file
+#
+log_must exceed_quota $TESTPOOL/$TESTCTR/$TESTFS1 $TESTDIR1
+
+log_pass "Could not write file. Quota limit enforced as expected"
diff --git a/tests/zfs-tests/tests/functional/quota/quota_005_pos.ksh b/tests/zfs-tests/tests/functional/quota/quota_005_pos.ksh
new file mode 100755
index 000000000000..ed28cc1f0c9b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/quota_005_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 2007 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/quota/quota.kshlib
+
+#
+# DESCRIPTION:
+#
+# Verify that quota doesn't inherit its value from parent.
+#
+# STRATEGY:
+# 1) Set quota for parents
+# 2) Create a filesystem tree
+# 3) Verify that the 'quota' for descendent doesnot inherit the value.
+#
+###############################################################################
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $fs_child && \
+ log_must zfs destroy $fs_child
+
+ log_must zfs set quota=$quota_val $fs
+}
+
+log_onexit cleanup
+
+log_assert "Verify that quota doesnot inherit its value from parent."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+fs_child=$TESTPOOL/$TESTFS/$TESTFS
+
+space_avail=$(get_prop available $fs)
+quota_val=$(get_prop quota $fs)
+typeset -i quotasize=$space_avail
+((quotasize = quotasize * 2 ))
+log_must zfs set quota=$quotasize $fs
+
+log_must zfs create $fs_child
+quota_space=$(get_prop quota $fs_child)
+[[ $quota_space == $quotasize ]] && \
+ log_fail "The quota of child dataset inherits its value from parent."
+
+log_pass "quota doesnot inherit its value from parent as expected."
diff --git a/tests/zfs-tests/tests/functional/quota/quota_006_neg.ksh b/tests/zfs-tests/tests/functional/quota/quota_006_neg.ksh
new file mode 100755
index 000000000000..ca5ea5f82f5a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/quota_006_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/quota/quota.kshlib
+
+#
+# DESCRIPTION:
+#
+# Can't set a quota to less than currently being used by the dataset.
+#
+# STRATEGY:
+# 1) Create a filesystem
+# 2) Set a quota on the filesystem that is lower than the space
+# currently in use.
+# 3) Verify that the attempt fails.
+#
+
+verify_runnable "both"
+
+log_assert "Verify cannot set quota lower than the space currently in use"
+
+function cleanup
+{
+ log_must zfs set quota=none $TESTPOOL/$TESTFS
+}
+
+log_onexit cleanup
+
+typeset -i quota_integer_size=0
+typeset invalid_size="123! @456 7#89 0\$ abc123% 123%s 12%s3 %c123 123%d %x123 12%p3 \
+ ^def456 789&ghi"
+typeset -i space_used=`get_prop used $TESTPOOL/$TESTFS`
+(( quota_integer_size = space_used - 1 ))
+quota_fp_size=${quota_integer_size}.123
+
+for size in 0 -1 $quota_integer_size -$quota_integer_size $quota_fp_size -$quota_fp_size \
+ $invalid_size ; do
+ log_mustnot zfs set quota=$size $TESTPOOL/$TESTFS
+done
+log_must zfs set quota=$space_used $TESTPOOL/$TESTFS
+
+log_pass "As expected cannot set quota lower than space currently in use"
diff --git a/tests/zfs-tests/tests/functional/quota/setup.ksh b/tests/zfs-tests/tests/functional/quota/setup.ksh
new file mode 100755
index 000000000000..677cb12d79ac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/quota/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_container_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/raidz/Makefile.am b/tests/zfs-tests/tests/functional/raidz/Makefile.am
new file mode 100644
index 000000000000..694de18a6cf9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/raidz
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ raidz_001_neg.ksh \
+ raidz_002_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/raidz/cleanup.ksh b/tests/zfs-tests/tests/functional/raidz/cleanup.ksh
new file mode 100755
index 000000000000..c92c54c270a7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/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 (c) 2016 by Gvozden Neskovic. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+# default_cleanup
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_001_neg.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_001_neg.ksh
new file mode 100755
index 000000000000..0f88a1a51468
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_001_neg.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 (c) 2016 by Gvozden Neskovic. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Call the raidz_test tool with -T options to test the infrastructure.
+# This option should make raidz_test to return non 0.
+#
+
+log_mustnot raidz_test -T
+
+log_pass "raidz_test detects errors as expected."
diff --git a/tests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh b/tests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh
new file mode 100755
index 000000000000..e238a881b054
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/raidz_002_pos.ksh
@@ -0,0 +1,41 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 Gvozden Neskovic. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Call the raidz_test tool with -S to test all supported raidz
+# implementations. This options will test several raidz block geometries
+# and several zio parameters that affect raidz block layout. Data
+# reconstruction performs all combinations of failed disks. Wall time
+# is set to 5min, but actual runtime might be longer.
+#
+
+log_must raidz_test -S -t 300
+
+log_pass "raidz_test parameter sweep test succeeded."
diff --git a/tests/zfs-tests/tests/functional/raidz/setup.ksh b/tests/zfs-tests/tests/functional/raidz/setup.ksh
new file mode 100755
index 000000000000..4e155d24d544
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/raidz/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 (c) 2016 by Gvozden Neskovic. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/redacted_send/Makefile.am b/tests/zfs-tests/tests/functional/redacted_send/Makefile.am
new file mode 100644
index 000000000000..dd6b4eb679a3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/Makefile.am
@@ -0,0 +1,25 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/redacted_send
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ redacted_compressed.ksh \
+ redacted_contents.ksh \
+ redacted_deleted.ksh \
+ redacted_disabled_feature.ksh \
+ redacted_embedded.ksh \
+ redacted_holes.ksh \
+ redacted_incrementals.ksh \
+ redacted_largeblocks.ksh \
+ redacted_many_clones.ksh \
+ redacted_mixed_recsize.ksh \
+ redacted_mounts.ksh \
+ redacted_negative.ksh \
+ redacted_origin.ksh \
+ redacted_props.ksh \
+ redacted_resume.ksh \
+ redacted_size.ksh \
+ redacted_volume.ksh
+
+dist_pkgdata_DATA = \
+ redacted.cfg \
+ redacted.kshlib
diff --git a/tests/zfs-tests/tests/functional/redacted_send/cleanup.ksh b/tests/zfs-tests/tests/functional/redacted_send/cleanup.ksh
new file mode 100755
index 000000000000..1a7c142b8551
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_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 (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+destroy_pool $POOL
+destroy_pool $POOL2
+log_must set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 0
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted.cfg b/tests/zfs-tests/tests/functional/redacted_send/redacted.cfg
new file mode 100644
index 000000000000..f964b37bad3b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted.cfg
@@ -0,0 +1,86 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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.
+#
+
+export DISK1=$(echo $DISKS | awk '{print $1}')
+export DISK2=$(echo $DISKS | awk '{print $2}')
+
+export POOL=$TESTPOOL
+export POOL2=$TESTPOOL2
+export FS=$TESTFS
+export FS2=$TESTFS2
+
+#
+# These are the byte ranges that differ between files and their redacted
+# counterparts. See compare_files() for more detail.
+#
+typeset RANGE0="0,2097152"
+typeset RANGE1="0,131072"
+typeset RANGE2="1048576,2097152"
+typeset RANGE3="0,131072
+1966080,131072
+3932160,131072"
+typeset RANGE4="0,131072
+262144,131072
+524288,131072
+786432,131072"
+typeset RANGE5="0,1048576
+7340032,1048576"
+typeset RANGE6="393216,131072
+655360,131072
+917504,131072
+1179648,131072
+1441792,393216
+1966080,393216
+2621440,262144
+3145728,262144
+3670016,262144
+4194304,262144
+4718592,262144
+5242880,262144"
+typeset RANGE7="1048576,6291456"
+typeset RANGE8="4063232,131072"
+typeset RANGE9="0,131072
+262144,131072
+524288,131072
+786432,131072
+1048576,131072
+1310720,131072
+1572864,131072
+1835008,131072
+2097152,131072
+2359296,131072
+2621440,131072
+2883584,131072
+3145728,131072
+3407872,131072
+3670016,131072
+3932160,131072"
+typeset RANGE10="0,393216"
+typeset RANGE11="0,1048576"
+typeset RANGE12="0,2097152"
+typeset RANGE13="0,16384"
+typeset RANGE14=""
+typeset RANGE15="0,4194304"
+typeset RANGE16="0,6291456" \ No newline at end of file
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib b/tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib
new file mode 100644
index 000000000000..30101939db64
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib
@@ -0,0 +1,266 @@
+#!/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 (c) 2016, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/tests/functional/redacted_send/redacted.cfg
+
+function setup_dataset
+{
+ typeset ds_name=$1
+ typeset opts=$2
+ typeset file_create_func=$3
+ typeset sendfs="$POOL/$ds_name"
+ [[ -n $file_create_func ]] || file_create_func=setup_common
+
+ log_must zfs create $opts $sendfs
+
+ $file_create_func $sendfs
+
+ log_must zfs snapshot $sendfs@snap
+ log_must zfs clone $opts $sendfs@snap $POOL/${ds_name}_clone
+ log_must zfs snapshot $POOL/${ds_name}_clone@snap
+}
+
+function setup_common
+{
+ typeset sendfs=$1
+
+ typeset mntpnt=$(get_prop mountpoint $sendfs)
+ typeset bs=$(get_prop recsize $sendfs)
+ log_must dd if=/dev/urandom of=$mntpnt/f1 bs=$bs count=16
+ log_must dd if=/dev/urandom of=$mntpnt/f2 bs=$bs count=32
+}
+
+function setup_embedded
+{
+ typeset sendfs=$1
+
+ typeset recsize
+ typeset mntpnt=$(get_prop mountpoint $sendfs)
+ for recsize in 512 1024 2048 4096 8192 16384; do
+ if is_illumos; then
+ log_must mkholes -d $((recsize - 8)):8 $mntpnt/$recsize
+ else
+ log_must dd if=/dev/urandom of=$mntpnt/$recsize bs=8 \
+ count=1 seek=$(((recsize / 8) - 1))
+ fi
+ done
+}
+
+function setup_holes
+{
+ typeset sendfs=$1
+
+ typeset mntpnt=$(get_prop mountpoint $sendfs)
+ typeset M=$((1024 * 1024))
+
+ if is_illumos; then
+ log_must mkholes -d 0:$((8 * M)) $mntpnt/f1
+ log_must mkholes -d 0:$M -d $((7 * M)):$M $mntpnt/f2
+ log_must mkholes -d $M:$((6 * M)) -h $((7 * M)):$M $mntpnt/f3
+ log_must mkholes -h 0:$((8 * M)) $mntpnt/f4
+ else
+ log_must dd if=/dev/urandom of=$mntpnt/f1 bs=8M count=1
+
+ log_must dd if=/dev/urandom of=$mntpnt/f2 bs=1M count=1
+ log_must dd if=/dev/urandom of=$mntpnt/f2 bs=1M count=1 seek=7 \
+ conv=notrunc
+
+ log_must dd if=/dev/urandom of=$mntpnt/f3 bs=1M count=6 seek=1
+ log_must truncate -s $((8 * M)) $mntpnt/f3
+
+ log_must truncate -s $((8 * M)) $mntpnt/f4
+ fi
+
+ log_must zfs create $sendfs/manyrm
+ for i in {1..256}; do
+ log_must stride_dd -i /dev/urandom -o $mntpnt/manyrm/f$i -b 512 \
+ -c $(random_int_between 1 100) -s $(random_int_between 1 4)
+ done
+
+ log_must zfs snapshot $sendfs/manyrm@snap
+ log_must zfs clone $sendfs/manyrm@snap $sendfs/manyrm_clone
+ log_must zfs snapshot $sendfs/manyrm_clone@snap
+}
+
+function setup_incrementals
+{
+ typeset sendfs=$1
+
+ typeset mntpnt=$(get_prop mountpoint $sendfs)
+ typeset bs=$(get_prop recsize $sendfs)
+ log_must dd if=/dev/urandom of=$mntpnt/f1 bs=$bs count=16
+ log_must dd if=/dev/urandom of=$mntpnt/f2 bs=$bs count=32
+ log_must mkdir $mntpnt/d1
+ log_must eval "cat $mntpnt/f1 $mntpnt/f2 >$mntpnt/d1/f1"
+ log_must zfs snapshot $sendfs@snap0
+
+ log_must zfs clone $sendfs@snap0 $POOL/hole
+ mntpnt=$(get_prop mountpoint $POOL/hole)
+ log_must dd if=/dev/zero of=$mntpnt/f2 bs=$bs count=16 conv=notrunc
+ log_must zfs snapshot $POOL/hole@snap
+
+ log_must zfs clone $sendfs@snap0 $POOL/stride3
+ mntpnt=$(get_prop mountpoint $POOL/stride3)
+ log_must stride_dd -i /dev/urandom -o $mntpnt/f2 -b $bs -c 11 -s 3
+ log_must zfs snapshot $POOL/stride3@snap
+
+ log_must zfs clone $sendfs@snap0 $POOL/stride5
+ mntpnt=$(get_prop mountpoint $POOL/stride5)
+ log_must stride_dd -i /dev/urandom -o $mntpnt/f2 -b $bs -c 7 -s 5
+ log_must zfs snapshot $POOL/stride5@snap
+
+ log_must zfs clone $sendfs@snap0 $POOL/int
+ log_must zfs snapshot $POOL/int@snap
+
+ log_must zfs clone $POOL/int@snap $POOL/rm
+ mntpnt=$(get_prop mountpoint $POOL/rm)
+ log_must rm -rf $mntpnt/[df][12]
+ log_must zfs snapshot $POOL/rm@snap
+
+ log_must zfs clone $POOL/int@snap $POOL/write
+ mntpnt=$(get_prop mountpoint $POOL/write)
+ log_must dd if=/dev/urandom of=$mntpnt/f1 bs=512 count=16 conv=notrunc
+ log_must dd if=/dev/urandom of=$mntpnt/d1/f1 bs=512 count=16 seek=16 \
+ conv=notrunc
+ log_must zfs snapshot $POOL/write@snap
+}
+
+function setup_mounts
+{
+ typeset sendfs=$1
+
+ typeset mntpnt=$(get_prop mountpoint $sendfs)
+ log_must touch $mntpnt/empty
+ log_must dd if=/dev/urandom of=$mntpnt/contents1 bs=512 count=2
+ log_must dd if=/dev/urandom of=$mntpnt/contents2 bs=512 count=2
+ log_must mkdir $mntpnt/dir1
+ log_must touch $mntpnt/dir1/empty
+ log_must dd if=/dev/urandom of=$mntpnt/dir1/contents1 bs=512 count=2
+ log_must dd if=/dev/urandom of=$mntpnt/dir1/contents2 bs=512 count=2
+ log_must mkdir $mntpnt/dir1/dir2
+ log_must touch $mntpnt/dir1/dir2/empty
+ log_must dd if=/dev/urandom of=$mntpnt/dir1/dir2/file bs=512 count=2
+
+ log_must zfs create -s -V 16p $sendfs/vol
+ log_must zfs snapshot $sendfs/vol@snap
+ log_must zfs clone $sendfs/vol@snap $sendfs/vol_clone
+ log_must zfs snapshot $sendfs/vol_clone@snap
+}
+
+function mount_redacted
+{
+ typeset flag=''
+ while getopts "f" opt; do
+ case $opt in
+ f)
+ flag='-f'
+ ;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+
+ typeset ds=$1
+ log_must set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 1
+ zfs mount $flag -oro $ds || return 1
+ log_must set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 0
+ return 0
+}
+
+function unmount_redacted
+{
+ typeset ds=$1
+
+ zfs unmount $ds
+}
+
+#
+# This function calls a utility that prints out the ranges where a file
+# and its redacted counterpart differ, each range on a new line like this:
+#
+# 0,131072
+# 1966080,131072
+# 3932160,131072
+#
+# The output is then checked against a variable containing the expected
+# output to verify the redacted ranges are the ones expected.
+#
+function compare_files
+{
+ typeset sendfs=$1
+ typeset recvfs=$2
+ typeset file=$3
+ typeset expected="$4"
+ typeset tmpfile="$tmpdir/get_file.out"
+
+ log_must mount_redacted -f $recvfs
+
+ typeset file1="$(get_prop mountpoint $sendfs)/$file"
+ typeset file2="$(get_prop mountpoint $recvfs)/$file"
+ log_note "Comparing $file1 and $file2"
+ [[ -f $file1 ]] || log_fail "File $file1 does not exist."
+ [[ -f $file2 ]] || log_fail "File $file2 does not exist."
+
+ log_must eval "get_diff $file1 $file2 >$tmpfile"
+ typeset range="$(cat $tmpfile)"
+ log_must unmount_redacted $recvfs
+ [[ "$expected" = "$range" ]] || log_fail "Unexpected range: $range"
+}
+
+function redacted_cleanup
+{
+ typeset ds_list=$@
+ typeset ds
+
+ for ds in $ds_list; do
+ zfs destroy -R $ds
+ done
+
+ set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 0
+ rm -f $(get_prop mountpoint $POOL)/tmp/*
+}
+
+# Retrieve the redaction list of a bookmark or snapshot, using
+# the property or zdb output, as requested.
+function get_guid_list
+{
+ typeset filename=$1
+ typeset dataset=$2
+ typeset use_zdb=${3:-false}
+
+ if $use_zdb; then
+ guid_list=$(zdb -vvvv $dataset | sed -e 's/,//g' \
+ -ne 's/^.*Snapshots: \[\(.*\)\]/\1/p')
+ else
+ guid_list=$(get_prop redact_snaps $dataset)
+ fi
+
+ for guid in $(echo $guid_list | tr ',' ' '); do
+ echo $guid
+ done | sort >$filename
+}
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_compressed.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_compressed.ksh
new file mode 100755
index 000000000000..0a8bf3903c28
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_compressed.ksh
@@ -0,0 +1,71 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify that compressed send streams are redacted correctly.
+#
+# Strategy:
+# 1. Receive a redacted compressed send stream, verifying compression and
+# redaction.
+# 2. Receive an incremental on the full receive, verifying compression and
+# redaction.
+#
+
+typeset ds_name="compressed"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name "-o compress=lz4"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+log_must stride_dd -i /dev/urandom -o $clone_mnt/f1 -b $((128 * 1024)) -c 4 -s 2
+log_must zfs snapshot $clone@snap1
+log_must rm $clone_mnt/f2
+log_must zfs snapshot $clone@snap2
+
+log_must zfs redact $sendfs@snap book1 $clone@snap1 $clone@snap2
+log_must eval "zfs send -c --redact book1 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must stream_has_features $stream compressed lz4 redacted
+compare_files $sendfs $recvfs "f1" "$RANGE4"
+verify_stream_size $stream $sendfs
+log_must mount_redacted -f $recvfs
+verify_stream_size $stream $recvfs
+log_must unmount_redacted $recvfs
+
+log_must eval "zfs send -c -i $sendfs@snap $clone@snap1 >$stream"
+log_must eval "zfs recv $POOL2/inc1 <$stream"
+log_must stream_has_features $stream compressed lz4
+typeset mntpnt=$(get_prop mountpoint $POOL2)
+log_must diff $clone_mnt/f1 $mntpnt/inc1/f1
+log_must diff $send_mnt/f2 $mntpnt/inc1/f2
+
+log_must eval "zfs send -c -i $sendfs@snap $clone@snap2 >$stream"
+log_must eval "zfs recv $POOL2/inc2 <$stream"
+log_must stream_has_features $stream compressed lz4
+log_must diff $clone_mnt/f1 $mntpnt/inc1/f1
+[[ -f $mntpnt/inc2/f2 ]] && log_fail "File f2 should not exist."
+
+log_pass "Compressed send streams are redacted correctly."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_contents.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_contents.ksh
new file mode 100755
index 000000000000..fb12862c9531
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_contents.ksh
@@ -0,0 +1,162 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify redaction works as expected for various scenarios.
+#
+# Strategy:
+# 1. An unmodified file does not get redacted at all.
+# 2. Empty redaction list redacts everything.
+# 3. A file removed in the clone redacts the whole file.
+# 4. A file moved in the clone does not redact the file.
+# 5. A copied, then removed file in the clone redacts the whole file.
+# 6. Overwriting a file with identical contents redacts the file.
+# 7. A partially modified block redacts the entire block.
+# 8. Only overlapping areas of modified ranges are redacted.
+# 9. Send from the root dataset of a pool work correctly.
+#
+
+typeset ds_name="contents"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name ''
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+# An unmodified file does not get redacted at all.
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book1 $clone@snap1
+log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must mount_redacted -f $recvfs
+log_must diff $send_mnt/f1 $recv_mnt/f1
+log_must diff $send_mnt/f2 $recv_mnt/f2
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Removing a file in the clone redacts the entire file.
+log_must rm "$clone_mnt/f1"
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book3 $clone@snap1
+log_must eval "zfs send --redact book3 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f1" "$RANGE0"
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Moving a file in the clone does not redact the file.
+log_must mv "$clone_mnt/f1" "$clone_mnt/f1.moved"
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book4 $clone@snap1
+log_must eval "zfs send --redact book4 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must mount_redacted -f $recvfs
+[[ -f $recv_mnt/f1.moved ]] && log_fail "Found moved file in redacted receive."
+log_must diff $send_mnt/f1 $recv_mnt/f1
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Copying, then removing a file in the clone does redact the file.
+log_must cp "$clone_mnt/f1" "$clone_mnt/f1.copied"
+log_must rm "$clone_mnt/f1"
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book5 $clone@snap1
+log_must eval "zfs send --redact book5 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f1" "$RANGE0"
+log_must mount_redacted -f $recvfs
+[[ -f $recv_mnt/f1.copied ]] && log_fail "Found moved file in redacted receive."
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Overwriting the contents of a block with identical contents redacts the file.
+log_must cp "$clone_mnt/f1" "$clone_mnt/f1.copied"
+log_must cp "$clone_mnt/f1.copied" "$clone_mnt/f1"
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book6 $clone@snap1
+log_must eval "zfs send --redact book6 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f1" "$RANGE0"
+log_must mount_redacted -f $recvfs
+[[ -f $recv_mnt/f1.copied ]] && log_fail "Found moved file in redacted receive."
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Modifying some of a block redacts the whole block.
+log_must dd if=/dev/urandom of=$clone_mnt/f1 conv=notrunc seek=2 count=1 bs=32k
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book7 $clone@snap1
+log_must eval "zfs send --redact book7 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f1" "$RANGE1"
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Only overlapping areas of modified ranges are redacted.
+log_must dd if=/dev/urandom of=$clone_mnt/f2 bs=1024k count=3 conv=notrunc
+log_must zfs snapshot $clone@snap1
+log_must zfs clone $sendfs@snap $clone/new
+typeset mntpnt="$(get_prop mountpoint $clone/new)"
+log_must dd if=/dev/urandom of=$mntpnt/f2 bs=1024k seek=1 count=3 \
+ conv=notrunc
+log_must zfs snapshot $clone/new@snap
+log_must zfs redact $sendfs@snap book8 $clone@snap1 $clone/new@snap
+log_must eval "zfs send --redact book8 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f2" "$RANGE2"
+log_must zfs destroy -R $clone/new
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# FizzBuzz version
+log_must zfs clone $sendfs@snap $POOL/stride3
+mntpnt="$(get_prop mountpoint $POOL/stride3)"
+log_must stride_dd -i /dev/urandom -o $mntpnt/f2 -b $((128 * 1024)) -c 11 -s 3
+log_must zfs snapshot $POOL/stride3@snap
+log_must zfs clone $sendfs@snap $POOL/stride5
+mntpnt="$(get_prop mountpoint $POOL/stride5)"
+log_must stride_dd -i /dev/urandom -o $mntpnt/f2 -b $((128 * 1024)) -c 7 -s 5
+log_must zfs snapshot $POOL/stride5@snap
+log_must zfs redact $sendfs@snap book8a $POOL/stride3@snap $POOL/stride5@snap
+log_must eval "zfs send --redact book8a $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f2" "$RANGE3"
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Send from the root dataset of a pool work correctly.
+log_must dd if=/dev/urandom of=/$POOL/f1 bs=128k count=4
+log_must zfs snapshot $POOL@snap
+log_must zfs clone $POOL@snap $POOL/clone
+log_must dd if=/dev/urandom of=/$POOL/clone/f1 bs=128k count=1 conv=notrunc
+log_must zfs snapshot $POOL/clone@snap
+log_must zfs redact $POOL@snap book9 $POOL/clone@snap
+log_must eval "zfs send --redact book9 $POOL@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $POOL $recvfs "f1" "$RANGE1"
+log_must zfs destroy -R $POOL@snap
+
+log_pass "Redaction works as expected for various scenarios."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_deleted.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_deleted.ksh
new file mode 100755
index 000000000000..3e2aeb733546
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_deleted.ksh
@@ -0,0 +1,103 @@
+#!/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, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify redaction works as expected with respect to deleted files
+#
+# Strategy:
+# 1. A file on the delete queue counts as deleted when using it to calculate
+# redaction.
+# 2. A file that is removed in the tosnap of an incremental, where the fromsnap
+# is a redaction bookmark that contains references to that file, does not
+# result in records for that file.
+#
+
+typeset ds_name="deleted"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset clone2="$POOL/${ds_name}_clone2"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name ''
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+#
+# A file on the delete queue counts as deleted when using it to calculate
+# redaction.
+#
+
+#
+# Open file descriptor 5 for appending to $clone_mnt/f1 so that it will go on
+# the delete queue when we rm it.
+#
+exec 5>>$clone_mnt/f1
+log_must dd if=/dev/urandom of=$clone_mnt/f1 bs=512 count=1 conv=notrunc
+log_must rm $clone_mnt/f1
+log_must zfs snapshot $clone@snap1
+# Close file descriptor 5
+exec 5>&-
+log_must zfs redact $sendfs@snap book1 $clone@snap1
+log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must mount_redacted -f $recvfs
+#
+# We have temporarily disabled redaction blkptrs, so this will not
+# fail as was originally intended. We should uncomment this line
+# when we re-enable redaction blkptrs.
+#
+#log_mustnot dd if=$recv_mnt/f1 of=/dev/null bs=512 count=1
+log_must diff $send_mnt/f2 $recv_mnt/f2
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+#
+# A file that is removed in the tosnap of an incremental, where the fromsnap
+# is a redaction bookmark that contains references to that file, does not
+# result in records for that file.
+#
+log_must zfs clone $sendfs@snap $clone2
+typeset clone2_mnt="$(get_prop mountpoint $clone2)"
+log_must rm -rf $clone2_mnt/*
+log_must zfs snapshot $clone2@snap
+log_must zfs redact $sendfs@snap book2 $clone2@snap
+log_must zfs destroy -R $clone2
+log_must eval "zfs send --redact book2 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must rm $send_mnt/f1
+log_must zfs snapshot $sendfs@snap2
+log_must zfs clone $sendfs@snap2 $clone2
+typeset clone2_mnt="$(get_prop mountpoint $clone2)"
+log_must rm $clone2_mnt/*
+log_must zfs snapshot $clone2@snap
+log_must zfs redact $sendfs@snap2 book3 $clone2@snap
+log_must zfs destroy -R $clone2
+log_must eval "zfs send -i $sendfs#book2 --redact book3 $sendfs@snap2 >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must mount_redacted -f $recvfs
+log_must diff <(ls $send_mnt) <(ls $recv_mnt)
+log_must zfs destroy -R $recvfs
+log_must zfs rollback -R $sendfs@snap
+
+log_pass "Verify Redaction works as expected with respect to deleted files."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_disabled_feature.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_disabled_feature.ksh
new file mode 100755
index 000000000000..3cf73f00167e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_disabled_feature.ksh
@@ -0,0 +1,71 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify the functionality of the redaction_bookmarks and redacted_datasets
+# features.
+#
+# Strategy:
+# 1. Create a pool with all features disabled.
+# 2. Verify redacted send fails.
+# 3. Enable redaction_bookmarks and verify redacted sends works.
+# 4. Verify receipt of a redacted stream fails.
+# 5. Enable recacted_datasets and verify zfs receive works.
+#
+
+typeset ds_name="disabled"
+typeset sendfs="$POOL/$ds_name"
+typeset sendfs1="$POOL2/${ds_name}1"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset clone1="$POOL2/${ds_name}_clone1"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name ''
+
+function cleanup
+{
+ destroy_pool $POOL2
+ create_pool $POOL2 $DISK2
+ log_must zfs snapshot $POOL2@init
+ redacted_cleanup $sendfs $recvfs
+}
+
+log_onexit cleanup
+
+destroy_pool $POOL2
+log_must zpool create -d $POOL2 $DISK2
+
+log_must zfs create $sendfs1
+log_must zfs snapshot $sendfs1@snap
+log_must zfs clone $sendfs1@snap $clone1
+log_must zfs snapshot $clone1@snap
+
+log_mustnot zfs redact $sendfs1@snap book1 $clone1@snap
+log_must zpool set feature@redaction_bookmarks=enabled $POOL2
+log_must zfs redact $sendfs1@snap book1 $clone1@snap
+
+log_must zfs redact $sendfs@snap book1 $clone@snap
+log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
+log_mustnot eval "zfs recv $recvfs <$stream"
+log_must zpool set feature@redacted_datasets=enabled $POOL2
+log_must eval "zfs recv $recvfs <$stream"
+
+log_pass "The redacted send/recv features work correctly."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_embedded.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_embedded.ksh
new file mode 100755
index 000000000000..94937a2f79ab
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_embedded.ksh
@@ -0,0 +1,103 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify embedded blocks and redacted send work correctly together.
+#
+# Strategy:
+# 1. Create recsize sized files with embedded blocks from size 512b to 16k.
+# 2. Receive a redacted send stream with nothing redacted.
+# 3. Verify the received files match the source, contain embedded blocks, and
+# that the stream has the redacted and embedded data features.
+# 4. Receive a redacted send stream with files 512, 2048 and 8192 redacted.
+# 5. Verify that the redacted files no longer match, but the others still
+# contain embedded blocks and the stream has the redacted and embedded
+# data features.
+#
+
+typeset ds_name="embedded"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name '-o compress=lz4' setup_embedded
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+typeset recsize send_obj recv_obj
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+log_must zfs redact $sendfs@snap book1 $clone@snap
+log_must eval "zfs send -e --redact book1 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must stream_has_features $stream redacted embed_data
+
+log_must mount_redacted -f $recvfs
+for recsize in 512 1024 2048 4096 8192 16384; do
+ send_obj=$(get_objnum $send_mnt/$recsize)
+ recv_obj=$(get_objnum $recv_mnt/$recsize)
+
+ log_must diff $send_mnt/$recsize $recv_mnt/$recsize
+ log_must eval "zdb -ddddd $sendfs $send_obj >$tmpdir/send.zdb"
+ log_must eval "zdb -ddddd $recvfs $recv_obj >$tmpdir/recv.zdb"
+
+ grep -q "EMBEDDED" $tmpdir/send.zdb || \
+ log_fail "Obj $send_obj not embedded in $sendfs"
+ grep -q "EMBEDDED" $tmpdir/recv.zdb || \
+ log_fail "Obj $recv_obj not embedded in $recvfs"
+
+ cat $stream | zstreamdump -v | log_must grep -q \
+ "WRITE_EMBEDDED object = $send_obj offset = 0"
+done
+
+log_must zfs destroy -R $recvfs
+for recsize in 512 2048 8192; do
+ log_must dd if=/dev/urandom of=$clone_mnt/$recsize bs=$recsize count=1
+done
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book2 $clone@snap1
+log_must eval "zfs send -e --redact book2 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must stream_has_features $stream redacted embed_data
+
+log_must mount_redacted -f $recvfs
+for recsize in 512 2048 8192; do
+ log_mustnot diff $send_mnt/$recsize $recv_mnt/$recsize
+done
+for recsize in 1024 4096 16384; do
+ send_obj=$(get_objnum $send_mnt/$recsize)
+ recv_obj=$(get_objnum $recv_mnt/$recsize)
+
+ log_must diff $send_mnt/$recsize $recv_mnt/$recsize
+ log_must eval "zdb -ddddd $sendfs $send_obj >$tmpdir/send.zdb"
+ log_must eval "zdb -ddddd $recvfs $recv_obj >$tmpdir/recv.zdb"
+
+ grep -q "EMBEDDED" $tmpdir/send.zdb || \
+ log_fail "Obj $send_obj not embedded in $sendfs"
+ grep -q "EMBEDDED" $tmpdir/recv.zdb || \
+ log_fail "Obj $recv_obj not embedded in $recvfs"
+
+ cat $stream | zstreamdump -v | log_must grep -q \
+ "WRITE_EMBEDDED object = $send_obj offset = 0"
+done
+
+log_pass "Embedded blocks and redacted send work correctly together."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_holes.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_holes.ksh
new file mode 100755
index 000000000000..d111aa0ef608
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_holes.ksh
@@ -0,0 +1,120 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify redacted send streams reliably handle holes.
+#
+# Strategy:
+# 1. Holes written at the beginning and end of a non-sparse file in the
+# redacted list are correctly redacted.
+# 2. Holes written throughout a non-sparse file in the redacted list are
+# correctly redacted.
+# 3. Data written into a hole in a sparse file in the redacted list are
+# correctly redacted.
+# 4. Holes in metadata blocks.
+#
+
+typeset ds_name="holes"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name '' setup_holes
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+typeset M=$((1024 * 1024))
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+# Write holes at the start and end of a non-sparse file.
+if is_illumos; then
+ log_must mkholes -h 0:$M -h $((7 * M)):$M $clone_mnt/f1
+else
+ log_must dd if=/dev/zero of=$clone_mnt/f1 bs=1M count=1 conv=notrunc
+ log_must dd if=/dev/zero of=$clone_mnt/f1 bs=1M count=1 conv=notrunc seek=7
+fi
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book1 $clone@snap1
+log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f1" "$RANGE5"
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Write two overlapping sets of holes into the same non-sparse file.
+log_must stride_dd -i /dev/zero -o $clone_mnt/f1 -b $((128 * 1024)) -c 8 -s 2 -k 3
+log_must stride_dd -i /dev/zero -o $clone_mnt/f1 -b $((256 * 1024)) -c 8 -s 2 -k 6
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book2 $clone@snap1
+log_must eval "zfs send --redact book2 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f1" "$RANGE6"
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Write data into the middle of a hole.
+if is_illumos; then
+ log_must mkholes -d $((3 * M)):$((2 * M)) $clone_mnt/f2
+else
+ log_must dd if=/dev/urandom of=$clone_mnt/f2 bs=1M count=2 seek=3 \
+ conv=notrunc
+fi
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book3 $clone@snap1
+log_must eval "zfs send --redact book3 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f2" "$RANGE14"
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Remove a file with holes.
+log_must rm $clone_mnt/f3
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendfs@snap book4 $clone@snap1
+log_must eval "zfs send --redact book4 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f3" "$RANGE7"
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+# Create a hole in a L0 metadata block by removing files.
+log_must rm $send_mnt/manyrm_clone/f{32..96}
+log_must zfs snapshot $sendfs/manyrm_clone@snap1
+
+log_must zfs redact $sendfs/manyrm@snap book6 $sendfs/manyrm_clone@snap1
+log_must eval "zfs send --redact book6 $sendfs/manyrm@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+log_must mount_redacted -f $recvfs
+for i in {1..31} {97..256}; do
+ diff $send_mnt/manyrm/f$i $recv_mnt/f$i || log_fail \
+ "File f$i did not match in the send and recv datasets."
+done
+for i in {32..96}; do
+ file_size=$(stat_size $send_mnt/manyrm/f$i)
+ redacted_size=$(stat_size $recv_mnt/f$i)
+ [[ $file_size -eq $redacted_size ]] || log_fail \
+ "File f$i has size $file_size and redacted size $redacted_size"
+done
+log_must zfs rollback -R $clone@snap
+log_must zfs destroy -R $recvfs
+
+log_pass "Redacted send streams reliably handle holes."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_incrementals.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_incrementals.ksh
new file mode 100755
index 000000000000..1d2ed3a687be
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_incrementals.ksh
@@ -0,0 +1,152 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify that incrementals (redacted and normal) work with redacted datasets.
+#
+# Strategy:
+# 1. Test normal incrementals from the original snap to a subset of the
+# redaction list.
+# 2. Test receipt of intermediate clones, and their children.
+# 3. Test receipt with origin snap specified by '-o origin='.
+# 4. Test incrementals from redaction bookmarks.
+#
+
+typeset ds_name="incrementals"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name '' setup_incrementals
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+
+log_onexit redacted_cleanup $sendfs $recvfs $POOL2/rfs
+
+# Setup a redacted send using a redaction list at varying depth.
+log_must zfs redact $sendfs@snap0 book1 $POOL/rm@snap $POOL/stride3@snap \
+ $POOL/stride5@snap
+log_must eval "zfs send --redact book1 $sendfs@snap0 >$stream"
+log_must eval "zfs receive $POOL2/rfs <$stream"
+
+# Verify receipt of normal incrementals to redaction list members.
+log_must eval "zfs send -i $sendfs@snap0 $POOL/stride3@snap >$stream"
+log_must eval "zfs recv $POOL2/rstride3 <$stream"
+log_must diff -r /$POOL/stride3 /$POOL2/rstride3
+log_must eval "zfs send -i $sendfs@snap0 $POOL/stride5@snap >$stream"
+log_must eval "zfs recv $POOL2/rstride5 <$stream"
+log_must diff -r /$POOL/stride5 /$POOL2/rstride5
+
+# But not a normal child that we weren't redacted with respect to.
+log_must eval "zfs send -i $sendfs@snap0 $POOL/hole@snap >$stream"
+log_mustnot eval "zfs recv $POOL2/rhole@snap <$stream"
+
+# Verify we can receive an intermediate clone redacted with respect to a
+# subset of the original redaction list.
+log_must zfs redact $POOL/int@snap book2 $POOL/rm@snap
+log_must eval "zfs send -i $sendfs@snap0 --redact book2 $POOL/int@snap >$stream"
+log_must eval "zfs recv $POOL2/rint <$stream"
+compare_files $POOL/int $POOL2/rint "f1" "$RANGE0"
+compare_files $POOL/int $POOL2/rint "f2" "$RANGE15"
+compare_files $POOL/int $POOL2/rint "d1/f1" "$RANGE16"
+log_must mount_redacted -f $POOL2/rint
+
+# Verify we can receive grandchildren on the child.
+log_must eval "zfs send -i $POOL/int@snap $POOL/rm@snap >$stream"
+log_must eval "zfs receive $POOL2/rrm <$stream"
+log_must diff -r /$POOL/rm /$POOL2/rrm
+
+# But not a grandchild that the received child wasn't redacted with respect to.
+log_must eval "zfs send -i $POOL/int@snap $POOL/write@snap >$stream"
+log_mustnot eval "zfs recv $POOL2/rwrite<$stream"
+
+# Verify we cannot receive an intermediate clone that isn't redacted with
+# respect to a subset of the original redaction list.
+log_must zfs redact $POOL/int@snap book4 $POOL/rm@snap $POOL/write@snap
+log_must eval "zfs send -i $sendfs@snap0 --redact book4 $POOL/int@snap >$stream"
+log_mustnot eval "zfs recv $POOL2/rint <$stream"
+log_must zfs redact $POOL/int@snap book5 $POOL/write@snap
+log_must eval "zfs send -i $sendfs@snap0 --redact book5 $POOL/int@snap >$stream"
+log_mustnot eval "zfs recv $POOL2/rint <$stream"
+log_mustnot zfs redact $POOL/int@snap book6 $POOL/hole@snap
+
+# Verify we can receive a full clone of the grandchild on the child.
+log_must eval "zfs send $POOL/write@snap >$stream"
+log_must eval "zfs recv -o origin=$POOL2/rint@snap $POOL2/rwrite <$stream"
+log_must diff -r /$POOL/write /$POOL2/rwrite
+
+# Along with other origins.
+log_must eval "zfs recv -o origin=$POOL2/rfs@snap0 $POOL2/rwrite1 <$stream"
+log_must diff -r /$POOL/write /$POOL2/rwrite1
+log_must eval "zfs recv -o origin=$POOL2@init $POOL2/rwrite2 <$stream"
+log_must diff -r /$POOL/write /$POOL2/rwrite2
+log_must zfs destroy -R $POOL2/rwrite2
+
+log_must zfs destroy -R $POOL2/rfs
+
+# Write some data for tests of incremental sends from bookmarks
+log_must zfs snapshot $sendfs@snap1
+log_must zfs clone $sendfs@snap1 $POOL/hole1
+typeset mntpnt=$(get_prop mountpoint $POOL/hole1)
+log_must dd if=/dev/zero of=$mntpnt/f2 bs=128k count=16 conv=notrunc
+log_must zfs snapshot $POOL/hole1@snap
+log_must zfs clone $sendfs@snap1 $POOL/write1
+mntpnt=$(get_prop mountpoint $POOL/write1)
+log_must dd if=/dev/urandom of=$mntpnt/f2 bs=128k count=16 conv=notrunc
+log_must zfs snapshot $POOL/write1@snap
+log_must zfs clone $POOL/int@snap $POOL/write2
+mntpnt=$(get_prop mountpoint $POOL/write2)
+log_must dd if=/dev/urandom of=$mntpnt/f2 bs=128k count=16 conv=notrunc
+log_must zfs snapshot $POOL/write2@snap
+
+# Setup a redacted send using a redaction list at varying depth.
+log_must zfs redact $sendfs@snap0 book7 $POOL/rm@snap $POOL/stride3@snap \
+ $POOL/stride5@snap
+log_must eval "zfs send --redact book7 $sendfs@snap0 >$stream"
+log_must eval "zfs receive $POOL2/rfs <$stream"
+
+# Verify we can receive a redacted incremental sending from the bookmark.
+log_must zfs redact $sendfs@snap1 book8 $POOL/write1@snap
+log_must eval "zfs send -i $sendfs#book7 --redact book8 $sendfs@snap1 >$stream"
+log_must eval "zfs receive $POOL2/rfs <$stream"
+# The stride3 and stride5 snaps redact 3 128k blocks at block offsets 0 15 and
+# 30 of f2. The write1 snap only covers the first two of those three blocks.
+compare_files $sendfs $POOL2/rfs "f2" "$RANGE12"
+log_must mount_redacted -f $POOL2/rfs
+log_must diff $send_mnt/f1 /$POOL2/rfs/f1
+log_must diff $send_mnt/d1/f1 /$POOL2/rfs/d1/f1
+unmount_redacted $POOL2/rfs
+
+# Verify we can receive a normal child we weren't redacted with respect to by
+# sending from the bookmark.
+log_must eval "zfs send -i $sendfs#book7 $POOL/hole1@snap >$stream"
+log_must eval "zfs recv $POOL2/rhole1 <$stream"
+log_must diff -r /$POOL/hole1 /$POOL2/rhole1
+
+# Verify we can receive an intermediate clone redacted with respect to a
+# non-subset if we send from the bookmark.
+log_must zfs redact $POOL/int@snap book9 $POOL/write2@snap
+log_must eval "zfs send -i $sendfs#book7 --redact book9 $POOL/int@snap >$stream"
+log_must eval "zfs receive $POOL2/rint <$stream"
+compare_files $sendfs $POOL2/rint "f2" "$RANGE12"
+
+log_pass "Incrementals (redacted and normal) work with redacted datasets."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_largeblocks.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_largeblocks.ksh
new file mode 100755
index 000000000000..caccdd360061
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_largeblocks.ksh
@@ -0,0 +1,63 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify large blocks and redacted send work correctly together.
+#
+# Strategy:
+# 1. Create a dataset and clone with a 1m recordsize, modifying a few k
+# within the first 1m of a 16m file.
+# 2. Verify that the whole first 1m of the file is redacted.
+# 3. Receive an incremental stream from the original snap to the snap it
+# was redacted with respect to.
+# 4. Verify that the received dataset matches the clone
+#
+
+typeset ds_name="largeblocks"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name '-o recsize=1m'
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+log_must dd if=/dev/urandom of=$clone_mnt/f1 bs=32k count=3 seek=8 conv=notrunc
+log_must zfs snapshot $clone@snap1
+
+log_must zfs redact $sendfs@snap book1 $clone@snap1
+log_must eval "zfs send -L --redact book1 $sendfs@snap >$stream"
+log_must stream_has_features $stream redacted large_blocks
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f1" "$RANGE11"
+log_must mount_redacted -f $recvfs
+log_must diff $send_mnt/f2 $recv_mnt/f2
+unmount_redacted $recvfs
+
+log_must eval "zfs send -L -i $sendfs@snap $clone@snap1 >$stream"
+log_must stream_has_features $stream large_blocks
+log_must eval "zfs recv $recvfs/new <$stream"
+log_must diff -r $clone_mnt $recv_mnt/new
+
+log_pass "Large blocks and redacted send work correctly together."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh
new file mode 100755
index 000000000000..3386643b295e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_many_clones.ksh
@@ -0,0 +1,68 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify redacted send can deal with a large redaction list.
+#
+# Strategy:
+# 1. Create 64 clones of sendfs each of which modifies two blocks in a file.
+# The first modification is at an offset unique to each clone, and the
+# second (the last block in the file) is common to them all.
+# 2. Verify a redacted stream with a reasonable redaction list length can
+# be correctly processed.
+# 3. Verify that if the list is too long, the send fails gracefully.
+#
+
+typeset ds_name="many_clones"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name ''
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+typeset redaction_list=''
+typeset mntpnt
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+# Fill in both the last block, and a different block in every clone.
+for i in {1..64}; do
+ log_must zfs clone $sendfs@snap ${clone}$i
+ mntpnt=$(get_prop mountpoint ${clone}$i)
+ log_must dd if=/dev/urandom of=$mntpnt/f2 bs=64k count=1 seek=$i \
+ conv=notrunc
+ log_must dd if=/dev/urandom of=$mntpnt/f2 bs=64k count=1 seek=63 \
+ conv=notrunc
+ log_must zfs snapshot ${clone}$i@snap
+done
+
+# The limit isn't necessarily 32 snapshots. The maximum number of snapshots in
+# the redacted list is determined in dsl_bookmark_create_redacted_check().
+log_must zfs redact $sendfs@snap book1 $clone{1..32}@snap
+log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+compare_files $sendfs $recvfs "f2" "$RANGE8"
+
+log_mustnot zfs redact $sendfs@snap book2 $clone{1..64}@snap
+
+log_pass "Redacted send can deal with a large redaction list."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_mixed_recsize.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_mixed_recsize.ksh
new file mode 100755
index 000000000000..e1cd09e17d59
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_mixed_recsize.ksh
@@ -0,0 +1,77 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify redacted send works with datasets of different sizes.
+#
+# Strategy:
+# 1. Create two dataset one with recsize 512, and one 1m and create a 2m file.
+# 2. For each dataset, create clones of both 512 and 1m recsize and modify
+# the first 16k of the file.
+# 3. Send each original dataset, redacted with respect to each of the clones
+# into both a dataset inheriting a 512 recsize and a 1m one.
+# 4. Verify that the smallest unit of redaction is that of the origin fs.
+#
+
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+typeset mntpnt
+
+log_onexit redacted_cleanup $POOL/512 $POOL/1m $POOL2/512 $POOL2/1m
+
+# Set up the datasets we'll send and redact from.
+log_must zfs create -o recsize=512 $POOL/512
+mntpnt=$(get_prop mountpoint $POOL/512)
+log_must dd if=/dev/urandom of=$mntpnt/f1 bs=1024k count=2
+log_must zfs snapshot $POOL/512@snap
+log_must zfs clone -o recsize=1m $POOL/512@snap $POOL/1mclone
+mntpnt=$(get_prop mountpoint $POOL/1mclone)
+log_must dd if=/dev/urandom of=$mntpnt/f1 bs=512 count=32 conv=notrunc
+log_must zfs snapshot $POOL/1mclone@snap
+
+log_must zfs create -o recsize=1m $POOL/1m
+mntpnt=$(get_prop mountpoint $POOL/1m)
+log_must dd if=/dev/urandom of=$mntpnt/f1 bs=1024k count=2
+log_must zfs snapshot $POOL/1m@snap
+log_must zfs clone -o recsize=512 $POOL/1m@snap $POOL/512clone
+mntpnt=$(get_prop mountpoint $POOL/512clone)
+log_must dd if=/dev/urandom of=$mntpnt/f1 bs=512 count=32 conv=notrunc
+log_must zfs snapshot $POOL/512clone@snap
+
+# Create datasets that allow received datasets to inherit recordsize.
+log_must zfs create -o recsize=512 $POOL2/512
+log_must zfs create -o recsize=1m $POOL2/1m
+
+# Do the sends and verify the contents.
+log_must zfs redact $POOL/512@snap book1 $POOL/1mclone@snap
+log_must eval "zfs send --redact book1 $POOL/512@snap>$stream"
+log_must eval "zfs recv $POOL2/512/recva <$stream"
+compare_files $POOL/512 $POOL2/512/recva "f1" "$RANGE13"
+log_must eval "zfs recv $POOL2/1m/recvb <$stream"
+compare_files $POOL/512 $POOL2/1m/recvb "f1" "$RANGE13"
+
+log_must zfs redact $POOL/1m@snap book2 $POOL/512clone@snap
+log_must eval "zfs send --redact book2 $POOL/1m@snap >$stream"
+log_must eval "zfs recv $POOL2/512/recvc <$stream"
+compare_files $POOL/1m $POOL2/512/recvc "f1" "$RANGE11"
+log_must eval "zfs recv $POOL2/1m/recvd <$stream"
+compare_files $POOL/1m $POOL2/1m/recvd "f1" "$RANGE11"
+
+log_pass "Redaction works correctly with different recordsizes."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_mounts.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_mounts.ksh
new file mode 100755
index 000000000000..0bc4bf461747
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_mounts.ksh
@@ -0,0 +1,109 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify that received redacted datasets are not mounted by default, but
+# can still be mounted after setting ALLOW_REDACTED_DATASET_MOUNT.
+#
+# Strategy:
+# 1. Verify a received redacted stream isn't mounted by default.
+# 2. Set ALLOW_REDACTED_DATASET_MOUNT and verify it can't be mounted
+# without the -f flag, but can with -f.
+# 3. Receive a redacted volume.
+# 4. Verify the device file isn't present until the kernel variable is set.
+# 5. Verify the files in the send fs are also present in the recv fs.
+#
+
+typeset ds_name="mounts"
+typeset sendfs="$POOL/$ds_name"
+typeset sendvol="$sendfs/vol"
+typeset recvfs="$POOL2/$ds_name"
+typeset recvvol="$POOL2/vol"
+typeset clone="$POOL/${ds_name}_clone"
+typeset clonevol="${sendvol}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name '' setup_mounts
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+typeset recv_vol_file="/dev/zvol/$recvvol"
+
+log_onexit redacted_cleanup $sendfs $recvfs $recvvol
+
+log_must rm $clone_mnt/empty $clone_mnt/contents1
+log_must dd if=/dev/urandom of=$clone_mnt/contents2 bs=512 count=1 conv=notrunc
+log_must rm $clone_mnt/dir1/contents1
+log_must rm -rf $clone_mnt/dir1/dir2
+log_must dd if=/dev/urandom of=$clone_mnt/dir1/contents2 bs=512 count=1 \
+ conv=notrunc
+log_must dd if=/dev/urandom of=$clone_mnt/dir1/empty bs=512 count=1
+log_must zfs snapshot $clone@snap1
+
+log_must zfs redact $sendfs@snap book1 $clone@snap
+log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
+log_must eval "zfs receive $recvfs <$stream"
+log_mustnot ismounted $recvfs
+log_mustnot mount_redacted $recvfs
+log_mustnot ismounted $recvfs
+log_must mount_redacted -f $recvfs
+log_must ismounted $recvfs
+
+# Verify that the send and recv fs both have the same files under their
+# mountpoints by comparing find output with the name of the mountpoint
+# deleted.
+contents=$(log_must find $recv_mnt)
+contents_orig=$(log_must find $send_mnt)
+log_must diff <(echo ${contents//$recv_mnt/}) \
+ <(echo ${contents_orig//$send_mnt/})
+log_must zfs redact $sendvol@snap book2 $clonevol@snap
+log_must eval "zfs send --redact book2 $sendvol@snap >$stream"
+log_must eval "zfs receive $recvvol <$stream"
+is_disk_device $recv_vol_file && log_fail "Volume device file should not exist."
+log_must set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 1
+log_must zpool export $POOL2
+log_must zpool import $POOL2
+udevadm settle
+
+# The device file isn't guaranteed to show up right away.
+if ! is_disk_device $recv_vol_file; then
+ udevadm settle
+ for t in 10 5 3 2 1; do
+ log_note "Polling $t seconds for device file."
+ udevadm settle
+ sleep $t
+ is_disk_device $recv_vol_file && break
+ done
+fi
+is_disk_device $recv_vol_file || log_fail "Volume device file should exist."
+
+log_must dd if=/dev/urandom of=$send_mnt/dir1/contents1 bs=512 count=2
+log_must rm $send_mnt/dir1/dir2/empty
+log_must zfs snapshot $sendfs@snap2
+log_must eval "zfs send -i $sendfs#book1 $sendfs@snap2 >$stream"
+log_must eval "zfs receive $recvfs <$stream"
+log_must mount_redacted -f $recvfs
+log_must ismounted $recvfs
+contents=$(log_must find $recv_mnt)
+contents_orig=$(log_must find $send_mnt)
+log_must diff <(echo ${contents//$recv_mnt/}) \
+ <(echo ${contents_orig//$send_mnt/})
+
+log_pass "Received redacted streams can be mounted."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_negative.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_negative.ksh
new file mode 100755
index 000000000000..56b990be1bee
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_negative.ksh
@@ -0,0 +1,92 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Test that redacted send correctly detects invalid arguments.
+#
+
+typeset sendfs="$POOL2/sendfs"
+typeset recvfs="$POOL2/recvfs"
+typeset clone1="$POOL2/clone1"
+typeset clone2="$POOL2/clone2"
+typeset clone3="$POOL2/clone3"
+typeset clone3="$POOL2/clone4"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+
+log_onexit redacted_cleanup $sendfs $recvfs $clone3
+
+log_must zfs create $sendfs
+log_must zfs snapshot $sendfs@snap1
+log_must zfs snapshot $sendfs@snap2
+log_must zfs snapshot $sendfs@snap3
+log_must zfs clone $sendfs@snap2 $clone1
+log_must zfs snapshot $clone1@snap
+log_must zfs bookmark $clone1@snap $clone1#book
+log_must zfs clone $sendfs@snap2 $clone2
+log_must zfs snapshot $clone2@snap
+
+# Incompatible flags
+log_must zfs redact $sendfs@snap2 book $clone1@snap
+log_mustnot eval "zfs send -R --redact book $sendfs@snap2 >/dev/null"
+
+typeset arg
+for arg in "$sendfs" "$clone1#book"; do
+ log_mustnot eval "zfs send --redact book $arg >/dev/null"
+done
+
+# Bad redaction list arguments
+log_mustnot zfs redact $sendfs@snap1
+log_mustnot zfs redact $sendfs@snap1 book
+log_mustnot zfs redact $sendfs#book1 book4 $clone1
+log_mustnot eval "zfs send --redact $sendfs#book $sendfs@snap >/dev/null"
+
+# Redaction snapshots not a descendant of tosnap
+log_mustnot zfs redact $sendfs@snap2 book $sendfs@snap2
+log_must zfs redact $sendfs@snap2 book2 $clone1@snap $clone2@snap
+log_must eval "zfs send --redact book2 $sendfs@snap2 >$stream"
+log_must zfs redact $sendfs@snap2 book3 $clone1@snap $clone2@snap
+log_must eval "zfs send -i $sendfs@snap1 --redact book3 $sendfs@snap2 \
+ >/dev/null"
+log_mustnot zfs redact $sendfs@snap3 $sendfs@snap3 $clone1@snap
+
+# Full redacted sends of redacted datasets are not allowed.
+log_must eval "zfs recv $recvfs <$stream"
+log_must zfs snapshot $recvfs@snap
+log_must zfs clone $recvfs@snap $clone3
+log_must zfs snapshot $clone3@snap
+log_mustnot zfs redact $recvfs@snap book5 $clone3@snap
+
+# Nor may a redacted dataset appear in the redaction list.
+log_mustnot zfs redact testpool2/recvfs@snap2 book7 testpool2/recvfs@snap
+
+# Non-redaction bookmark cannot be sent and produces invalid argument error
+log_must zfs bookmark "$sendfs@snap1" "$sendfs#book8"
+log_must eval "zfs send --redact book8 -i $sendfs@snap1 $sendfs@snap2 2>&1 | head -n 100 | grep 'not a redaction bookmark'"
+
+# Error messages for common usage errors
+log_mustnot_expect "not contain '#'" zfs redact $sendfs@snap1 \#book $sendfs@snap2
+log_mustnot_expect "not contain '#'" zfs redact $sendfs@snap1 $sendfs#book $sendfs@snap2
+log_mustnot_expect "full dataset names" zfs redact $sendfs@snap1 book @snap2
+log_mustnot_expect "full dataset names" zfs redact $sendfs@snap1 book @snap2
+log_mustnot_expect "full dataset names" zfs redact $sendfs@snap1 \#book @snap2
+log_mustnot_expect "descendent of snapshot" zfs redact $sendfs@snap2 book $sendfs@snap1
+
+log_pass "Verify that redacted send correctly detects invalid arguments."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_origin.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_origin.ksh
new file mode 100755
index 000000000000..74e5914f2d88
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_origin.ksh
@@ -0,0 +1,87 @@
+#!/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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Test that receiving sends from redaction bookmarks and redacted datasets
+# works correctly in certain edge cases.
+# 1. Send A(B,C,D) to pool2.
+# 2. Verify send from A(B, C, D) can be received onto it.
+# 3. Verify send from A(B, C) can be received onto it.
+# 4. Verify send from A() can be received onto it.
+# 5. Verify send from A(E) cannot be received onto it.
+# 6. Verify send from redaction bookmark for A(B, C) can be received onto it.
+# 7. Verify send from redaction bookmark for A() can be received onto it.
+# 8. Verify send from redaction bookmark for A(E) cannot be received onto it.
+#
+
+typeset ds_name="origin"
+typeset sendfs="$POOL/$ds_name"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name '' setup_incrementals
+typeset dsA=$sendfs@snap0
+typeset dsB=$POOL/hole@snap
+typeset dsC=$POOL/rm@snap
+typeset dsD=$POOL/write@snap
+typeset dsE=$POOL/stride3@snap
+typeset dsF=$POOL/stride5@snap
+typeset targ=$POOL2/targfs@snap
+
+log_onexit redacted_cleanup $sendfs $POOL2/rBCD $POOL2/targfs \
+ $POOL2/rBC $POOL2/rE
+
+# Set up all the filesystems and clones.
+log_must zfs redact $dsA BCD $dsB $dsC $dsD
+log_must eval "zfs send --redact BCD $dsA >$stream"
+log_must eval "zfs receive $POOL2/rBCD <$stream"
+log_must eval "zfs receive $targ <$stream"
+
+log_must zfs redact $dsA BC $dsB $dsC
+log_must eval "zfs send --redact BC $dsA >$stream"
+log_must eval "zfs receive $POOL2/rBC <$stream"
+
+log_must zfs redact $dsA E $dsE
+log_must eval "zfs send --redact E $dsA >$stream"
+log_must eval "zfs receive $POOL2/rE <$stream"
+
+log_must eval "zfs send $dsF >$stream"
+log_must eval "zfs receive -o origin=$POOL2/rBCD@snap0 $POOL2/BCDrF <$stream"
+log_must eval "zfs receive -o origin=$POOL2/rBC@snap0 $POOL2/BCrF <$stream"
+log_must eval "zfs receive -o origin=$POOL2/rE@snap0 $POOL2/ErF <$stream"
+
+# Run tests from redacted datasets.
+log_must eval "zfs send -i $POOL2/rBCD@snap0 $POOL2/BCDrF@snap >$stream"
+log_must eval "zfs receive -o origin=$targ $POOL2/tdBCD <$stream"
+
+log_must eval "zfs send -i $POOL2/rBC@snap0 $POOL2/BCrF@snap >$stream"
+log_must eval "zfs receive -o origin=$targ $POOL2/tdBC <$stream"
+
+log_must eval "zfs send -i $POOL2/rE@snap0 $POOL2/ErF@snap >$stream"
+log_mustnot eval "zfs receive -o origin=$targ $POOL2/tdE <$stream"
+
+# Run tests from redaction bookmarks.
+log_must eval "zfs send -i $sendfs#BC $dsF >$stream"
+log_must eval "zfs receive -o origin=$targ $POOL2/tbBC <$stream"
+
+log_must eval "zfs send -i $sendfs#E $dsF >$stream"
+log_mustnot eval "zfs receive -o origin=$targ $POOL2/tbE <$stream"
+
+log_pass "Verify sends from redacted datasets and bookmarks work correctly."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_props.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_props.ksh
new file mode 100755
index 000000000000..e4163c4ef8da
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_props.ksh
@@ -0,0 +1,77 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify the list of redacted snapshot guids as properties.
+#
+# Strategy:
+# 1. Create a redacted dataset and receive it into another pool.
+# 2. Verify that the redaction list in the book mark (according to zdb)
+# matches the list shown in the redact_snaps property.
+# 3. Verify that the received snapshot has a matching redaction list.
+#
+
+typeset ds_name="props"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name ''
+typeset mntpnt
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+# Verify a plain dataset, snapshot or bookmark has an empty list.
+log_must zfs snapshot $sendfs@empty_snapshot
+log_must zfs bookmark $sendfs@empty_snapshot $sendfs#empty_bookmark
+found_list=$(get_prop redact_snaps $sendfs)
+[[ $found_list = "-" ]] || log_fail "Unexpected dataset list: $found_list"
+found_list=$(get_prop redact_snaps $sendfs@empty_snapshot)
+[[ $found_list = "-" ]] || log_fail "Unexpected snapshot list: $found_list"
+found_list=$(get_prop redact_snaps $sendfs#empty_bookmark)
+[[ $found_list = "-" ]] || log_fail "Unexpected bookmark list: $found_list"
+
+# Fill in a different block in every clone.
+for i in {1..16}; do
+ log_must zfs clone $sendfs@snap ${clone}$i
+ mntpnt=$(get_prop mountpoint ${clone}$i)
+ log_must dd if=/dev/urandom of=$mntpnt/f2 bs=64k count=1 seek=$i \
+ conv=notrunc
+ log_must zfs snapshot ${clone}$i@snap
+done
+
+log_must zfs redact $sendfs@snap book1 $clone{1..16}@snap
+log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
+log_must eval "zfs recv $recvfs <$stream"
+
+get_guid_list $tmpdir/prop_list $sendfs#book1
+get_guid_list $tmpdir/zdb_list $sendfs#book1 true
+get_guid_list $tmpdir/recvd_prop_list $recvfs@snap
+
+count=$(wc -l $tmpdir/prop_list | awk '{print $1}')
+[[ $count -eq 16 ]] || log_fail "Found incorrect number of redaction snapshots."
+
+diff $tmpdir/prop_list $tmpdir/zdb_list || \
+ log_fail "Property list differed from zdb output"
+diff $tmpdir/prop_list $tmpdir/recvd_prop_list || \
+ log_fail "Received property list differed from sent"
+
+log_pass "The redaction list is consistent between sent and received datasets."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_resume.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_resume.ksh
new file mode 100755
index 000000000000..8118ea59ec8b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_resume.ksh
@@ -0,0 +1,88 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify that resumable send works correctly with redacted streams.
+#
+# Strategy:
+# 1. Do a full redacted resumable send.
+# 2. Verify the received contents are correct.
+# 3. Do an incremental redacted resumable send.
+# 4. Verify the received contents are correct.
+# 5. Verify that recv -A removes a partially received dataset.
+#
+
+typeset ds_name="resume"
+typeset sendfs="$POOL/$ds_name"
+typeset recvfs="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset clone1="$POOL/${ds_name}_clone1"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+setup_dataset $ds_name ''
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+typeset send_mnt="$(get_prop mountpoint $sendfs)"
+typeset recv_mnt="/$POOL2/$ds_name"
+
+log_onexit redacted_cleanup $sendfs $recvfs
+
+log_must stride_dd -i /dev/urandom -o $clone_mnt/f2 -b 512 -c 64 -s 512
+log_must zfs snapshot $clone@snap1
+
+# Do the full resumable send
+log_must zfs redact $sendfs@snap book1 $clone@snap1
+resume_test "zfs send --redact book1 $sendfs@snap" $tmpdir $recvfs
+log_must mount_redacted -f $recvfs
+log_must set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 1
+log_must diff $send_mnt/f1 $recv_mnt/f1
+log_must eval "get_diff $send_mnt/f2 $recv_mnt/f2 >$tmpdir/get_diff.out"
+typeset range=$(cat $tmpdir/get_diff.out)
+[[ "$RANGE9" = "$range" ]] || log_fail "Unexpected range: $range"
+
+log_must dd if=/dev/urandom of=$send_mnt/f3 bs=1024k count=3
+log_must zfs snapshot $sendfs@snap2
+log_must zfs clone $sendfs@snap2 $clone1
+typeset clone1_mnt="$(get_prop mountpoint $clone1)"
+log_must dd if=/dev/urandom of=$clone1_mnt/f3 bs=128k count=3 conv=notrunc
+log_must zfs snapshot $clone1@snap
+
+# Do the incremental resumable send
+log_must zfs redact $sendfs@snap2 book2 $clone1@snap
+resume_test "zfs send --redact book2 -i $sendfs#book1 $sendfs@snap2" \
+ $tmpdir $recvfs
+log_must diff $send_mnt/f1 $recv_mnt/f1
+log_must diff $send_mnt/f2 $recv_mnt/f2
+log_must eval "get_diff $send_mnt/f3 $recv_mnt/f3 >$tmpdir/get_diff.out"
+range=$(cat $tmpdir/get_diff.out)
+[[ "$RANGE10" = "$range" ]] || log_fail "Unexpected range: $range"
+
+# Test recv -A works properly and verify saved sends are not allowed
+log_mustnot zfs recv -A $recvfs
+log_must zfs destroy -R $recvfs
+log_mustnot zfs recv -A $recvfs
+log_must eval "zfs send --redact book1 $sendfs@snap >$stream"
+dd if=$stream bs=64k count=1 | log_mustnot zfs receive -s $recvfs
+[[ "-" = $(get_prop receive_resume_token $recvfs) ]] && \
+ log_fail "Receive token not found."
+log_mustnot eval "zfs send --saved --redact book1 $recvfs > /dev/null"
+log_must zfs recv -A $recvfs
+log_must datasetnonexists $recvfs
+
+log_pass "Resumable send works correctly with redacted streams."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_size.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_size.ksh
new file mode 100755
index 000000000000..7456084b04bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_size.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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify that send size estimates of redacted sends work correctly
+#
+# Strategy:
+# 1. Perform a redacted send with -nv and without, and verify the
+# size estimate is the same as the size of the actual send.
+# 2. Receive an incremental send from the redaction bookmark with
+# -nv and without, and verify the size estimate is the same as
+# the size of the actual send.
+#
+
+ds_name="sizes"
+typeset sendfs="$POOL/$ds_name"
+typeset clone="$POOL/${ds_name}_clone2"
+setup_dataset $ds_name "-o compress=lz4"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset size=$(mktemp $tmpdir/size.XXXX)
+typeset size2=$(mktemp $tmpdir/size.XXXX)
+
+log_onexit redacted_cleanup $sendfs $clone
+log_must zfs clone $sendfs@snap $clone
+typeset clone_mnt="$(get_prop mountpoint $clone)"
+log_must rm -rf $clone_mnt/*
+log_must zfs snapshot $clone@snap
+log_must zfs redact $sendfs@snap book $clone@snap
+log_must eval "zfs send -nvP --redact book $sendfs@snap | \
+ grep '^size' | awk '{print \$2}' >$size"
+log_must eval "zfs send --redact book $sendfs@snap | wc -c \
+ >$size2"
+bytes1=$(cat $size | tr -d '[[:space:]]')
+bytes2=$(cat $size2 | tr -d '[[:space:]]')
+[[ "$bytes1" -eq "$bytes2" ]] || \
+ log_fail "Full sizes differ: estimate $bytes1 and actual $bytes2"
+
+log_must zfs snapshot $sendfs@snap2
+log_must eval "zfs send -nvP -i $sendfs#book $sendfs@snap2 | \
+ grep '^size' | awk '{print \$2}' >$size"
+log_must eval "zfs send -i $sendfs#book $sendfs@snap2 | wc -c >$size2"
+bytes1=$(cat $size | tr -d '[[:space:]]')
+bytes2=$(cat $size2 | tr -d '[[:space:]]')
+[[ "$bytes1" -eq "$bytes2" ]] || \
+ log_fail "Incremental sizes differ: estimate $bytes1 and actual $bytes2"
+
+log_pass "Size estimates of redacted sends estimate accurately."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/redacted_volume.ksh b/tests/zfs-tests/tests/functional/redacted_send/redacted_volume.ksh
new file mode 100755
index 000000000000..2ea10638ce31
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/redacted_volume.ksh
@@ -0,0 +1,105 @@
+#!/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.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+#
+# Description:
+# Verify that redacted send works on volumes.
+#
+# Strategy:
+# 1. Write to a volume, then make a clone of that volume.
+# 2. Receive a redacted stream that sends all blocks.
+# 3. Receive a redacted stream that redacts the first half of the written area.
+#
+
+typeset ds_name="volume"
+typeset sendvol="$POOL/$ds_name"
+typeset recvvol="$POOL2/$ds_name"
+typeset clone="$POOL/${ds_name}_clone"
+typeset tmpdir="$(get_prop mountpoint $POOL)/tmp"
+typeset stream=$(mktemp $tmpdir/stream.XXXX)
+typeset send_file="/dev/zvol/$sendvol"
+typeset recv_file="/dev/zvol/$recvvol"
+typeset clone_file="/dev/zvol/$clone"
+
+log_onexit redacted_cleanup $sendvol $recvvol
+
+log_must zfs create -b 8k -V 1g $sendvol
+sleep 10
+log_must zpool export $POOL
+log_must zpool import $POOL
+udevadm settle
+if ! is_disk_device $send_file; then
+ udevadm settle
+ for t in 10 5 3 2 1; do
+ log_note "Polling $t seconds for device file."
+ udevadm settle
+ sleep $t
+ is_disk_device $send_file && break
+ done
+fi
+log_must dd if=/dev/urandom of=$send_file bs=8k count=64
+log_must zfs snapshot $sendvol@snap
+log_must zfs clone $sendvol@snap $clone
+log_must zfs snapshot $clone@snap
+
+log_must set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 1
+log_must zfs redact $sendvol@snap book1 $clone@snap
+log_must eval "zfs send --redact book1 $sendvol@snap >$stream"
+log_must eval "zfs recv $recvvol <$stream"
+sleep 10
+log_must zpool export $POOL2
+log_must zpool import $POOL2
+udevadm settle
+if ! is_disk_device $recv_file; then
+ udevadm settle
+ for t in 10 5 3 2 1; do
+ log_note "Polling $t seconds for device file."
+ udevadm settle
+ sleep $t
+ is_disk_device $recv_file && break
+ done
+fi
+log_must dd if=$send_file of=$tmpdir/send.dd bs=8k count=64
+log_must dd if=$recv_file of=$tmpdir/recv.dd bs=8k count=64
+log_must diff $tmpdir/send.dd $tmpdir/recv.dd
+log_must zfs destroy -R $recvvol
+
+log_must dd if=/dev/urandom of=$clone_file bs=8k count=32
+log_must zfs snapshot $clone@snap1
+log_must zfs redact $sendvol@snap book2 $clone@snap1
+log_must eval "zfs send --redact book2 $sendvol@snap >$stream"
+log_must eval "zfs recv $recvvol <$stream"
+sleep 10
+log_must zpool export $POOL2
+log_must zpool import $POOL2
+udevadm settle
+if ! is_disk_device $recv_file; then
+ udevadm settle
+ for t in 10 5 3 2 1; do
+ log_note "Polling $t seconds for device file."
+ udevadm settle
+ sleep $t
+ is_disk_device $recv_file && break
+ done
+fi
+log_must dd if=$send_file of=$tmpdir/send.dd bs=8k count=32 skip=32
+log_must dd if=$recv_file of=$tmpdir/recv.dd bs=8k count=32 skip=32
+log_must diff $tmpdir/send.dd $tmpdir/recv.dd
+
+log_pass "Redacted send works correctly with volumes."
diff --git a/tests/zfs-tests/tests/functional/redacted_send/setup.ksh b/tests/zfs-tests/tests/functional/redacted_send/setup.ksh
new file mode 100755
index 000000000000..3f537f813db0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redacted_send/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 (c) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/redacted_send/redacted.kshlib
+
+verify_disk_count "$DISKS" 2
+
+create_pool $POOL $DISK1
+log_must zfs snapshot $POOL@init
+create_pool $POOL2 $DISK2
+log_must zfs snapshot $POOL2@init
+log_must zfs create $POOL/tmp
+log_pass
diff --git a/tests/zfs-tests/tests/functional/redundancy/Makefile.am b/tests/zfs-tests/tests/functional/redundancy/Makefile.am
new file mode 100644
index 000000000000..6f6cc405b9bf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/redundancy
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ redundancy_001_pos.ksh \
+ redundancy_002_pos.ksh \
+ redundancy_003_pos.ksh \
+ redundancy_004_neg.ksh
+
+dist_pkgdata_DATA = \
+ redundancy.cfg \
+ redundancy.kshlib
diff --git a/tests/zfs-tests/tests/functional/redundancy/cleanup.ksh b/tests/zfs-tests/tests/functional/redundancy/cleanup.ksh
new file mode 100755
index 000000000000..ba8d980710ee
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/redundancy/redundancy.kshlib
+
+verify_runnable "global"
+
+cleanup
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy.cfg b/tests/zfs-tests/tests/functional/redundancy/redundancy.cfg
new file mode 100644
index 000000000000..37b93820bc1d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy.cfg
@@ -0,0 +1,38 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2015 by Delphix. All rights reserved.
+#
+
+export BASEDIR=$TEST_BASE_DIR/basedir.$$
+export TESTFILE=testfile.$$
+
+export PRE_RECORD_FILE=$BASEDIR/pre-record-file.$$
+export PST_RECORD_FILE=$BASEDIR/pst-record-file.$$
+
+export BLOCKSZ=$(( 1024 * 1024 ))
+export NUM_WRITES=40
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib b/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
new file mode 100644
index 000000000000..9bf2df0d1368
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib
@@ -0,0 +1,335 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/redundancy/redundancy.cfg
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+ typeset dir
+ for dir in $TESTDIR $BASEDIR; do
+ if [[ -d $dir ]]; then
+ log_must rm -rf $dir
+ fi
+ done
+}
+
+#
+# Get random number between min and max number.
+#
+# $1 Minimal value
+# $2 Maximal value
+#
+function random
+{
+ typeset -i min=$1
+ typeset -i max=$2
+ typeset -i value
+
+ while true; do
+ ((value = RANDOM % (max + 1)))
+ if ((value >= min)); then
+ break
+ fi
+ done
+
+ echo $value
+}
+
+#
+# Record the directories construction and checksum all the files which reside
+# within the specified pool
+#
+# $1 The specified pool
+# $2 The file which save the record.
+#
+function record_data
+{
+ typeset pool=$1
+ typeset recordfile=$2
+
+ [[ -z $pool ]] && log_fail "No specified pool."
+ [[ -f $recordfile ]] && log_must rm -f $recordfile
+
+ typeset mntpnt
+ mntpnt=$(get_prop mountpoint $pool)
+ log_must eval "du -a $mntpnt > $recordfile 2>&1"
+ #
+ # When the data was damaged, checksum is failing and return 1
+ # So, will not use log_must
+ #
+ find $mntpnt -type f -exec cksum {} + >> $recordfile 2>&1
+}
+
+#
+# Create test pool and fill with files and directories.
+#
+# $1 pool name
+# $2 pool type
+# $3 virtual devices number
+#
+function setup_test_env
+{
+ typeset pool=$1
+ typeset keyword=$2
+ typeset -i vdev_cnt=$3
+ typeset vdevs
+
+ typeset -i i=0
+ while (( i < vdev_cnt )); do
+ vdevs="$vdevs $BASEDIR/vdev$i"
+ ((i += 1))
+ done
+
+ if [[ ! -d $BASEDIR ]]; then
+ log_must mkdir $BASEDIR
+ fi
+
+ if poolexists $pool ; then
+ destroy_pool $pool
+ fi
+
+ log_must mkfile $MINVDEVSIZE $vdevs
+
+ log_must zpool create -m $TESTDIR $pool $keyword $vdevs
+
+ log_note "Filling up the filesystem ..."
+ typeset -i ret=0
+ typeset -i i=0
+ typeset file=$TESTDIR/file
+ while true ; do
+ file_write -o create -f $file.$i \
+ -b $BLOCKSZ -c $NUM_WRITES
+ ret=$?
+ (( $ret != 0 )) && break
+ (( i = i + 1 ))
+ done
+ (($ret != 28 )) && log_note "file_write return value($ret) is unexpected."
+
+ record_data $TESTPOOL $PRE_RECORD_FILE
+}
+
+#
+# Check pool status is healthy
+#
+# $1 pool
+#
+function is_healthy
+{
+ typeset pool=$1
+
+ typeset healthy_output="pool '$pool' is healthy"
+ typeset real_output=$(zpool status -x $pool)
+
+ if [[ "$real_output" == "$healthy_output" ]]; then
+ return 0
+ else
+ typeset -i ret
+ zpool status -x $pool | grep "state:" | \
+ grep "FAULTED" >/dev/null 2>&1
+ ret=$?
+ (( $ret == 0 )) && return 1
+ typeset l_scan
+ typeset errnum
+ l_scan=$(zpool status -x $pool | grep "scan:")
+ l_scan=${l_scan##*"with"}
+ errnum=$(echo $l_scan | awk '{print $1}')
+
+ return $errnum
+ fi
+}
+
+#
+# Check pool data is valid
+#
+# $1 pool
+#
+function is_data_valid
+{
+ typeset pool=$1
+
+ record_data $pool $PST_RECORD_FILE
+ if ! diff $PRE_RECORD_FILE $PST_RECORD_FILE > /dev/null 2>&1; then
+ return 1
+ fi
+
+ return 0
+}
+
+#
+# Get the specified count devices name
+#
+# $1 pool name
+# $2 devices count
+#
+function get_vdevs #pool cnt
+{
+ typeset pool=$1
+ typeset -i cnt=$2
+
+ typeset all_devs=$(zpool iostat -v $pool | awk '{print $1}'| \
+ egrep -v "^pool$|^capacity$|^mirror$|^raidz1$|^raidz2$|---" | \
+ egrep -v "/old$|^$pool$")
+ typeset -i i=0
+ typeset vdevs
+ while ((i < cnt)); do
+ typeset dev=$(echo $all_devs | awk '{print $1}')
+ eval all_devs=\${all_devs##*$dev}
+
+ vdevs="$dev $vdevs"
+ ((i += 1))
+ done
+
+ echo "$vdevs"
+}
+
+#
+# Create and replace the same name virtual device files
+#
+# $1 pool name
+# $2-n virtual device files
+#
+function replace_missing_devs
+{
+ typeset pool=$1
+ shift
+
+ typeset vdev
+ for vdev in $@; do
+ log_must gnudd if=/dev/zero of=$vdev \
+ bs=1024k count=$(($MINDEVSIZE / (1024 * 1024))) \
+ oflag=fdatasync
+ log_must zpool replace -wf $pool $vdev $vdev
+ done
+}
+
+#
+# Damage the pool's virtual device files.
+#
+# $1 pool name
+# $2 Failing devices count
+# $3 damage vdevs method, if not null, we keep
+# the label for the vdevs
+#
+function damage_devs
+{
+ typeset pool=$1
+ typeset -i cnt=$2
+ typeset label="$3"
+ typeset vdevs
+ typeset -i bs_count=$((64 * 1024))
+
+ vdevs=$(get_vdevs $pool $cnt)
+ typeset dev
+ if [[ -n $label ]]; then
+ for dev in $vdevs; do
+ dd if=/dev/zero of=$dev seek=512 bs=1024 \
+ count=$bs_count conv=notrunc >/dev/null 2>&1
+ done
+ else
+ for dev in $vdevs; do
+ dd if=/dev/zero of=$dev bs=1024 count=$bs_count \
+ conv=notrunc >/dev/null 2>&1
+ done
+ fi
+
+ sync_pool $pool
+}
+
+#
+# Clear errors in the pool caused by data corruptions
+#
+# $1 pool name
+#
+function clear_errors
+{
+ typeset pool=$1
+
+ log_must zpool clear $pool
+
+ if ! is_healthy $pool ; then
+ log_note "$pool should be healthy."
+ return 1
+ fi
+ if ! is_data_valid $pool ; then
+ log_note "Data should be valid in $pool."
+ return 1
+ fi
+
+ return 0
+}
+
+#
+# Remove the specified pool's virtual device files
+#
+# $1 Pool name
+# $2 Missing devices count
+#
+function remove_devs
+{
+ typeset pool=$1
+ typeset -i cnt=$2
+ typeset vdevs
+
+ vdevs=$(get_vdevs $pool $cnt)
+ log_must rm -f $vdevs
+
+ sync_pool $pool
+}
+
+#
+# Recover the bad or missing device files in the pool
+#
+# $1 Pool name
+# $2 Missing devices count
+#
+function recover_bad_missing_devs
+{
+ typeset pool=$1
+ typeset -i cnt=$2
+ typeset vdevs
+
+ vdevs=$(get_vdevs $pool $cnt)
+ replace_missing_devs $pool $vdevs
+
+ if ! is_healthy $pool ; then
+ log_note "$pool should be healthy."
+ return 1
+ fi
+ if ! is_data_valid $pool ; then
+ log_note "Data should be valid in $pool."
+ return 1
+ fi
+
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_001_pos.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_001_pos.ksh
new file mode 100755
index 000000000000..90d14f60017b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/redundancy/redundancy.kshlib
+
+#
+# DESCRIPTION:
+# A raidz pool can withstand at most 1 device failing or missing.
+#
+# STRATEGY:
+# 1. Create N(>2,<5) virtual disk files.
+# 2. Create raidz pool based on the virtual disk files.
+# 3. Fill the filesystem with directories and files.
+# 4. Record all the files and directories checksum information.
+# 5. Damaged one of the virtual disk file.
+# 6. Verify the data is correct to prove raidz can withstand 1 device is
+# failing.
+#
+
+verify_runnable "global"
+
+log_assert "Verify raidz pool can withstand one device is failing."
+log_onexit cleanup
+
+typeset -i cnt=$(random_int_between 2 5)
+setup_test_env $TESTPOOL raidz $cnt
+
+#
+# Inject data corruption error for raidz pool
+#
+damage_devs $TESTPOOL 1 "label"
+log_must is_data_valid $TESTPOOL
+log_must clear_errors $TESTPOOL
+
+#
+# Inject bad device error for raidz pool
+#
+damage_devs $TESTPOOL 1
+log_must is_data_valid $TESTPOOL
+log_must recover_bad_missing_devs $TESTPOOL 1
+
+#
+# Inject missing device error for raidz pool
+#
+remove_devs $TESTPOOL 1
+log_must is_data_valid $TESTPOOL
+
+log_pass "Raidz pool can withstand one devices is failing passed."
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_002_pos.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_002_pos.ksh
new file mode 100755
index 000000000000..74bda19990e3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_002_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/redundancy/redundancy.kshlib
+
+#
+# DESCRIPTION:
+# A raidz2 pool can withstand 2 devices are failing or missing.
+#
+# STRATEGY:
+# 1. Create N(>3,<5) virtual disk files.
+# 2. Create raidz2 pool based on the virtual disk files.
+# 3. Fill the filesystem with directories and files.
+# 4. Record all the files and directories checksum information.
+# 5. Damaged at most two of the virtual disk files.
+# 6. Verify the data is correct to prove raidz2 can withstand 2 devices
+# are failing.
+#
+
+verify_runnable "global"
+
+log_assert "Verify raidz2 pool can withstand two devices are failing."
+log_onexit cleanup
+
+typeset -i cnt=$(random_int_between 3 5)
+setup_test_env $TESTPOOL raidz2 $cnt
+
+#
+# Inject data corruption errors for raidz2 pool
+#
+for i in 1 2; do
+ damage_devs $TESTPOOL $i "label"
+ log_must is_data_valid $TESTPOOL
+ log_must clear_errors $TESTPOOL
+done
+
+#
+# Inject bad devices errors for raidz2 pool
+#
+for i in 1 2; do
+ damage_devs $TESTPOOL $i
+ log_must is_data_valid $TESTPOOL
+ log_must recover_bad_missing_devs $TESTPOOL $i
+done
+
+#
+# Inject missing device errors for raidz2 pool
+#
+for i in 1 2; do
+ remove_devs $TESTPOOL $i
+ log_must is_data_valid $TESTPOOL
+ log_must recover_bad_missing_devs $TESTPOOL $i
+done
+
+log_pass "Raidz2 pool can withstand two devices are failing passed."
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_003_pos.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_003_pos.ksh
new file mode 100755
index 000000000000..b7b791b248ee
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/redundancy/redundancy.kshlib
+
+#
+# DESCRIPTION:
+# A mirrored pool can withstand N-1 device are failing or missing.
+#
+# STRATEGY:
+# 1. Create N(>2,<5) virtual disk files.
+# 2. Create mirror pool based on the virtual disk files.
+# 3. Fill the filesystem with directories and files.
+# 4. Record all the files and directories checksum information.
+# 5. Damaged at most N-1 of the virtual disk files.
+# 6. Verify the data are correct to prove mirror can withstand N-1 devices
+# are failing.
+#
+
+verify_runnable "global"
+
+log_assert "Verify mirrored pool can withstand N-1 devices are failing or missing."
+log_onexit cleanup
+
+typeset -i cnt=$(random_int_between 2 5)
+setup_test_env $TESTPOOL mirror $cnt
+
+typeset -i i=1
+
+#
+# Inject data corruption errors for mirrored pool
+#
+while (( i < cnt )); do
+ damage_devs $TESTPOOL $i "label"
+ log_must is_data_valid $TESTPOOL
+ log_must clear_errors $TESTPOOL
+
+ (( i +=1 ))
+done
+
+#
+# Inject bad devices errors for mirrored pool
+#
+i=1
+while (( i < cnt )); do
+ damage_devs $TESTPOOL $i
+ log_must is_data_valid $TESTPOOL
+ log_must recover_bad_missing_devs $TESTPOOL $i
+
+ (( i +=1 ))
+done
+
+#
+# Inject missing device errors for mirrored pool
+#
+i=1
+while (( i < cnt )); do
+ remove_devs $TESTPOOL $i
+ log_must is_data_valid $TESTPOOL
+ log_must recover_bad_missing_devs $TESTPOOL $i
+
+ (( i +=1 ))
+done
+
+log_pass "Mirrored pool can withstand N-1 devices failing as expected."
diff --git a/tests/zfs-tests/tests/functional/redundancy/redundancy_004_neg.ksh b/tests/zfs-tests/tests/functional/redundancy/redundancy_004_neg.ksh
new file mode 100755
index 000000000000..7ee51051ea1a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/redundancy_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 2007 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/redundancy/redundancy.kshlib
+
+#
+# DESCRIPTION:
+# Striped pool have no data redundancy. Any device errors will
+# cause data corruption.
+#
+# STRATEGY:
+# 1. Create N virtual disk file.
+# 2. Create stripe pool based on the virtual disk files.
+# 3. Fill the filesystem with directories and files.
+# 4. Record all the files and directories checksum information.
+# 5. Damage one of the virtual disk file.
+# 6. Verify the data is error.
+#
+
+verify_runnable "global"
+
+log_assert "Verify striped pool have no data redundancy."
+log_onexit cleanup
+
+typeset -i cnt=$(random_int_between 2 5)
+setup_test_env $TESTPOOL "" $cnt
+
+damage_devs $TESTPOOL 1 "keep_label"
+log_must zpool scrub -w $TESTPOOL
+
+log_mustnot is_healthy $TESTPOOL
+
+log_pass "Striped pool has no data redundancy as expected."
diff --git a/tests/zfs-tests/tests/functional/redundancy/setup.ksh b/tests/zfs-tests/tests/functional/redundancy/setup.ksh
new file mode 100755
index 000000000000..e2c04fe5cfbd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/redundancy/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/refquota/Makefile.am b/tests/zfs-tests/tests/functional/refquota/Makefile.am
new file mode 100644
index 000000000000..1d8418fbbec5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/refquota
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ refquota_001_pos.ksh \
+ refquota_002_pos.ksh \
+ refquota_003_pos.ksh \
+ refquota_004_pos.ksh \
+ refquota_005_pos.ksh \
+ refquota_006_neg.ksh \
+ refquota_007_neg.ksh \
+ refquota_008_neg.ksh
diff --git a/tests/zfs-tests/tests/functional/refquota/cleanup.ksh b/tests/zfs-tests/tests/functional/refquota/cleanup.ksh
new file mode 100755
index 000000000000..ea139ae0395b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_001_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_001_pos.ksh
new file mode 100755
index 000000000000..411fab8459af
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_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 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
+
+#
+# DESCRIPTION:
+# refquota limits the amount of space a dataset can consume, but does
+# not include space used by descendents.
+#
+# STRATEGY:
+# 1. Setting refquota in given filesystem
+# 2. Create descendent filesystem
+# 3. Verify refquota limits the amount of space a dataset can consume
+# 4. Verify the limit does not impact descendents
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "refquota limits the amount of space a dataset can consume, " \
+ "but does not include space used by descendents."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+sub=$fs/sub
+log_must zfs create $sub
+
+log_must zfs set refquota=10M $fs
+mntpnt=$(get_prop mountpoint $fs)
+
+log_mustnot mkfile 11M $mntpnt/file
+log_must mkfile 9M $mntpnt/file
+log_must zfs snapshot $fs@snap
+log_mustnot mkfile 2M $mntpnt/file2
+
+mntpnt=$(get_prop mountpoint $sub)
+log_must mkfile 10M $mntpnt/file
+log_must zfs snapshot $sub@snap
+log_must mkfile 10 $mntpnt/file2
+
+log_pass "refquota limits the amount of space a dataset can consume, " \
+ "but does not include space used by descendents."
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_002_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_002_pos.ksh
new file mode 100755
index 000000000000..e1d3aa82033c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_002_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 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
+
+#
+# DESCRIPTION:
+# Quotas are enforced using the minimum of the two properties:
+# quota & refquota
+#
+# STRATEGY:
+# 1. Set value for quota and refquota. Quota less than refquota.
+# 2. Creating file which should be limited by quota.
+# 3. Switch the value of quota and refquota.
+# 4. Verify file should be limited by refquota.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "Quotas are enforced using the minimum of the two properties"
+log_onexit cleanup
+
+TESTFILE='testfile'
+fs=$TESTPOOL/$TESTFS
+log_must zfs set quota=15M $fs
+log_must zfs set refquota=25M $fs
+
+mntpnt=$(get_prop mountpoint $fs)
+log_mustnot mkfile 20M $mntpnt/$TESTFILE
+typeset -i used quota
+used=$(get_prop used $fs)
+quota=$(get_prop quota $fs)
+((used = used / (1024 * 1024)))
+((quota = quota / (1024 * 1024)))
+if [[ $used -ne $quota ]]; then
+ log_fail "ERROR: $used -ne $quota Quotas are not limited by quota"
+fi
+
+#
+# Switch the value of them and try again
+#
+log_must rm $mntpnt/$TESTFILE
+log_must zfs set quota=25M $fs
+log_must zfs set refquota=15M $fs
+
+log_mustnot mkfile 20M $mntpnt/$TESTFILE
+used=$(get_prop used $fs)
+refquota=$(get_prop refquota $fs)
+((used = used / (1024 * 1024)))
+((refquota = refquota / (1024 * 1024)))
+if [[ $used -ne $refquota ]]; then
+ log_fail "ERROR: $used -ne $refquota Quotas are not limited by refquota"
+fi
+
+log_pass "Quotas are enforced using the minimum of the two properties"
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_003_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_003_pos.ksh
new file mode 100755
index 000000000000..e4def1a0a7b4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_003_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 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
+
+#
+# DESCRIPTION:
+# Sub-filesystem quotas are not enforced by property 'refquota'
+#
+# STRATEGY:
+# 1. Setting quota and refquota for parent. refquota < quota
+# 2. Verify sub-filesystem will not be limited by refquota
+# 3. Verify sub-filesystem will only be limited by quota
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "Sub-filesystem quotas are not enforced by property 'refquota'"
+log_onexit cleanup
+
+TESTFILE='testfile'
+fs=$TESTPOOL/$TESTFS
+log_must zfs set quota=25M $fs
+log_must zfs set refquota=10M $fs
+log_must zfs create $fs/subfs
+
+mntpnt=$(get_prop mountpoint $fs/subfs)
+log_must mkfile 20M $mntpnt/$TESTFILE
+
+typeset -i used quota refquota
+used=$(get_prop used $fs)
+refquota=$(get_prop refquota $fs)
+((used = used / (1024 * 1024)))
+((refquota = refquota / (1024 * 1024)))
+if [[ $used -lt $refquota ]]; then
+ log_fail "ERROR: $used < $refquota subfs quotas are limited by refquota"
+fi
+
+log_mustnot mkfile 20M $mntpnt/$TESTFILE.2
+used=$(get_prop used $fs)
+quota=$(get_prop quota $fs)
+((used = used / (1024 * 1024)))
+((quota = quota / (1024 * 1024)))
+if [[ $used -gt $quota ]]; then
+ log_fail "ERROR: $used > $quota subfs quotas aren't limited by quota"
+fi
+
+log_pass "Sub-filesystem quotas are not enforced by property 'refquota'"
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_004_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_004_pos.ksh
new file mode 100755
index 000000000000..0691c3630931
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_004_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 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
+
+#
+# DESCRIPTION:
+# refquotas are not limited by snapshots.
+#
+# STRATEGY:
+# 1. Setting refquota < quota
+# 2. Create file in filesystem, take snapshot and remove the file
+# 3. Verify snapshot will not consume refquota
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "refquotas are not limited by snapshots."
+log_onexit cleanup
+
+TESTFILE='testfile'
+fs=$TESTPOOL/$TESTFS
+log_must zfs set quota=25M $fs
+log_must zfs set refquota=15M $fs
+
+mntpnt=$(get_prop mountpoint $fs)
+typeset -i i=0
+while ((i < 3)); do
+ log_must mkfile 7M $mntpnt/$TESTFILE.$i
+ log_must zfs snapshot $fs@snap.$i
+ log_must rm $mntpnt/$TESTFILE.$i
+
+ ((i += 1))
+done
+
+#
+# Verify out of the limitation of 'quota'
+#
+log_mustnot mkfile 7M $mntpnt/$TESTFILE
+
+log_pass "refquotas are not limited by snapshots."
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_005_pos.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_005_pos.ksh
new file mode 100755
index 000000000000..13977bc3b48f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_005_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# refquotas are not limited by sub-filesystem snapshots.
+#
+# STRATEGY:
+# 1. Setting refquota < quota for parent
+# 2. Create file in sub-filesystem, take snapshot and remove the file
+# 3. Verify sub-filesystem snapshot will not consume refquota
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "refquotas are not limited by sub-filesystem snapshots."
+log_onexit cleanup
+
+TESTFILE='testfile'
+fs=$TESTPOOL/$TESTFS
+log_must zfs set quota=25M $fs
+log_must zfs set refquota=15M $fs
+log_must zfs create $fs/subfs
+
+mntpnt=$(get_prop mountpoint $fs/subfs)
+typeset -i i=0
+while ((i < 3)); do
+ log_must mkfile 7M $mntpnt/$TESTFILE.$i
+ log_must zfs snapshot $fs/subfs@snap.$i
+ log_must rm $mntpnt/$TESTFILE.$i
+
+ ((i += 1))
+done
+
+#
+# Verify out of the limitation of 'quota'
+#
+log_mustnot mkfile 7M $mntpnt/$TESTFILE
+
+log_pass "refquotas are not limited by sub-filesystem snapshots"
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_006_neg.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_006_neg.ksh
new file mode 100755
index 000000000000..39b317512df2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_006_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 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
+
+#
+# DESCRIPTION:
+# 'zfs set refquota/refreserv' can handle incorrect arguments correctly.
+#
+# STRATEGY:
+# 1. Setup incorrect arguments arrays.
+# 2. Set the bad argument to refquota.
+# 3. Verify zfs can handle it correctly.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs set refquota=none $TESTPOOL/$TESTFS
+ log_must zfs set refreserv=none $TESTPOOL/$TESTFS
+}
+
+log_assert "'zfs set refquota' can handle incorrect arguments correctly."
+log_onexit cleanup
+
+set -A badopt \
+ "None" "-1" "1TT" "%5" \
+ "123!" "@456" "7#89" "0\$" \
+ "abc123%" "123%s" "12%s3" "%c123" \
+ "123%d" "%x123" "12%p3" "^def456" \
+ "\0" "x0"
+
+typeset -i i=0
+while ((i < ${#badopt[@]})); do
+ log_mustnot zfs set refquota=${badopt[$i]} $TESTPOOL/$TESTFS
+ log_mustnot zfs set refreserv=${badopt[$i]} $TESTPOOL/$TESTFS
+
+ ((i += 1))
+done
+
+log_pass "'zfs set refquota' can handle incorrect arguments correctly."
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_007_neg.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_007_neg.ksh
new file mode 100755
index 000000000000..4f0393883b6a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_007_neg.ksh
@@ -0,0 +1,61 @@
+#!/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# refquota limits the amount of space a dataset can consume,
+# snapshot rollback should be limited by refquota.
+#
+# STRATEGY:
+# 1. Create a file in a filesystem
+# 2. Create a snapshot of the filesystem
+# 3. Remove the file
+# 4. Set a refquota of size half of the file
+# 5. Rollback the filesystem from the snapshot
+# 6. Rollback should fail
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_onexit cleanup
+
+TESTFILE='testfile'
+FS=$TESTPOOL/$TESTFS
+
+mntpnt=$(get_prop mountpoint $FS)
+log_must mkfile 20M $mntpnt/$TESTFILE
+log_must zfs snapshot $FS@snap20M
+log_must rm $mntpnt/$TESTFILE
+
+log_must sync
+
+log_must zfs set refquota=10M $FS
+log_mustnot zfs rollback $FS@snap20M
+
+log_pass "The rollback to the snapshot was restricted by refquota."
diff --git a/tests/zfs-tests/tests/functional/refquota/refquota_008_neg.ksh b/tests/zfs-tests/tests/functional/refquota/refquota_008_neg.ksh
new file mode 100755
index 000000000000..6e4da3621c29
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/refquota_008_neg.ksh
@@ -0,0 +1,71 @@
+#!/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# refquota limits the amount of space a dataset can consume,
+# This test verifies that zfs receive does not override
+# refquota.
+#
+# STRATEGY:
+# 1. Create a sub-filesystem $TESTSUBFS1
+# 2. Create a file in the sub-filesystem $TESTSUBFS1
+# 3. Create a snapshot of the sub-filesystem $TESTSUBFS1
+# 4. Create another sub-filesystem $TESTSUBFS2
+# 5. Apply a refquota value to $TESTSUBFS2,
+# half the sub-filesystem $TESTSUBFS1 file size
+# 6. Verify that zfs receive of the snapshot of $TESTSUBFS1
+# fails due to refquota
+#
+
+verify_runnable "both"
+
+oldvalue=$(get_tunable SPA_ASIZE_INFLATION)
+function cleanup
+{
+ set_tunable32 SPA_ASIZE_INFLATION $oldvalue
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_onexit cleanup
+
+set_tunable32 SPA_ASIZE_INFLATION 2
+
+TESTFILE='testfile'
+FS=$TESTPOOL/$TESTFS
+log_must zfs create $FS/$TESTSUBFS1
+log_must zfs create $FS/$TESTSUBFS2
+
+mntpnt1=$(get_prop mountpoint $FS/$TESTSUBFS1)
+mntpnt2=$(get_prop mountpoint $FS/$TESTSUBFS2)
+
+log_must mkfile 200M $mntpnt1/$TESTFILE
+log_must zfs snapshot $FS/$TESTSUBFS1@snap200m
+
+log_must zfs set refquota=10M $FS/$TESTSUBFS2
+log_mustnot eval "zfs send $FS/$TESTSUBFS1@snap200m |" \
+ "zfs receive -F $FS/$TESTSUBFS2"
+
+log_pass "ZFS receive does not override refquota"
+
diff --git a/tests/zfs-tests/tests/functional/refquota/setup.ksh b/tests/zfs-tests/tests/functional/refquota/setup.ksh
new file mode 100755
index 000000000000..a34453bd3892
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refquota/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 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/refreserv/Makefile.am b/tests/zfs-tests/tests/functional/refreserv/Makefile.am
new file mode 100644
index 000000000000..bd760a1f0697
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/refreserv
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ refreserv_001_pos.ksh \
+ refreserv_002_pos.ksh \
+ refreserv_003_pos.ksh \
+ refreserv_004_pos.ksh \
+ refreserv_005_pos.ksh \
+ refreserv_multi_raidz.ksh \
+ refreserv_raidz.ksh
+
+dist_pkgdata_DATA = \
+ refreserv.cfg
diff --git a/tests/zfs-tests/tests/functional/refreserv/cleanup.ksh b/tests/zfs-tests/tests/functional/refreserv/cleanup.ksh
new file mode 100755
index 000000000000..ea139ae0395b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv.cfg b/tests/zfs-tests/tests/functional/refreserv/refreserv.cfg
new file mode 100644
index 000000000000..8c892db4a3a2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export TESTFILE=testfile
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.ksh
new file mode 100755
index 000000000000..527949f27c10
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_001_pos.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 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/refreserv/refreserv.cfg
+
+#
+# DESCRIPTION:
+# Reservations are enforced using the maximum of 'reserv' and 'refreserv'
+#
+# STRATEGY:
+# 1. Setting quota for parent filesystem.
+# 2. Setting reservation and refreservation for sub-filesystem.
+# 3. Verify the sub-fs reservation are enforced by the maximum of 'reserv'
+# and 'refreserv'.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "Reservations are enforced using the maximum of " \
+ "'reserv' and 'refreserv'"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS ; subfs=$fs/subfs
+log_must zfs create $subfs
+log_must zfs set quota=25M $fs
+
+log_must zfs set reserv=10M $subfs
+log_must zfs set refreserv=20M $subfs
+mntpnt=$(get_prop mountpoint $fs)
+log_mustnot mkfile 15M $mntpnt/$TESTFILE
+
+log_must rm -f $mntpnt/$TESTFILE
+
+log_must zfs set reserv=20M $subfs
+log_must zfs set refreserv=10M $subfs
+log_mustnot mkfile 15M $mntpnt/$TESTFILE
+
+log_pass "Reservations are enforced using the maximum of " \
+ "'reserv' and 'refreserv'"
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh
new file mode 100755
index 000000000000..d4c0a4faebdc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_002_pos.ksh
@@ -0,0 +1,114 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/refreserv/refreserv.cfg
+
+#
+# DESCRIPTION:
+# Setting full size as refreservation, verify no snapshot can be created.
+#
+# STRATEGY:
+# 1. Setting full size as refreservation on pool
+# 2. Verify no snapshot can be created on this pool
+# 3. Setting full size as refreservation on filesystem
+# 4. Verify no snapshot can be created on it and its subfs
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if is_global_zone ; then
+ log_must zfs set refreservation=none $TESTPOOL
+
+ if datasetexists $TESTPOOL@snap ; then
+ log_must zfs destroy -f $TESTPOOL@snap
+ fi
+ fi
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+# This function iteratively increases refreserv to its highest possible
+# value. Simply setting refreserv == quota can allow enough writes to
+# complete that the test fails.
+function max_refreserv
+{
+ typeset ds=$1
+ typeset -i incsize=131072
+ typeset -i rr=$(get_prop available $ds)
+
+ log_must zfs set refreserv=$rr $ds
+ while :; do
+ zfs set refreserv=$((rr + incsize)) $ds >/dev/null 2>&1
+ if [[ $? == 0 ]]; then
+ ((rr += incsize))
+ continue
+ else
+ ((incsize /= 2))
+ ((incsize == 0)) && break
+ fi
+ done
+}
+
+
+log_assert "Setting full size as refreservation, verify no snapshot " \
+ "can be created."
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS/subfs
+
+typeset datasets
+if is_global_zone; then
+ datasets="$TESTPOOL $TESTPOOL/$TESTFS $TESTPOOL/$TESTFS/subfs"
+else
+ datasets="$TESTPOOL/$TESTFS $TESTPOOL/$TESTFS/subfs"
+fi
+
+for ds in $datasets; do
+ #
+ # Verify refreservation on dataset
+ #
+ log_must zfs set quota=25M $ds
+ max_refreserv $ds
+ log_mustnot zfs snapshot $ds@snap
+ if datasetexists $ds@snap ; then
+ log_fail "ERROR: $ds@snap should not exists."
+ fi
+
+ log_must zfs set quota=none $ds
+ log_must zfs set refreservation=none $ds
+done
+
+log_pass "Setting full size as refreservation, verify no snapshot " \
+ "can be created."
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_003_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_003_pos.ksh
new file mode 100755
index 000000000000..3e5a78cf944f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/refreserv/refreserv.cfg
+
+#
+# DESCRIPTION:
+# Verify a snapshot will only be allowed if there is enough free pool
+# space outside of this refreservation.
+#
+# STRATEGY:
+# 1. Setting quota and refreservation
+# 2. Verify snapshot can be created, when used =< quota - refreserv
+# 3. Verify failed to create snapshot, when used > quota - refreserv
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "Verify a snapshot will only be allowed if there is enough " \
+ "free space outside of this refreservation."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+log_must zfs set quota=25M $fs
+log_must zfs set refreservation=10M $fs
+
+mntpnt=$(get_prop mountpoint $fs)
+log_must mkfile 7M $mntpnt/$TESTFILE
+log_must zfs snapshot $fs@snap
+
+log_must mkfile 7M $mntpnt/$TESTFILE.2
+log_must zfs snapshot $fs@snap2
+
+log_must mkfile 7M $mntpnt/$TESTFILE.3
+log_mustnot zfs snapshot $fs@snap3
+if datasetexists $fs@snap3 ; then
+ log_fail "ERROR: $fs@snap3 should not exists."
+fi
+
+log_pass "Verify a snapshot will only be allowed if there is enough " \
+ "free space outside of this refreservation."
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_004_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_004_pos.ksh
new file mode 100755
index 000000000000..529d918c3695
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_004_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/refreserv/refreserv.cfg
+
+#
+# DESCRIPTION:
+# Verify refreservation is limited by available space.
+#
+# STRATEGY:
+# 1. Setting quota and refreservation on parent filesystem.
+# 2. Get available space on sub-filesystem.
+# 3. Verify refreservation is limited by available on it.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if is_global_zone ; then
+ log_must zfs set refreservation=none $TESTPOOL
+ fi
+ log_must zfs destroy -rf $TESTPOOL/$TESTFS
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "Verify refreservation is limited by available space."
+log_onexit cleanup
+
+pool=$TESTPOOL ; fs=$pool/$TESTFS ; subfs=$fs/subfs
+log_must zfs create $subfs
+
+typeset datasets
+if is_global_zone; then
+ datasets="$pool $fs"
+else
+ datasets="$fs"
+fi
+
+for ds in $datasets; do
+ log_must zfs set quota=25M $ds
+ log_must zfs set refreservation=15M $ds
+
+ typeset -i avail
+ avail=$(get_prop avail $subfs)
+ log_must zfs set refreservation=$avail $subfs
+ typeset mntpnt
+ mntpnt=$(get_prop mountpoint $subfs)
+ log_must mkfile $avail $mntpnt/$TESTFILE
+
+ typeset -i exceed
+ ((exceed = avail + 1))
+ log_mustnot zfs set refreservation=$exceed $subfs
+ log_mustnot mkfile $avail $mntpnt/$TESTFILE
+
+ log_must zfs set quota=none $ds
+ log_must zfs set reservation=15M $ds
+done
+
+log_pass "Verify refreservation is limited by available space."
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_005_pos.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_005_pos.ksh
new file mode 100755
index 000000000000..1ccc9828d4f7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_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 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
+
+#
+# DESCRIPTION:
+# Volume (ref)reservation is not limited by volsize
+#
+# STRATEGY:
+# 1. Create volume on filesystem
+# 2. Setting quota for parent filesystem
+# 3. Verify volume (ref)reservation is not limited by volsize
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_dataset "$fs" "-rf"
+ log_must zfs create $fs
+ log_must zfs set mountpoint=$TESTDIR $fs
+}
+
+log_assert "Volume (ref)reservation is not limited by volsize"
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+vol=$fs/vol
+log_must zfs create -V 10M $vol
+refreserv=`get_prop refreservation $vol`
+fudge=1
+
+# Verify the parent filesystem does not affect volume
+log_must zfs set quota=25M $fs
+log_must zfs set reservation=10M $vol
+log_must zfs set refreservation=10M $vol
+
+# Verify it is not affected by volsize
+log_must zfs set reservation=$(($refreserv + $fudge)) $vol
+log_must zfs set reservation=$(($refreserv - $fudge)) $vol
+log_must zfs set refreservation=$(($refreserv + $fudge)) $vol
+log_must zfs set refreservation=$(($refreserv - $fudge)) $vol
+
+log_pass "Volume (ref)reservation is not limited by volsize"
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_multi_raidz.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_multi_raidz.ksh
new file mode 100755
index 000000000000..ff79764babd8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_multi_raidz.ksh
@@ -0,0 +1,201 @@
+#!/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/refreserv/refreserv.cfg
+
+#
+# DESCRIPTION:
+# raidz refreservation=auto picks worst raidz vdev
+#
+# STRATEGY:
+# 1. Create a pool with a single raidz vdev
+# 2. For each block size [512b, 1k, 128k] or [4k, 8k, 128k]
+# - create a volume
+# - remember its refreservation
+# - destroy the volume
+# 3. Destroy the pool
+# 4. Recreate the pool with one more disk in the vdev, then repeat steps
+# 2 and 3.
+#
+# NOTES:
+# 1. This test will use up to 14 disks but can cover the key concepts with
+# 5 disks.
+# 2. If the disks are a mixture of 4Kn and 512n/512e, failures are likely.
+#
+
+verify_runnable "global"
+
+typeset -a alldisks=($DISKS)
+
+# The larger the volsize, the better zvol_volsize_to_reservation() is at
+# guessing the right number - though it is horrible with tiny blocks. At 10M on
+# ashift=12, the estimate may be over 26% too high.
+volsize=100
+
+function cleanup
+{
+ default_cleanup_noexit
+ default_setup_noexit "${alldisks[0]}"
+}
+
+log_assert "raidz refreservation=auto picks worst raidz vdev"
+log_onexit cleanup
+
+poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+# Testing tiny block sizes on ashift=12 pools causes so much size inflation
+# that small test disks may fill before creating small volumes. However,
+# testing 512b and 1K blocks on ashift=9 pools is an ok approximation for
+# testing the problems that arise from 4K and 8K blocks on ashift=12 pools.
+if is_freebsd; then
+ bps=$(diskinfo -v ${alldisks[0]} | awk '/sectorsize/ { print $1 }')
+elif is_linux; then
+ bps=$(lsblk -nrdo min-io /dev/${alldisks[0]})
+fi
+case "$bps" in
+512)
+ allshifts=(9 10 17)
+ ;;
+4096)
+ allshifts=(12 13 17)
+ ;;
+*)
+ log_fail "bytes/sector: $bps != (512|4096)"
+ ;;
+esac
+log_note "Testing in ashift=${allshifts[0]} mode"
+
+typeset -A sizes=
+
+#
+# Determine the refreservation for a $volsize MiB volume on each raidz type at
+# various block sizes.
+#
+for parity in 1 2 3; do
+ raid=raidz$parity
+ typeset -A sizes["$raid"]
+
+ # Ensure we hit scenarios with and without skip blocks
+ for ndisks in $((parity * 2)) $((parity * 2 + 1)); do
+ typeset -a disks=(${alldisks[0..$((ndisks - 1))]})
+
+ if (( ${#disks[@]} < ndisks )); then
+ log_note "Too few disks to test $raid-$ndisks"
+ continue
+ fi
+
+ typeset -A sizes["$raid"]["$ndisks"]
+
+ log_must zpool create "$TESTPOOL" "$raid" "${disks[@]}"
+
+ for bits in "${allshifts[@]}"; do
+ vbs=$((1 << bits))
+ log_note "Gathering refreservation for $raid-$ndisks" \
+ "volblocksize=$vbs"
+
+ vol=$TESTPOOL/$TESTVOL
+ log_must zfs create -V ${volsize}m \
+ -o volblocksize=$vbs "$vol"
+
+ refres=$(zfs get -Hpo value refreservation "$vol")
+ log_must test -n "$refres"
+ sizes["$raid"]["$ndisks"]["$vbs"]=$refres
+
+ log_must_busy zfs destroy "$vol"
+ done
+
+ log_must_busy zpool destroy "$TESTPOOL"
+ done
+done
+
+# A little extra info is always helpful when diagnosing problems. To
+# pretty-print what you find in the log, do this in ksh:
+# typeset -A sizes=(...)
+# print -v sizes
+log_note "sizes=$(print -C sizes)"
+
+#
+# Helper function for checking that refreservation is calculated properly in
+# multi-vdev pools. "Properly" is defined as assuming that all vdevs are as
+# space inefficient as the worst one.
+#
+function check_vdevs {
+ typeset raid=$1
+ typeset nd1=$2
+ typeset nd2=$3
+ typeset -a disks1 disks2
+ typeset vbs vol refres refres1 refres2 expect
+
+ disks1=(${alldisks[0..$((nd1 - 1))]})
+ disks2=(${alldisks[$nd1..$((nd1 + nd2 - 1))]})
+ if (( ${#disks2[@]} < nd2 )); then
+ log_note "Too few disks to test $raid-$nd1 + $raid=$nd2"
+ return
+ fi
+
+ log_must zpool create -f "$TESTPOOL" \
+ "$raid" "${disks1[@]}" "$raid" "${disks2[@]}"
+
+ for bits in "${allshifts[@]}"; do
+ vbs=$((1 << bits))
+ log_note "Verifying $raid-$nd1 $raid-$nd2 volblocksize=$vbs"
+
+ vol=$TESTPOOL/$TESTVOL
+ log_must zfs create -V ${volsize}m -o volblocksize=$vbs "$vol"
+ refres=$(zfs get -Hpo value refreservation "$vol")
+ log_must test -n "$refres"
+
+ refres1=${sizes["$raid"]["$nd1"]["$vbs"]}
+ refres2=${sizes["$raid"]["$nd2"]["$vbs"]}
+
+ if (( refres1 > refres2 )); then
+ log_note "Expecting refres ($refres) to match refres" \
+ "from $raid-$nd1 ($refres1)"
+ log_must test "$refres" -eq "$refres1"
+ else
+ log_note "Expecting refres ($refres) to match refres" \
+ "from $raid-$nd1 ($refres2)"
+ log_must test "$refres" -eq "$refres2"
+ fi
+
+ log_must zfs destroy "$vol"
+ done
+
+ log_must zpool destroy "$TESTPOOL"
+}
+
+#
+# Verify that multi-vdev pools use the last optimistic size for all the
+# permutations within a particular raidz variant.
+#
+for raid in "${!sizes[@]}"; do
+ # ksh likes to create a [0] item for us. Thanks, ksh!
+ [[ $raid == "0" ]] && continue
+
+ for nd1 in "${!sizes["$raid"][@]}"; do
+ # And with an empty array we get one key, ''. Thanks, ksh!
+ [[ $nd1 == "0" || -z "$nd1" ]] && continue
+
+ for nd2 in "${!sizes["$raid"][@]}"; do
+ [[ $nd2 == "0" || -z "$nd2" ]] && continue
+
+ check_vdevs "$raid" "$nd1" "$nd2"
+ done
+ done
+done
+
+log_pass "raidz refreservation=auto picks worst raidz vdev"
diff --git a/tests/zfs-tests/tests/functional/refreserv/refreserv_raidz.ksh b/tests/zfs-tests/tests/functional/refreserv/refreserv_raidz.ksh
new file mode 100755
index 000000000000..22891ef1d513
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/refreserv_raidz.ksh
@@ -0,0 +1,135 @@
+#!/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/refreserv/refreserv.cfg
+
+#
+# DESCRIPTION:
+# raidz refreservation=auto accounts for extra parity and skip blocks
+#
+# STRATEGY:
+# 1. Create a pool with a single raidz vdev
+# 2. For each block size [512b, 1k, 128k] or [4k, 8k, 128k]
+# - create a volume
+# - fully overwrite it
+# - verify that referenced is less than or equal to reservation
+# - destroy the volume
+# 3. Destroy the pool
+# 4. Recreate the pool with one more disk in the vdev, then repeat steps
+# 2 and 3.
+# 5. Repeat all steps above for raidz2 and raidz3.
+#
+# NOTES:
+# 1. This test will use up to 14 disks but can cover the key concepts with
+# 5 disks.
+# 2. If the disks are a mixture of 4Kn and 512n/512e, failures are likely.
+#
+
+verify_runnable "global"
+
+typeset -a alldisks=($DISKS)
+
+# The larger the volsize, the better zvol_volsize_to_reservation() is at
+# guessing the right number. At 10M on ashift=12, the estimate may be over 26%
+# too high.
+volsize=100
+
+function cleanup
+{
+ default_cleanup_noexit
+ default_setup_noexit "${alldisks[0]}"
+}
+
+log_assert "raidz refreservation=auto accounts for extra parity and skip blocks"
+log_onexit cleanup
+
+poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL"
+
+# Testing tiny block sizes on ashift=12 pools causes so much size inflation
+# that small test disks may fill before creating small volumes. However,
+# testing 512b and 1K blocks on ashift=9 pools is an ok approximation for
+# testing the problems that arise from 4K and 8K blocks on ashift=12 pools.
+if is_freebsd; then
+ bps=$(diskinfo -v ${alldisks[0]} | awk '/sectorsize/ { print $1 }')
+elif is_linux; then
+ bps=$(lsblk -nrdo min-io /dev/${alldisks[0]})
+fi
+log_must test "$bps" -eq 512 -o "$bps" -eq 4096
+case "$bps" in
+512)
+ allshifts=(9 10 17)
+ maxpct=151
+ ;;
+4096)
+ allshifts=(12 13 17)
+ maxpct=110
+ ;;
+*)
+ log_fail "bytes/sector: $bps != (512|4096)"
+ ;;
+esac
+log_note "Testing in ashift=${allshifts[0]} mode"
+
+# This loop handles all iterations of steps 1 through 4 described in strategy
+# comment above,
+for parity in 1 2 3; do
+ raid=raidz$parity
+
+ # Ensure we hit scenarios with and without skip blocks
+ for ndisks in $((parity * 2)) $((parity * 2 + 1)); do
+ typeset -a disks=(${alldisks[0..$((ndisks - 1))]})
+
+ if (( ${#disks[@]} < ndisks )); then
+ log_note "Too few disks to test $raid-$ndisks"
+ continue
+ fi
+
+ log_must zpool create "$TESTPOOL" "$raid" "${disks[@]}"
+
+ for bits in "${allshifts[@]}"; do
+ vbs=$((1 << bits))
+ log_note "Testing $raid-$ndisks volblocksize=$vbs"
+
+ vol=$TESTPOOL/$TESTVOL
+ log_must zfs create -V ${volsize}m \
+ -o volblocksize=$vbs "$vol"
+ block_device_wait "/dev/zvol/$vol"
+ log_must dd if=/dev/zero of=/dev/zvol/$vol \
+ bs=1024k count=$volsize
+ sync
+
+ ref=$(zfs get -Hpo value referenced "$vol")
+ refres=$(zfs get -Hpo value refreservation "$vol")
+ log_must test -n "$ref"
+ log_must test -n "$refres"
+
+ typeset -F2 deltapct=$((refres * 100.0 / ref))
+ log_note "$raid-$ndisks refreservation $refres" \
+ "is $deltapct% of reservation $res"
+
+ log_must test "$ref" -le "$refres"
+ log_must test "$deltapct" -le $maxpct
+
+ log_must_busy zfs destroy "$vol"
+ block_device_wait
+ done
+
+ log_must_busy zpool destroy "$TESTPOOL"
+ done
+done
+
+log_pass "raidz refreservation=auto accounts for extra parity and skip blocks"
diff --git a/tests/zfs-tests/tests/functional/refreserv/setup.ksh b/tests/zfs-tests/tests/functional/refreserv/setup.ksh
new file mode 100755
index 000000000000..a34453bd3892
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/refreserv/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 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/removal/Makefile.am b/tests/zfs-tests/tests/functional/removal/Makefile.am
new file mode 100644
index 000000000000..4cc773463356
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/Makefile.am
@@ -0,0 +1,37 @@
+#
+# 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) 2014, 2019 by Delphix. All rights reserved.
+#
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/removal
+
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh removal_all_vdev.ksh removal_cancel.ksh \
+ removal_check_space.ksh removal_condense_export.ksh \
+ removal_multiple_indirection.ksh \
+ removal_nopwrite.ksh removal_remap_deadlists.ksh \
+ removal_reservation.ksh removal_resume_export.ksh \
+ removal_sanity.ksh removal_with_add.ksh removal_with_create_fs.ksh \
+ removal_with_dedup.ksh removal_with_errors.ksh \
+ removal_with_export.ksh removal_with_faulted.ksh \
+ removal_with_ganging.ksh \
+ removal_with_remove.ksh removal_with_scrub.ksh \
+ removal_with_send.ksh removal_with_send_recv.ksh \
+ removal_with_snapshot.ksh removal_with_write.ksh \
+ removal_with_zdb.ksh remove_mirror.ksh remove_mirror_sanity.ksh \
+ remove_raidz.ksh remove_expanded.ksh remove_indirect.ksh
+
+dist_pkgdata_DATA = \
+ removal.kshlib
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/removal
diff --git a/tests/zfs-tests/tests/functional/removal/cleanup.ksh b/tests/zfs-tests/tests/functional/removal/cleanup.ksh
new file mode 100755
index 000000000000..352a9fe10a20
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/cleanup.ksh
@@ -0,0 +1,23 @@
+#! /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) 2014 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/removal/removal.kshlib b/tests/zfs-tests/tests/functional/removal/removal.kshlib
new file mode 100644
index 000000000000..140ac38ad898
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal.kshlib
@@ -0,0 +1,156 @@
+#
+# 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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+export REMOVEDISK=${DISKS%% *}
+export NOTREMOVEDISK=${DISKS##* }
+
+#
+# Waits for the pool to finish a removal.
+#
+function wait_for_removal # pool
+{
+ typeset pool=$1
+ typeset callback=$2
+
+ log_must zpool wait -t remove $pool
+
+ #
+ # The pool state changes before the TXG finishes syncing; wait for
+ # the removal to be completed on disk.
+ #
+ sync_pool $pool
+
+ log_must is_pool_removed $pool
+ return 0
+}
+
+#
+# Removes the specified disk from its respective pool and
+# runs the callback while the removal is in progress.
+#
+# This function is mainly used to test how other operations
+# interact with device removal. After the callback is done,
+# the removal is unpaused and we wait for it to finish.
+#
+# Example usage:
+#
+# attempt_during_removal $TESTPOOL $DISK dd if=/dev/urandom \
+# of=/$TESTPOOL/file count=1
+#
+function attempt_during_removal # pool disk callback [args]
+{
+ typeset pool=$1
+ typeset disk=$2
+ typeset callback=$3
+
+ shift 3
+ log_onexit_push set_tunable32 REMOVAL_SUSPEND_PROGRESS 0
+ set_tunable32 REMOVAL_SUSPEND_PROGRESS 1
+
+ log_must zpool remove $pool $disk
+
+ #
+ # We want to make sure that the removal started
+ # before issuing the callback.
+ #
+ sync
+ log_must is_pool_removing $pool
+
+ log_must $callback "$@"
+
+ #
+ # Ensure that we still haven't finished the removal
+ # as expected.
+ #
+ log_must is_pool_removing $pool
+
+ set_tunable32 REMOVAL_SUSPEND_PROGRESS 0
+ log_onexit_pop
+
+ log_must wait_for_removal $pool
+ log_mustnot vdevs_in_pool $pool $disk
+ return 0
+}
+
+function indirect_vdev_mapping_size # pool
+{
+ typeset pool=$1
+ zdb -P $pool | grep 'indirect vdev' | \
+ sed -E 's/.*\(([0-9]+) in memory\).*/\1/g'
+}
+
+function random_write # file write_size
+{
+ typeset file=$1
+ typeset block_size=$2
+ typeset file_size=$(stat_size $file 2>/dev/null)
+ typeset nblocks=$((file_size / block_size))
+
+ [[ -w $file ]] || return 1
+
+ dd if=/dev/urandom of=$file conv=notrunc \
+ bs=$block_size count=1 seek=$((RANDOM % nblocks)) >/dev/null 2>&1
+}
+
+function start_random_writer # file
+{
+ typeset file=$1
+ (
+ log_note "Starting writer for $file"
+ # This will fail when we destroy the pool.
+ while random_write $file $((2**12)); do
+ :
+ done
+ log_note "Stopping writer for $file"
+ ) &
+}
+
+function test_removal_with_operation # callback [args]
+{
+ #
+ # To ensure that the removal takes a while, we fragment the pool
+ # by writing random blocks and continue to do during the removal.
+ #
+ log_must mkfile 1g $TESTDIR/$TESTFILE0
+ for i in $(seq $((2**10))); do
+ random_write $TESTDIR/$TESTFILE0 $((2**12)) || \
+ log_fail "Could not write to $TESTDIR/$TESTFILE0."
+ done
+ start_random_writer $TESTDIR/$TESTFILE0 1g
+ killpid=$!
+
+ log_must attempt_during_removal $TESTPOOL $REMOVEDISK "$@"
+ log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
+ log_must zdb -cd $TESTPOOL
+
+ kill $killpid
+ wait
+
+ verify_pool $TESTPOOL
+}
+
+#
+# Kill the background job use by the test_removal_with_operation function.
+#
+function test_removal_with_operation_kill
+{
+ kill $killpid
+ wait $killpid
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/removal/removal_all_vdev.ksh b/tests/zfs-tests/tests/functional/removal/removal_all_vdev.ksh
new file mode 100755
index 000000000000..d3a594689a45
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_all_vdev.ksh
@@ -0,0 +1,39 @@
+#! /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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+for disk in $DISKS; do
+ if [[ "$disk" != "$REMOVEDISK" ]]; then
+ log_must zpool remove $TESTPOOL $disk
+ log_must wait_for_removal $TESTPOOL
+ log_mustnot vdevs_in_pool $TESTPOOL $disk
+ fi
+done
+
+log_must [ "x$(get_disklist $TESTPOOL)" = "x$REMOVEDISK" ]
+
+log_mustnot zpool remove $TESTPOOL $disk
+
+log_pass "Was not able to remove the last device in a pool."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_cancel.ksh b/tests/zfs-tests/tests/functional/removal/removal_cancel.ksh
new file mode 100755
index 000000000000..e97dc5e77a8a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_cancel.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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# DESCRIPTION:
+#
+# Ensure that cancelling a removal midway does not cause any
+# issues like cause a panic.
+#
+# STRATEGY:
+#
+# 1. Create a pool with one vdev and do some writes on it.
+# 2. Add a new vdev to the pool and start the removal of
+# the first vdev.
+# 3. Cancel the removal after some segments have been copied
+# over to the new vdev.
+# 4. Run zdb to ensure the on-disk state of the pool is ok.
+#
+
+function cleanup
+{
+ #
+ # Reset tunable.
+ #
+ log_must set_tunable32 REMOVAL_SUSPEND_PROGRESS 0
+}
+log_onexit cleanup
+
+SAMPLEFILE=/$TESTDIR/00
+
+#
+# Create pool with one disk.
+#
+log_must default_setup_noexit "$REMOVEDISK"
+
+#
+# Create a file of size 1GB and then do some random writes.
+# Since randwritecomp does 8K writes we do 25000 writes
+# which means we write ~200MB to the vdev.
+#
+log_must mkfile -n 1g $SAMPLEFILE
+log_must randwritecomp $SAMPLEFILE 25000
+
+#
+# Add second device where all the data will be evacuated.
+#
+log_must zpool add -f $TESTPOOL $NOTREMOVEDISK
+
+#
+# Block removal.
+#
+log_must set_tunable32 REMOVAL_SUSPEND_PROGRESS 1
+
+#
+# Start removal.
+#
+log_must zpool remove $TESTPOOL $REMOVEDISK
+
+#
+# Only for debugging purposes in test logs.
+#
+log_must zpool status $TESTPOOL
+
+#
+# Cancel removal.
+#
+log_must zpool remove -s $TESTPOOL
+
+#
+# Verify on-disk state.
+#
+log_must zdb $TESTPOOL
+
+log_pass "Device removal thread cancelled successfully."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_check_space.ksh b/tests/zfs-tests/tests/functional/removal/removal_check_space.ksh
new file mode 100755
index 000000000000..dec692ada47f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_check_space.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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+log_must mkfile $MINVDEVSIZE $TMPDIR/dsk1
+log_must mkfile $MINVDEVSIZE $TMPDIR/dsk2
+DISKS="$TMPDIR/dsk1 $TMPDIR/dsk2"
+REMOVEDISK=$TMPDIR/dsk1
+
+log_must default_setup_noexit "$DISKS"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $DISKS
+}
+log_onexit cleanup
+
+# Write a little more than half the pool.
+log_must dd if=/dev/urandom of=/$TESTDIR/$TESTFILE0 bs=$((2**20)) \
+ count=$((MINVDEVSIZE / (1024 * 1024)))
+log_mustnot zpool remove $TESTPOOL $TMPDIR/dsk1
+
+log_pass "Removal will not succeed if insufficient space."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_condense_export.ksh b/tests/zfs-tests/tests/functional/removal/removal_condense_export.ksh
new file mode 100755
index 000000000000..7648900acf10
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_condense_export.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) 2015, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+function reset
+{
+ log_must set_tunable64 CONDENSE_INDIRECT_COMMIT_ENTRY_DELAY_MS 0
+ log_must set_tunable64 CONDENSE_MIN_MAPPING_BYTES 131072
+ default_cleanup_noexit
+}
+
+default_setup_noexit "$DISKS" "true"
+log_onexit reset
+log_must set_tunable64 CONDENSE_INDIRECT_COMMIT_ENTRY_DELAY_MS 5000
+log_must set_tunable64 CONDENSE_MIN_MAPPING_BYTES 1
+
+log_must zfs set recordsize=512 $TESTPOOL/$TESTFS
+
+#
+# Create a large file so that we know some of the blocks will be on the
+# removed device, and hence eligible for remapping.
+#
+log_must dd if=/dev/urandom of=$TESTDIR/file bs=1024k count=10
+
+#
+# Create a file in the other filesystem, which will not be remapped.
+#
+log_must dd if=/dev/urandom of=$TESTDIR1/file bs=1024k count=10
+
+#
+# Randomly rewrite some of blocks in the file so that there will be holes and
+# we will not be able to remap the entire file in a few huge chunks.
+#
+for i in {1..4096}; do
+ #
+ # We have to sync periodically so that all the writes don't end up in
+ # the same txg. If they were all in the same txg, only the last write
+ # would go through and we would not have as many allocations to
+ # fragment the file.
+ #
+ ((i % 100 > 0 )) || sync_pool $TESTPOOL || log_fail "Could not sync."
+ random_write $TESTDIR/file 512 || \
+ log_fail "Could not random write."
+done
+
+REMOVEDISKPATH=/dev
+case $REMOVEDISK in
+ /*)
+ REMOVEDISKPATH=$(dirname $REMOVEDISK)
+ ;;
+esac
+
+log_must zpool remove $TESTPOOL $REMOVEDISK
+log_must wait_for_removal $TESTPOOL
+log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
+
+#
+# Touch one block under each L1 indirect block, so that the other data blocks
+# will be remapped to their concrete locations. These parameters assume
+# recordsize=512, indirect block size of 128K (1024 block pointers per
+# indirect block), and file size of less than 20*1024 blocks (10MB).
+#
+log_must stride_dd -i /dev/urandom -o $TESTDIR/file -b 512 -c 20 -s 1024
+
+sync_pool $TESTPOOL
+sleep 4
+sync_pool $TESTPOOL
+log_must zpool export $TESTPOOL
+zdb -e -p $REMOVEDISKPATH $TESTPOOL | grep 'Condensing indirect vdev' || \
+ log_fail "Did not export during a condense."
+log_must zdb -e -p $REMOVEDISKPATH -cudi $TESTPOOL
+log_must zpool import $TESTPOOL
+
+log_pass "Pool can be exported in the middle of a condense."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_multiple_indirection.ksh b/tests/zfs-tests/tests/functional/removal/removal_multiple_indirection.ksh
new file mode 100755
index 000000000000..6c52fd7819ae
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_multiple_indirection.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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# DESCRIPTION:
+#
+# For device removal a file's contents should transfer
+# completely from one disk to another. That should remain
+# to be the case even if multiple levels of indirection
+# are introduced as we remove more and more devices.
+#
+# STRATEGY:
+#
+# 1. We create a file of size 128k and we save its contents
+# in a local variable.
+# 2. We set the limit of the maximum copied segment size of
+# removals to 32k, so during removal our 128k file will
+# be split to 4 blocks.
+# 3. We start removing disks and adding them back in a loop.
+# This way the file is moved around and introduces split
+# blocks.
+# 4. The loop itself tests that we don't have any problem
+# when removing many devices. Within the loop we test
+# that the files contents remain the same across transfers.
+#
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+log_must mkfile $(($MINVDEVSIZE * 2)) $TMPDIR/dsk1
+log_must mkfile $(($MINVDEVSIZE * 2)) $TMPDIR/dsk2
+DISKS="$TMPDIR/dsk1 $TMPDIR/dsk2"
+REMOVEDISK=$TMPDIR/dsk1
+
+log_must default_setup_noexit "$DISKS"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $DISKS
+
+ # reset REMOVE_MAX_SEGMENT to 1M
+ set_tunable32 REMOVE_MAX_SEGMENT 1048576
+}
+
+log_onexit cleanup
+
+# set REMOVE_MAX_SEGMENT to 32k
+log_must set_tunable32 REMOVE_MAX_SEGMENT 32768
+
+log_must dd if=/dev/urandom of=$TESTDIR/$TESTFILE0 bs=128k count=1
+FILE_CONTENTS=$(<$TESTDIR/$TESTFILE0)
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+
+for i in {1..10}; do
+ log_must zpool remove $TESTPOOL $TMPDIR/dsk1
+ log_must wait_for_removal $TESTPOOL
+ log_mustnot vdevs_in_pool $TESTPOOL $TMPDIR/dsk1
+ log_must zpool add $TESTPOOL $TMPDIR/dsk1
+
+ log_must zinject -a
+ log_must dd if=$TESTDIR/$TESTFILE0 of=/dev/null
+ log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+
+ log_must zpool remove $TESTPOOL $TMPDIR/dsk2
+ log_must wait_for_removal $TESTPOOL
+ log_mustnot vdevs_in_pool $TESTPOOL $TMPDIR/dsk2
+ log_must zpool add $TESTPOOL $TMPDIR/dsk2
+
+ log_must zinject -a
+ log_must dd if=$TESTDIR/$TESTFILE0 of=/dev/null
+ log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+done
+
+log_pass "File contents transferred completely from one disk to another."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh b/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh
new file mode 100755
index 000000000000..cede81ad60c2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_nopwrite.ksh
@@ -0,0 +1,87 @@
+#! /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 Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+. $STF_SUITE/tests/functional/nopwrite/nopwrite.shlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+BLOCKSIZE=8192
+
+origin="$TESTPOOL/$TESTFS"
+
+log_must zfs set compress=on $origin
+log_must zfs set checksum=skein $origin
+
+log_must zfs set recordsize=8k $origin
+dd if=/dev/urandom of=$TESTDIR/file_8k bs=1024k count=$MEGS oflag=sync \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+log_must zfs set recordsize=128k $origin
+dd if=/dev/urandom of=$TESTDIR/file_128k bs=1024k count=$MEGS oflag=sync \
+ conv=notrunc >/dev/null 2>&1 || log_fail "dd into $TESTDIR/file failed."
+
+zfs snapshot $origin@a || log_fail "zfs snap failed"
+log_must zfs clone $origin@a $origin/clone
+
+#
+# Verify that nopwrites work prior to removal
+#
+log_must zfs set recordsize=8k $origin/clone
+dd if=/$TESTDIR/file_8k of=/$TESTDIR/clone/file_8k bs=1024k \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_must verify_nopwrite $origin $origin@a $origin/clone
+
+log_must zfs set recordsize=128k $origin/clone
+dd if=/$TESTDIR/file_128k of=/$TESTDIR/clone/file_128k bs=1024k \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_must verify_nopwrite $origin $origin@a $origin/clone
+
+#
+# Remove a device before testing nopwrites again
+#
+log_must zpool remove $TESTPOOL $REMOVEDISK
+log_must wait_for_removal $TESTPOOL
+log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
+
+#
+# Normally, we expect nopwrites to avoid allocating new blocks, but
+# after a device has been removed the DVAs will get remapped when
+# a L0's indirect block is written. This will negate the effects
+# of nopwrite and should result in new allocations.
+#
+
+#
+# Perform a direct zil nopwrite test
+#
+log_must zfs set recordsize=8k $origin/clone
+dd if=/$TESTDIR/file_8k of=/$TESTDIR/clone/file_8k bs=1024k \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+
+#
+# Perform an indirect zil nopwrite test
+#
+log_must zfs set recordsize=128k $origin/clone
+dd if=/$TESTDIR/file_128k of=/$TESTDIR/clone/file_128k bs=1024k \
+ oflag=sync conv=notrunc >/dev/null 2>&1 || log_fail "dd failed."
+log_mustnot verify_nopwrite $origin $origin@a $origin/clone
+
+log_pass "Remove works with nopwrite."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_remap_deadlists.ksh b/tests/zfs-tests/tests/functional/removal/removal_remap_deadlists.ksh
new file mode 100755
index 000000000000..9348022866f4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_remap_deadlists.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) 2015, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+log_must dd if=/dev/zero of=$TESTDIR/file bs=1024k count=300
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap-pre1
+log_must dd if=/dev/zero of=$TESTDIR/file bs=1024k count=100 \
+ conv=notrunc seek=100
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap-pre2
+log_must dd if=/dev/zero of=$TESTDIR/file bs=1024k count=100 \
+ conv=notrunc seek=200
+
+if is_linux || is_freebsd; then
+ log_must attempt_during_removal $TESTPOOL $REMOVEDISK zdb -cd $TESTPOOL
+else
+ log_must attempt_during_removal $TESTPOOL $REMOVEDISK
+fi
+log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
+log_must zdb -cd $TESTPOOL
+
+#
+# Touch one block under each L1 indirect block, so that the other data blocks
+# will be remapped to their concrete locations. These parameters assume
+# recordsize=128K, indirect block size of 128K (1024 block pointers per
+# indirect block), and file size of less than 3*1024 blocks (384MB).
+#
+log_must stride_dd -i /dev/urandom -o $TESTDIR/file -b 131072 -c 3 -s 1024
+
+log_must zdb -cd $TESTPOOL
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap-post3
+log_must zdb -cd $TESTPOOL
+
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap-post4
+log_must zdb -cd $TESTPOOL
+
+#
+# Test case where block is moved from remap deadlist: blocks born before
+# snap-pre2 will be obsoleted.
+#
+log_must zfs destroy $TESTPOOL/$TESTFS@snap-pre2
+log_must zdb -cd $TESTPOOL
+
+#
+# Test case where we merge remap deadlists: blocks before snap-pre1 will
+# need to go on snap-post4's deadlist.
+#
+log_must zfs destroy $TESTPOOL/$TESTFS@snap-post3
+log_must zdb -cd $TESTPOOL
+
+log_must zfs destroy $TESTPOOL/$TESTFS@snap-post4
+
+#
+# Test rollback.
+#
+log_must zfs rollback $TESTPOOL/$TESTFS@snap-pre1
+log_must zfs destroy $TESTPOOL/$TESTFS@snap-pre1
+
+log_pass "Remove and remap works with snapshots and deadlists."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_reservation.ksh b/tests/zfs-tests/tests/functional/removal/removal_reservation.ksh
new file mode 100755
index 000000000000..bf0c202ecbf2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_reservation.ksh
@@ -0,0 +1,63 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+log_must mkfile 1g $TMPDIR/dsk1
+log_must mkfile 1g $TMPDIR/dsk2
+DISKS="$TMPDIR/dsk1 $TMPDIR/dsk2"
+REMOVEDISK=$TMPDIR/dsk1
+
+default_setup_noexit "$DISKS"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $DISKS
+}
+
+log_onexit cleanup
+
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+
+# Write a little under half the pool.
+log_must file_write -o create -f $TESTDIR/$TESTFILE1 -b $((2**20)) -c $((2**9))
+
+#
+# Start a writing thread to ensure the removal will take a while.
+# This will automatically die when we destroy the pool.
+#
+start_random_writer $TESTDIR/$TESTFILE1
+
+function callback
+{
+ # Attempt to write more than the new pool will be able to handle.
+ file_write -o create -f $TESTDIR/$TESTFILE2 -b $((2**20)) -c $((2**9))
+ zret=$?
+ ENOSPC=28
+ log_note "file_write returned $zret"
+ (( $zret == $ENOSPC )) || log_fail "Did not get ENOSPC during removal."
+}
+
+log_must attempt_during_removal $TESTPOOL $REMOVEDISK callback
+
+log_pass "Removal properly sets reservation."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_resume_export.ksh b/tests/zfs-tests/tests/functional/removal/removal_resume_export.ksh
new file mode 100755
index 000000000000..142e72754b00
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_resume_export.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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# DESCRIPTION:
+#
+# When a pool has an ongoing removal and it is exported ZFS
+# suspends the removal thread beforehand. This test ensures
+# that ZFS restarts the removal thread if the export fails
+# for some reason.
+#
+# STRATEGY:
+#
+# 1. Create a pool with one vdev and do some writes on it.
+# 2. Add a new vdev to the pool and start the removal of
+# the first vdev.
+# 3. Inject a fault in the pool and attempt to export (it
+# should fail).
+# 4. After the export fails ensure that the removal thread
+# was restarted and the process complete successfully.
+#
+
+
+function cleanup
+{
+ zinject -c all
+ default_cleanup_noexit
+}
+
+function callback
+{
+ #
+ # Inject an error so export fails after having just suspended
+ # the removal thread. [spa_inject_ref gets incremented]
+ #
+ log_must zinject -d $REMOVEDISK -D 10:1 $TESTPOOL
+
+ #
+ # Because of the above error export should fail.
+ #
+ log_mustnot zpool export $TESTPOOL
+
+ #
+ # Let the removal finish.
+ #
+ log_must zinject -c all
+
+ return 0
+}
+
+log_onexit cleanup
+
+#
+# Create pool with one disk.
+#
+log_must default_setup_noexit "$REMOVEDISK"
+
+#
+# Turn off compression to raise capacity as much as possible
+# for the little time that this test runs.
+#
+log_must zfs set compression=off $TESTPOOL/$TESTFS
+
+#
+# Write some data that will be evacuated from the device when
+# we start the removal.
+#
+log_must dd if=/dev/urandom of=$TESTDIR/$TESTFILE0 bs=64M count=32
+
+#
+# Add second device where all the data will be evacuated.
+#
+log_must zpool add -f $TESTPOOL $NOTREMOVEDISK
+
+#
+# Attempt the export with errors injected.
+#
+log_must attempt_during_removal $TESTPOOL $REMOVEDISK callback
+
+log_pass "Device removal thread resumes after failed export"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_sanity.ksh b/tests/zfs-tests/tests/functional/removal/removal_sanity.ksh
new file mode 100755
index 000000000000..e927e3c0e25b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_sanity.ksh
@@ -0,0 +1,39 @@
+#! /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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+FILE_CONTENTS="Leeloo Dallas mul-ti-pass."
+
+echo $FILE_CONTENTS >$TESTDIR/$TESTFILE0
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+
+log_must zpool remove $TESTPOOL $REMOVEDISK
+log_must wait_for_removal $TESTPOOL
+log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
+
+log_must dd if=/$TESTDIR/$TESTFILE0 of=/dev/null
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+
+log_pass "Removed device not in use after removal."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_add.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_add.ksh
new file mode 100755
index 000000000000..7ec6c8675074
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_add.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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+log_must mkfile 1g $TMPDIR/dsk1
+log_must mkfile 1g $TMPDIR/dsk2
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $TMPDIR/dsk1 $TMPDIR/dsk2
+}
+
+default_setup_noexit "$DISKS"
+log_onexit cleanup
+
+function callback
+{
+ log_mustnot zpool attach -f $TESTPOOL $TMPDIR/dsk1 $TMPDIR/dsk2
+ log_mustnot zpool add -f $TESTPOOL \
+ raidz $TMPDIR/dsk1 $TMPDIR/dsk2
+ log_must zpool add -f $TESTPOOL $TMPDIR/dsk1
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_pass "Removal can only add normal disks."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_create_fs.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_create_fs.ksh
new file mode 100755
index 000000000000..0872fd9faf40
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_create_fs.ksh
@@ -0,0 +1,36 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+function callback
+{
+ log_must zfs create $TESTPOOL/$TESTFS1
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_pass "Can write to device during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_dedup.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_dedup.ksh
new file mode 100755
index 000000000000..ac79b7c17268
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_dedup.ksh
@@ -0,0 +1,49 @@
+#! /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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+log_must zfs set dedup=on $TESTPOOL
+
+FILE_CONTENTS="Leeloo Dallas mul-ti-pass."
+
+echo $FILE_CONTENTS >$TESTDIR/$TESTFILE0
+echo $FILE_CONTENTS >$TESTDIR/$TESTFILE1
+echo $FILE_CONTENTS >$TESTDIR/$TESTFILE2
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+log_must [ "x$(<$TESTDIR/$TESTFILE1)" = "x$FILE_CONTENTS" ]
+log_must [ "x$(<$TESTDIR/$TESTFILE2)" = "x$FILE_CONTENTS" ]
+
+log_must zpool remove $TESTPOOL $REMOVEDISK
+log_must wait_for_removal $TESTPOOL
+log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
+
+log_must dd if=/$TESTDIR/$TESTFILE0 of=/dev/null
+log_must dd if=/$TESTDIR/$TESTFILE1 of=/dev/null
+log_must dd if=/$TESTDIR/$TESTFILE2 of=/dev/null
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+log_must [ "x$(<$TESTDIR/$TESTFILE1)" = "x$FILE_CONTENTS" ]
+log_must [ "x$(<$TESTDIR/$TESTFILE2)" = "x$FILE_CONTENTS" ]
+
+log_pass "Removed device not in use after removal."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_errors.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_errors.ksh
new file mode 100755
index 000000000000..9d5143ef8b17
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_errors.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) 2014, 2017 by Delphix. All rights reserved.
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# DESCRIPTION:
+#
+# This test ensures the device removal is cancelled when hard IO
+# errors are encountered during the removal process. This is done
+# to ensure that when removing a device all of the data is copied.
+#
+# STRATEGY:
+#
+# 1. We create a pool with enough redundancy such that IO errors
+# will not result in the pool being suspended.
+# 2. We write some test data to the pool.
+# 3. We inject READ errors in to one half of the top-level mirror-0
+# vdev which is being removed. Then we start the removal process.
+# 4. Verify that the injected read errors cause the removal of
+# mirror-0 to be cancelled and that mirror-0 has not been removed.
+# 5. Clear the read fault injection.
+# 6. Repeat steps 3-6 above except inject WRITE errors on one of
+# child vdevs in the destination mirror-1.
+# 7. Lastly verify the pool data is still intact.
+#
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+DISK0=$TMPDIR/dsk0
+DISK1=$TMPDIR/dsk1
+DISK2=$TMPDIR/dsk2
+DISK3=$TMPDIR/dsk3
+
+log_must truncate -s $MINVDEVSIZE $DISK0 $DISK1
+log_must truncate -s $((MINVDEVSIZE * 4)) $DISK2 $DISK3
+
+function cleanup
+{
+ log_must zinject -c all
+ default_cleanup_noexit
+ log_must rm -f $DISK0 $DISK1 $DISK2 $DISK3
+}
+
+function wait_for_removing_cancel
+{
+ typeset pool=$1
+
+ log_must zpool wait -t remove $pool
+
+ #
+ # The pool state changes before the TXG finishes syncing; wait for
+ # the removal to be completed on disk.
+ #
+ sync_pool
+
+ log_mustnot is_pool_removed $pool
+ return 0
+}
+
+default_setup_noexit "mirror $DISK0 $DISK1 mirror $DISK2 $DISK3"
+log_onexit cleanup
+
+FILE_CONTENTS="Leeloo Dallas mul-ti-pass."
+
+echo $FILE_CONTENTS >$TESTDIR/$TESTFILE0
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+log_must file_write -o create -f $TESTDIR/$TESTFILE1 -b $((2**20)) -c $((2**8))
+
+# Flush the ARC to minimize cache effects.
+log_must zpool export $TESTPOOL
+log_must zpool import -d $TMPDIR $TESTPOOL
+
+# Verify that unexpected read errors automatically cancel the removal.
+log_must zinject -d $DISK0 -e io -T all -f 100 $TESTPOOL
+log_must zpool remove $TESTPOOL mirror-0
+log_must wait_for_removing_cancel $TESTPOOL
+log_must vdevs_in_pool $TESTPOOL mirror-0
+log_must zinject -c all
+
+# Flush the ARC to minimize cache effects.
+log_must zpool export $TESTPOOL
+log_must zpool import -d $TMPDIR $TESTPOOL
+
+# Verify that unexpected write errors automatically cancel the removal.
+log_must zinject -d $DISK3 -e io -T all -f 100 $TESTPOOL
+log_must zpool remove $TESTPOOL mirror-0
+log_must wait_for_removing_cancel $TESTPOOL
+log_must vdevs_in_pool $TESTPOOL mirror-0
+log_must zinject -c all
+
+log_must dd if=$TESTDIR/$TESTFILE0 of=/dev/null
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+log_must dd if=$TESTDIR/$TESTFILE1 of=/dev/null
+
+log_pass "Device not removed due to unexpected errors."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_export.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_export.ksh
new file mode 100755
index 000000000000..0ec358aadba9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_export.ksh
@@ -0,0 +1,47 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+function callback
+{
+ is_linux && test_removal_with_operation_kill
+ log_must zpool export $TESTPOOL
+
+ #
+ # We are concurrently starting dd processes that will
+ # create files in $TESTDIR. These could cause the import
+ # to fail because it can't mount on the filesystem on a
+ # non-empty directory. Therefore, remove the directory
+ # so that the dd process will fail.
+ #
+ log_must rm -rf $TESTDIR
+
+ log_must zpool import $TESTPOOL
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_pass "Can export and import pool during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_faulted.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_faulted.ksh
new file mode 100755
index 000000000000..44d222860b80
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_faulted.ksh
@@ -0,0 +1,104 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+# Copyright (c) 2018 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# DESCRIPTION:
+#
+# This test ensures that even when child vdevs are unavailable the
+# device removal process copies from readable source children to
+# writable destination children. This may be different than the
+# default mapping which preferentially pairs up source and destination
+# child vdevs based on their child ids.
+#
+# Default Mapping:
+# mirror-0 mirror-1
+# DISK0 (child 0) ------> DISK2 (child 0)
+# DISK1 (child 1) ------> DISK3 (child 1)
+#
+# We want to setup a scenario where the default mapping would make
+# it impossible to copy any data during the removal process. This
+# is done by faulting both the mirror-0 (child 0) source vdev and
+# mirror-1 (child 1) destination vdev. As shown below the default
+# mapping cannot be used due to the FAULTED vdevs. Verify that an
+# alternate mapping is selected and all the readable data is copied.
+#
+# Default Mapping (BAD):
+# mirror-0 mirror-1
+# DISK0 (FAULTED) ------> DISK2
+# DISK1 ----------------> DISK3 (FAULTED)
+#
+# Required Mapping (GOOD):
+# mirror-0 mirror-1
+# DISK0 (FAULTED) +---> DISK2
+# DISK1 ------------+ DISK3 (FAULTED)
+#
+# STRATEGY:
+#
+# 1. We create a pool with two top-level mirror vdevs.
+# 2. We write some test data to the pool.
+# 3. We fault two children to force the scenario described above.
+# 4. We remove the mirror-0 device.
+# 5. We verify that the device has been removed and that all of the
+# data is still intact.
+#
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+DISK0=$TMPDIR/dsk0
+DISK1=$TMPDIR/dsk1
+DISK2=$TMPDIR/dsk2
+DISK3=$TMPDIR/dsk3
+
+log_must truncate -s $MINVDEVSIZE $DISK0 $DISK1
+log_must truncate -s $((MINVDEVSIZE * 4)) $DISK2 $DISK3
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $DISK0 $DISK1 $DISK2 $DISK3
+}
+
+default_setup_noexit "mirror $DISK0 $DISK1 mirror $DISK2 $DISK3"
+log_onexit cleanup
+
+log_must zpool offline -f $TESTPOOL $DISK0
+log_must zpool offline -f $TESTPOOL $DISK3
+
+FILE_CONTENTS="Leeloo Dallas mul-ti-pass."
+
+echo $FILE_CONTENTS >$TESTDIR/$TESTFILE0
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+log_must file_write -o create -f $TESTDIR/$TESTFILE1 -b $((2**20)) -c $((2**7))
+sync_pool $TESTPOOL
+
+log_must zpool remove $TESTPOOL mirror-0
+log_must wait_for_removal $TESTPOOL
+log_mustnot vdevs_in_pool $TESTPOOL mirror-0
+
+verify_pool $TESTPOOL
+
+log_must dd if=$TESTDIR/$TESTFILE0 of=/dev/null
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+log_must dd if=$TESTDIR/$TESTFILE1 of=/dev/null
+
+log_pass "Can remove with faulted vdevs"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_ganging.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_ganging.ksh
new file mode 100755
index 000000000000..e3e635998efd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_ganging.ksh
@@ -0,0 +1,47 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+function cleanup
+{
+ log_must set_tunable64 METASLAB_FORCE_GANGING $((2**17 + 1))
+ default_cleanup_noexit
+}
+
+default_setup_noexit "$DISKS"
+log_must set_tunable64 METASLAB_FORCE_GANGING $((2**14))
+log_onexit cleanup
+
+FILE_CONTENTS="Leeloo Dallas mul-ti-pass."
+
+echo $FILE_CONTENTS >$TESTDIR/$TESTFILE0
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+log_must file_write -o create -f $TESTDIR/$TESTFILE1 -b $((2**20)) -c $((2**7))
+
+log_must zpool remove $TESTPOOL $REMOVEDISK
+log_must wait_for_removal $TESTPOOL
+log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
+
+log_must dd if=/$TESTDIR/$TESTFILE0 of=/dev/null
+log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+
+log_pass "Removed device not in use after removal."
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_remove.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_remove.ksh
new file mode 100755
index 000000000000..df7bc671994a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_remove.ksh
@@ -0,0 +1,35 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+function callback
+{
+ log_mustnot zpool remove $TESTPOOL $NOTREMOVEDISK
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_pass "Cannot remove a disk during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_scrub.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_scrub.ksh
new file mode 100755
index 000000000000..d96c1ce9de15
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_scrub.ksh
@@ -0,0 +1,29 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+test_removal_with_operation zpool scrub $TESTPOOL
+
+log_pass "Can use scrub during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_send.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_send.ksh
new file mode 100755
index 000000000000..59e66aca5256
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_send.ksh
@@ -0,0 +1,37 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+function callback
+{
+ create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+ log_must ksh -c \
+ "zfs send $TESTPOOL/$TESTFS@$TESTSNAP >/dev/null"
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_pass "Can use send during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_send_recv.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_send_recv.ksh
new file mode 100755
index 000000000000..c4b5f7e7686f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_send_recv.ksh
@@ -0,0 +1,38 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+function callback
+{
+ create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+ log_must ksh -o pipefail -c \
+ "zfs send $TESTPOOL/$TESTFS@$TESTSNAP | \
+ zfs recv $TESTPOOL/$TESTFS1"
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_pass "Can send and recv during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_snapshot.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_snapshot.ksh
new file mode 100755
index 000000000000..a4ec8ddfa6fa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_snapshot.ksh
@@ -0,0 +1,36 @@
+#! /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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+function callback
+{
+ create_snapshot $TESTPOOL/$TESTFS $TESTSNAP
+ destroy_snapshot $TESTPOOL/$TESTFS@$TESTSNAP
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_pass "Can create and destroy snapshot during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_write.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_write.ksh
new file mode 100755
index 000000000000..5d37b903e08c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_write.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) 2014 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+default_setup_noexit "$DISKS"
+log_onexit default_cleanup_noexit
+
+function callback
+{
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_pass "Can write to device during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/removal_with_zdb.ksh b/tests/zfs-tests/tests/functional/removal/removal_with_zdb.ksh
new file mode 100755
index 000000000000..5c469259a9ef
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/removal_with_zdb.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) 2014, 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+zdbout=${TMPDIR:-$TEST_BASE_DIR}/zdbout.$$
+
+if is_linux; then
+ log_unsupported "ZDB fails during concurrent pool activity."
+fi
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $zdbout
+}
+
+default_setup_noexit "$DISKS"
+log_onexit cleanup
+FIRSTDISK=${DISKS%% *}
+
+DISKPATH=/dev
+case $FIRSTDISK in
+ /*)
+ DISKPATH=$(dirname $FIRSTDISK)
+ ;;
+esac
+
+function callback
+{
+ typeset count=$1
+ typeset zdbstat
+
+ log_must zpool set cachefile=none $TESTPOOL
+ zdb -e -p $DISKPATH -cudi $TESTPOOL >$zdbout 2>&1
+ zdbstat=$?
+ log_must zpool set cachefile= $TESTPOOL
+ if [[ $zdbstat != 0 ]]; then
+ log_note "Output: zdb -e -p $DISKPATH -cudi $TESTPOOL"
+ cat $zdbout
+ log_note "zdb detected errors with exist status $zdbstat."
+ fi
+ log_note "zdb -e -p $DISKPATH -cudi $TESTPOOL >zdbout 2>&1"
+ return 0
+}
+
+test_removal_with_operation callback
+
+log_must zpool set cachefile=none $TESTPOOL
+zdb -e -p $DISKPATH -cudi $TESTPOOL >$zdbout 2>&1
+zdbstat=$?
+log_must zpool set cachefile= $TESTPOOL
+if [[ $zdbstat != 0 ]]; then
+ log_note "Output following removal: zdb -cudi $TESTPOOL"
+ cat $zdbout
+ log_fail "zdb detected errors with exit status " \
+ "$zdbstat following removal."
+fi
+
+log_pass "Can use zdb during removal"
diff --git a/tests/zfs-tests/tests/functional/removal/remove_expanded.ksh b/tests/zfs-tests/tests/functional/removal/remove_expanded.ksh
new file mode 100755
index 000000000000..e7e63b705575
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/remove_expanded.ksh
@@ -0,0 +1,89 @@
+#! /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) 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# BACKGROUND:
+#
+# ztest hit an issue where it ran zdb and zdb failed because
+# it couldn't access some indirect mappings at the end of a
+# vdev. The issue was that the vdev's ms_shift had changed after
+# it was removed by the addition of another vdev. This test is
+# a regression test for ensuring this case doesn't come up again.
+#
+
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+DISK0=$TMPDIR/dsk0
+DISK1=$TMPDIR/dsk1
+DISK2=$TMPDIR/dsk2
+
+log_must truncate -s $MINVDEVSIZE $DISK0
+log_must truncate -s $(($MINVDEVSIZE * 3)) $DISK1
+log_must truncate -s $MINVDEVSIZE $DISK2
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $DISK0 $DISK1 $DISK2
+}
+
+#
+# Setup the pool with one disk .
+#
+log_must default_setup_noexit "$DISK0"
+log_onexit cleanup
+
+#
+# Expand vdev.
+#
+log_must truncate -s $(($MINVDEVSIZE * 2)) $DISK0
+log_must zpool reopen $TESTPOOL
+log_must zpool online -e $TESTPOOL $DISK0
+
+#
+# Fill up the whole vdev.
+#
+dd if=/dev/urandom of=$TESTDIR/$TESTFILE0 bs=8M
+
+#
+# Add another vdev and remove the first vdev creating indirect
+# mappings for nearly all the allocatable space from the first
+# vdev. Wait for removal to finish.
+#
+log_must zpool add $TESTPOOL $DISK1
+log_must zpool remove $TESTPOOL $DISK0
+log_must wait_for_removal $TESTPOOL
+
+#
+# Add a new vdev that will trigger a change in the config.
+# Run sync once to ensure that the config actually changed.
+#
+log_must zpool add $TESTPOOL $DISK2
+log_must sync
+
+#
+# Ensure that zdb does not find any problems with this.
+#
+log_must zdb $TESTPOOL
+
+log_pass "Removal of expanded vdev doesn't cause any problems."
diff --git a/tests/zfs-tests/tests/functional/removal/remove_indirect.ksh b/tests/zfs-tests/tests/functional/removal/remove_indirect.ksh
new file mode 100755
index 000000000000..c4ba0d9ac564
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/remove_indirect.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 2019, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+#
+# DESCRIPTION:
+# Device removal cannot remove non-concrete vdevs
+#
+# STRATEGY:
+# 1. Create a pool with removable devices
+# 2. Remove a top-level device
+# 3. Verify we can't remove the "indirect" vdev created by the first removal
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $TESTPOOL
+ log_must rm -f $TEST_BASE_DIR/device-{1,2,3}
+}
+
+log_assert "Device removal should not be able to remove non-concrete vdevs"
+log_onexit cleanup
+
+# 1. Create a pool with removable devices
+truncate -s $MINVDEVSIZE $TEST_BASE_DIR/device-{1,2,3}
+zpool create $TESTPOOL $TEST_BASE_DIR/device-{1,2,3}
+
+# 2. Remove a top-level device
+log_must zpool remove $TESTPOOL $TEST_BASE_DIR/device-1
+log_must wait_for_removal $TESTPOOL
+
+# 3. Verify we can't remove the "indirect" vdev created by the first removal
+INDIRECT_VDEV=$(zpool list -v -g $TESTPOOL | awk '{if ($2 == "-") { print $1; exit} }')
+log_must test -n "$INDIRECT_VDEV"
+log_mustnot zpool remove $TESTPOOL $INDIRECT_VDEV
+
+log_pass "Device removal cannot remove non-concrete vdevs"
diff --git a/tests/zfs-tests/tests/functional/removal/remove_mirror.ksh b/tests/zfs-tests/tests/functional/removal/remove_mirror.ksh
new file mode 100755
index 000000000000..06335b70360a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/remove_mirror.ksh
@@ -0,0 +1,57 @@
+#! /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) 2014, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+
+DISK1="$TMPDIR/dsk1"
+DISK2="$TMPDIR/dsk2"
+DISK3="$TMPDIR/dsk3"
+DISKS="$DISK1 $DISK2 $DISK3"
+
+log_must mkfile $(($MINVDEVSIZE * 2)) $DISK1
+log_must mkfile $(($MINVDEVSIZE * 2)) $DISK2
+log_must mkfile $(($MINVDEVSIZE * 2)) $DISK3
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $DISKS
+}
+
+log_must default_setup_noexit "$DISK1 mirror $DISK2 $DISK3"
+log_onexit cleanup
+
+# Attempt to remove the non mirrored disk.
+log_must zpool remove $TESTPOOL $DISK1
+
+# Attempt to remove one of the disks in the mirror.
+log_mustnot zpool remove $TESTPOOL $DISK2
+log_must wait_for_removal $TESTPOOL
+
+# Add back the first disk.
+log_must zpool add $TESTPOOL $DISK1
+
+# Now attempt to remove the mirror.
+log_must zpool remove $TESTPOOL mirror-1
+
+log_pass "Removal will succeed for top level vdev(s)."
diff --git a/tests/zfs-tests/tests/functional/removal/remove_mirror_sanity.ksh b/tests/zfs-tests/tests/functional/removal/remove_mirror_sanity.ksh
new file mode 100755
index 000000000000..4473771521ba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/remove_mirror_sanity.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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+DISK1=$(echo $DISKS | awk '{print $1}')
+DISK2=$(echo $DISKS | awk '{print $2}')
+DISK3=$(echo $DISKS | awk '{print $3}')
+DISKS="$DISK1 $DISK2 $DISK3"
+
+log_must default_setup_noexit "$DISK1 mirror $DISK2 $DISK3"
+log_onexit default_cleanup_noexit
+
+WORDS_FILE1="/usr/dict/words"
+WORDS_FILE2="/usr/share/dict/words"
+FILE_CONTENTS="Leeloo Dallas mul-ti-pass."
+
+if [[ -f $WORDS_FILE1 ]]; then
+ log_must cp $WORDS_FILE1 $TESTDIR
+elif [[ -f $WORDS_FILE2 ]]; then
+ log_must cp $WORDS_FILE2 $TESTDIR
+else
+ echo $FILE_CONTENTS >$TESTDIR/$TESTFILE0
+ log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+fi
+
+log_must zpool remove $TESTPOOL mirror-1
+log_must wait_for_removal $TESTPOOL
+log_mustnot vdevs_in_pool $TESTPOOL mirror-1
+
+if [[ -f $WORDS_FILE1 ]]; then
+ log_must diff $WORDS_FILE1 $TESTDIR/words
+elif [[ -f $WORDS_FILE2 ]]; then
+ log_must diff $WORDS_FILE2 $TESTDIR/words
+else
+ log_must dd if=/$TESTDIR/$TESTFILE0 of=/dev/null
+ log_must [ "x$(<$TESTDIR/$TESTFILE0)" = "x$FILE_CONTENTS" ]
+fi
+
+log_pass "Removed top-level mirror device not in use after removal."
diff --git a/tests/zfs-tests/tests/functional/removal/remove_raidz.ksh b/tests/zfs-tests/tests/functional/removal/remove_raidz.ksh
new file mode 100755
index 000000000000..98d4536a148d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/removal/remove_raidz.ksh
@@ -0,0 +1,50 @@
+#! /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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/removal/removal.kshlib
+
+TMPDIR=${TMPDIR:-$TEST_BASE_DIR}
+log_must mkfile $MINVDEVSIZE $TMPDIR/dsk1
+log_must mkfile $MINVDEVSIZE $TMPDIR/dsk2
+log_must mkfile $MINVDEVSIZE $TMPDIR/dsk3
+DISKS1="$TMPDIR/dsk1"
+DISKS2="$TMPDIR/dsk2 $TMPDIR/dsk3"
+DISKS="$DISKS1 $DISKS2"
+
+function cleanup
+{
+ default_cleanup_noexit
+ log_must rm -f $DISKS
+}
+
+log_must default_setup_noexit "$DISKS1 raidz $DISKS2"
+log_onexit cleanup
+
+# Attempt to remove the non raidz disk.
+log_mustnot zpool remove $TESTPOOL $TMPDIR/dsk1
+
+# Attempt to remove one of the raidz disks.
+log_mustnot zpool remove $TESTPOOL $TMPDIR/dsk2
+
+# Attempt to remove the raidz.
+log_mustnot zpool remove $TESTPOOL raidz1-1
+
+log_pass "Removal will not succeed if there is a top level mirror."
diff --git a/tests/zfs-tests/tests/functional/rename_dirs/Makefile.am b/tests/zfs-tests/tests/functional/rename_dirs/Makefile.am
new file mode 100644
index 000000000000..029daf1f564b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rename_dirs/Makefile.am
@@ -0,0 +1,5 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/rename_dirs
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ rename_dirs_001_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/rename_dirs/cleanup.ksh b/tests/zfs-tests/tests/functional/rename_dirs/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rename_dirs/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/rename_dirs/rename_dirs_001_pos.ksh b/tests/zfs-tests/tests/functional/rename_dirs/rename_dirs_001_pos.ksh
new file mode 100755
index 000000000000..d7b6de1a2e01
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rename_dirs/rename_dirs_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Create two directory trees in ZFS filesystem, and concurrently rename
+# directory across the two trees. ZFS should be able to handle the race
+# situation.
+#
+# STRATEGY:
+# 1. Create a ZFS filesystem
+# 2. Make two directory tree in the zfs file system
+# 3. Continually rename directory from one tree to another tree in two process
+# 4. After the specified time duration, the system should not be panic.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must rm -rf $TESTDIR/*
+}
+
+log_assert "ZFS can handle race directory rename operation."
+
+log_onexit cleanup
+
+cd $TESTDIR
+mkdir -p 1/2/3/4/5 a/b/c/d/e
+
+rename_dir &
+
+sleep 10
+typeset -i retval=1
+pgrep -x rename_dir >/dev/null 2>&1
+retval=$?
+if (( $retval == 0 )); then
+ pkill -9 -x rename_dir >/dev/null 2>&1
+fi
+
+log_pass "ZFS handle race directory rename operation as expected."
diff --git a/tests/zfs-tests/tests/functional/rename_dirs/setup.ksh b/tests/zfs-tests/tests/functional/rename_dirs/setup.ksh
new file mode 100755
index 000000000000..fc5cec3063a6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rename_dirs/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/replacement/Makefile.am b/tests/zfs-tests/tests/functional/replacement/Makefile.am
new file mode 100644
index 000000000000..fe6e4912198d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/Makefile.am
@@ -0,0 +1,21 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/replacement
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ attach_import.ksh \
+ attach_multiple.ksh \
+ attach_rebuild.ksh \
+ attach_resilver.ksh \
+ detach.ksh \
+ rebuild_disabled_feature.ksh \
+ rebuild_multiple.ksh \
+ rebuild_raidz.ksh \
+ replace_import.ksh \
+ replace_rebuild.ksh \
+ replace_resilver.ksh \
+ resilver_restart_001.ksh \
+ resilver_restart_002.ksh \
+ scrub_cancel.ksh
+
+dist_pkgdata_DATA = \
+ replacement.cfg
diff --git a/tests/zfs-tests/tests/functional/replacement/attach_import.ksh b/tests/zfs-tests/tests/functional/replacement/attach_import.ksh
new file mode 100755
index 000000000000..e2749b164efe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/attach_import.ksh
@@ -0,0 +1,67 @@
+#!/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, Datto Inc. All rights reserved.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# Description:
+# Verify that on import an in progress attach operation is resumed.
+#
+# Strategy:
+# 1. For both healing and sequential resilvering.
+# a. Create a pool
+# b. Add a vdev with 'zpool attach' and resilver (-s) it.
+# c. Export the pool
+# d. Import the pool
+# e. Verify the 'zpool attach' resumed resilvering
+# f. Destroy the pool
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]}
+}
+
+log_assert "Verify attach is resumed on import"
+
+ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
+
+log_onexit cleanup
+
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]}
+
+# Verify healing and sequential resilver resume on import.
+for arg in "" "-s"; do
+ log_must zpool create -f $TESTPOOL1 ${VDEV_FILES[0]}
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+ log_must zpool attach $arg $TESTPOOL1 ${VDEV_FILES[0]} ${VDEV_FILES[1]}
+ log_must is_pool_resilvering $TESTPOOL1
+ log_must zpool export $TESTPOOL1
+ log_must zpool import -d $TEST_BASE_DIR $TESTPOOL1
+ log_must is_pool_resilvering $TESTPOOL1
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS $ORIG_SCAN_SUSPEND_PROGRESS
+ log_must zpool wait -t resilver $TESTPOOL1
+ log_must is_pool_resilvered $TESTPOOL1
+ destroy_pool $TESTPOOL1
+done
+
+log_pass "Verify attach is resumed on import"
diff --git a/tests/zfs-tests/tests/functional/replacement/attach_multiple.ksh b/tests/zfs-tests/tests/functional/replacement/attach_multiple.ksh
new file mode 100755
index 000000000000..b3192b2bfbda
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/attach_multiple.ksh
@@ -0,0 +1,111 @@
+#!/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, Datto Inc. All rights reserved.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# Description:
+# Verify that attach/detach work while resilvering and attaching
+# multiple vdevs.
+#
+# Strategy:
+# 1. Create a single vdev pool
+# 2. While healing or sequential resilvering:
+# a. Attach a vdev to convert the pool to a mirror.
+# b. Attach a vdev to convert the pool to a 3-way mirror.
+# c. Verify the original vdev cannot be removed (no redundant copies)
+# d. Detach a vdev. Healing and sequential resilver remain running.
+# e. Detach a vdev. Healing resilver remains running, sequential
+# resilver is canceled.
+# f. Wait for resilver to complete.
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]}
+}
+
+log_assert "Verify attach/detech with multiple vdevs"
+
+ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
+
+log_onexit cleanup
+
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]}
+
+# Verify resilver resumes on import.
+log_must zpool create -f $TESTPOOL1 ${VDEV_FILES[0]}
+
+for replace_mode in "healing" "sequential"; do
+ #
+ # Resilvers abort the dsl_scan and reconfigure it for resilvering.
+ # Rebuilds cancel the dsl_scan and start the vdev_rebuild thread.
+ #
+ if [[ "$replace_mode" = "healing" ]]; then
+ flags=""
+ else
+ flags="-s"
+ fi
+
+ log_mustnot is_pool_resilvering $TESTPOOL1
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+ # Attach first vdev (stripe -> mirror)
+ log_must zpool attach $flags $TESTPOOL1 \
+ ${VDEV_FILES[0]} ${VDEV_FILES[1]}
+ log_must is_pool_resilvering $TESTPOOL1
+
+ # Attach second vdev (2-way -> 3-way mirror)
+ log_must zpool attach $flags $TESTPOOL1 \
+ ${VDEV_FILES[1]} ${VDEV_FILES[2]}
+ log_must is_pool_resilvering $TESTPOOL1
+
+ # Original vdev cannot be detached until there is sufficent redundancy.
+ log_mustnot zpool detach $TESTPOOL1 ${VDEV_FILES[0]}
+
+ # Detach first vdev (resilver keeps running)
+ log_must zpool detach $TESTPOOL1 ${VDEV_FILES[1]}
+ log_must is_pool_resilvering $TESTPOOL1
+
+ #
+ # Detach second vdev. There's a difference in behavior between
+ # healing and sequential resilvers. A healing resilver will not be
+ # cancelled even though there's nothing on the original vdev which
+ # needs to be rebuilt. A sequential resilver on the otherhand is
+ # canceled when returning to a non-redundant striped layout. At
+ # some point the healing resilver behavior should be updated to match
+ # the sequential resilver behavior.
+ #
+ log_must zpool detach $TESTPOOL1 ${VDEV_FILES[2]}
+
+ if [[ "$replace_mode" = "healing" ]]; then
+ log_must is_pool_resilvering $TESTPOOL1
+ else
+ log_mustnot is_pool_resilvering $TESTPOOL1
+ fi
+
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ log_must zpool wait $TESTPOOL1
+done
+
+log_pass "Verify attach/detech with multiple vdevs"
diff --git a/tests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh b/tests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh
new file mode 100755
index 000000000000..e9427c7adc9d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/attach_rebuild.ksh
@@ -0,0 +1,173 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Attaching disks during I/O should pass for supported pools.
+#
+# STRATEGY:
+# 1. Create multidisk pools (stripe/mirror/raidz) and
+# start some random I/O
+# 2. Attach a disk to the pool.
+# 3. Verify the integrity of the file system and the resilvering.
+#
+# NOTE: Raidz does not support the sequential resilver (-s) option.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if [[ -n "$child_pids" ]]; then
+ for wait_pid in $child_pids; do
+ kill $wait_pid
+ done
+ fi
+
+ if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+ fi
+
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Replacing a disk during I/O completes."
+
+options=""
+options_display="default options"
+
+log_onexit cleanup
+
+[[ -n "$HOLES_FILESIZE" ]] && options=" $options -f $HOLES_FILESIZE "
+
+[[ -n "$HOLES_BLKSIZE" ]] && options="$options -b $HOLES_BLKSIZE "
+
+[[ -n "$HOLES_COUNT" ]] && options="$options -c $HOLES_COUNT "
+
+[[ -n "$HOLES_SEED" ]] && options="$options -s $HOLES_SEED "
+
+[[ -n "$HOLES_FILEOFFSET" ]] && options="$options -o $HOLES_FILEOFFSET "
+
+options="$options -r "
+
+[[ -n "$options" ]] && options_display=$options
+
+child_pids=""
+
+function attach_test
+{
+ typeset -i iters=2
+ typeset -i index=0
+ typeset opt=$1
+ typeset disk1=$2
+ typeset disk2=$3
+
+ typeset i=0
+ while [[ $i -lt $iters ]]; do
+ log_note "Invoking file_trunc with: $options_display"
+ file_trunc $options $TESTDIR/$TESTFILE.$i &
+ typeset pid=$!
+
+ sleep 1
+
+ child_pids="$child_pids $pid"
+ ((i = i + 1))
+ done
+
+ log_must zpool attach -sw $opt $TESTPOOL1 $disk1 $disk2
+
+ for wait_pid in $child_pids; do
+ kill $wait_pid
+ done
+ child_pids=""
+
+ log_must zpool export $TESTPOOL1
+ log_must zpool import -d $TESTDIR $TESTPOOL1
+ log_must zfs umount $TESTPOOL1/$TESTFS1
+ log_must zdb -cdui $TESTPOOL1/$TESTFS1
+ log_must zfs mount $TESTPOOL1/$TESTFS1
+ verify_pool $TESTPOOL1
+}
+
+specials_list=""
+i=0
+while [[ $i != 3 ]]; do
+ truncate -s $MINVDEVSIZE $TESTDIR/$TESTFILE1.$i
+ specials_list="$specials_list $TESTDIR/$TESTFILE1.$i"
+
+ ((i = i + 1))
+done
+
+#
+# Create a replacement disk special file.
+#
+truncate -s $MINVDEVSIZE $TESTDIR/$REPLACEFILE
+
+for op in "" "-f"; do
+ create_pool $TESTPOOL1 mirror $specials_list
+ log_must zfs create $TESTPOOL1/$TESTFS1
+ log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+ attach_test "$opt" $TESTDIR/$TESTFILE1.1 $TESTDIR/$REPLACEFILE
+
+ zpool iostat -v $TESTPOOL1 | grep "$REPLACEFILE"
+ if [[ $? -ne 0 ]]; then
+ log_fail "$REPLACEFILE is not present."
+ fi
+
+ destroy_pool $TESTPOOL1
+done
+
+log_note "Verify 'zpool attach' fails with non-mirrors."
+
+for type in "" "raidz" "raidz1"; do
+ for op in "" "-f"; do
+ create_pool $TESTPOOL1 $type $specials_list
+ log_must zfs create $TESTPOOL1/$TESTFS1
+ log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+ log_mustnot zpool attach -s "$opt" $TESTDIR/$TESTFILE1.1 \
+ $TESTDIR/$REPLACEFILE
+
+ zpool iostat -v $TESTPOOL1 | grep "$REPLACEFILE"
+ if [[ $? -eq 0 ]]; then
+ log_fail "$REPLACEFILE should not be present."
+ fi
+
+ destroy_pool $TESTPOOL1
+ done
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/replacement/attach_resilver.ksh b/tests/zfs-tests/tests/functional/replacement/attach_resilver.ksh
new file mode 100755
index 000000000000..4261d4d67cc0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/attach_resilver.ksh
@@ -0,0 +1,172 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Attaching disks during I/O should pass for supported pools.
+#
+# STRATEGY:
+# 1. Create multidisk pools (stripe/mirror/raidz) and
+# start some random I/O
+# 2. Attach a disk to the pool.
+# 3. Verify the integrity of the file system and the resilvering.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if [[ -n "$child_pids" ]]; then
+ for wait_pid in $child_pids
+ do
+ kill $wait_pid
+ done
+ fi
+
+ if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+ fi
+
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Replacing a disk during I/O completes."
+
+options=""
+options_display="default options"
+
+log_onexit cleanup
+
+[[ -n "$HOLES_FILESIZE" ]] && options=" $options -f $HOLES_FILESIZE "
+
+[[ -n "$HOLES_BLKSIZE" ]] && options="$options -b $HOLES_BLKSIZE "
+
+[[ -n "$HOLES_COUNT" ]] && options="$options -c $HOLES_COUNT "
+
+[[ -n "$HOLES_SEED" ]] && options="$options -s $HOLES_SEED "
+
+[[ -n "$HOLES_FILEOFFSET" ]] && options="$options -o $HOLES_FILEOFFSET "
+
+options="$options -r "
+
+[[ -n "$options" ]] && options_display=$options
+
+child_pids=""
+
+function attach_test
+{
+ typeset -i iters=2
+ typeset -i index=0
+ typeset opt=$1
+ typeset disk1=$2
+ typeset disk2=$3
+
+ typeset i=0
+ while [[ $i -lt $iters ]]; do
+ log_note "Invoking file_trunc with: $options_display"
+ file_trunc $options $TESTDIR/$TESTFILE.$i &
+ typeset pid=$!
+
+ sleep 1
+
+ child_pids="$child_pids $pid"
+ ((i = i + 1))
+ done
+
+ log_must zpool attach -w $opt $TESTPOOL1 $disk1 $disk2
+
+ for wait_pid in $child_pids
+ do
+ kill $wait_pid
+ done
+ child_pids=""
+
+ log_must zpool export $TESTPOOL1
+ log_must zpool import -d $TESTDIR $TESTPOOL1
+ log_must zfs umount $TESTPOOL1/$TESTFS1
+ log_must zdb -cdui $TESTPOOL1/$TESTFS1
+ log_must zfs mount $TESTPOOL1/$TESTFS1
+ verify_pool $TESTPOOL1
+}
+
+specials_list=""
+i=0
+while [[ $i != 3 ]]; do
+ truncate -s $MINVDEVSIZE $TESTDIR/$TESTFILE1.$i
+ specials_list="$specials_list $TESTDIR/$TESTFILE1.$i"
+
+ ((i = i + 1))
+done
+
+#
+# Create a replacement disk special file.
+#
+truncate -s $MINVDEVSIZE $TESTDIR/$REPLACEFILE
+
+for op in "" "-f"; do
+ create_pool $TESTPOOL1 mirror $specials_list
+ log_must zfs create $TESTPOOL1/$TESTFS1
+ log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+ attach_test "$opt" $TESTDIR/$TESTFILE1.1 $TESTDIR/$REPLACEFILE
+
+ zpool iostat -v $TESTPOOL1 | grep "$REPLACEFILE"
+ if [[ $? -ne 0 ]]; then
+ log_fail "$REPLACEFILE is not present."
+ fi
+
+ destroy_pool $TESTPOOL1
+done
+
+log_note "Verify 'zpool attach' fails with non-mirrors."
+
+for type in "" "raidz" "raidz1"; do
+ for op in "" "-f"; do
+ create_pool $TESTPOOL1 $type $specials_list
+ log_must zfs create $TESTPOOL1/$TESTFS1
+ log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+ log_mustnot zpool attach "$opt" $TESTDIR/$TESTFILE1.1 \
+ $TESTDIR/$REPLACEFILE
+
+ zpool iostat -v $TESTPOOL1 | grep "$REPLACEFILE"
+ if [[ $? -eq 0 ]]; then
+ log_fail "$REPLACEFILE should not be present."
+ fi
+
+ destroy_pool $TESTPOOL1
+ done
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/replacement/cleanup.ksh b/tests/zfs-tests/tests/functional/replacement/cleanup.ksh
new file mode 100755
index 000000000000..b81a372638e3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/replacement/detach.ksh b/tests/zfs-tests/tests/functional/replacement/detach.ksh
new file mode 100755
index 000000000000..aa3ec4f7a75d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/detach.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 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/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Detaching disks during I/O should pass for supported pools.
+#
+# STRATEGY:
+# 1. Create multidisk pools (stripe/mirror/raidz) and
+# start some random I/O
+# 2. Detach a disk from the pool.
+# 3. Verify the integrity of the file system and the resilvering.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if [[ -n "$child_pids" ]]; then
+ for wait_pid in $child_pids
+ do
+ kill $wait_pid
+ done
+ fi
+
+ if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+ fi
+
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Replacing a disk during I/O completes."
+
+options=""
+options_display="default options"
+
+log_onexit cleanup
+
+[[ -n "$HOLES_FILESIZE" ]] && options=" $options -f $HOLES_FILESIZE "
+
+[[ -n "$HOLES_BLKSIZE" ]] && options="$options -b $HOLES_BLKSIZE "
+
+[[ -n "$HOLES_COUNT" ]] && options="$options -c $HOLES_COUNT "
+
+[[ -n "$HOLES_SEED" ]] && options="$options -s $HOLES_SEED "
+
+[[ -n "$HOLES_FILEOFFSET" ]] && options="$options -o $HOLES_FILEOFFSET "
+
+ptions="$options -r "
+
+[[ -n "$options" ]] && options_display=$options
+
+child_pids=""
+
+function detach_test
+{
+ typeset -i iters=2
+ typeset -i index=0
+ typeset disk1=$1
+
+ typeset i=0
+ while [[ $i -lt $iters ]]; do
+ log_note "Invoking file_trunc with: $options_display"
+ file_trunc $options $TESTDIR/$TESTFILE.$i &
+ typeset pid=$!
+
+ sleep 1
+
+ child_pids="$child_pids $pid"
+ ((i = i + 1))
+ done
+
+ log_must zpool detach $TESTPOOL1 $disk1
+
+ sleep 10
+
+ for wait_pid in $child_pids
+ do
+ kill $wait_pid
+ done
+ child_pids=""
+
+ log_must zpool export $TESTPOOL1
+ log_must zpool import -d $TESTDIR $TESTPOOL1
+ log_must zfs umount $TESTPOOL1/$TESTFS1
+ log_must zdb -cdui $TESTPOOL1/$TESTFS1
+ log_must zfs mount $TESTPOOL1/$TESTFS1
+}
+
+specials_list=""
+i=0
+while [[ $i != 3 ]]; do
+ truncate -s $MINVDEVSIZE $TESTDIR/$TESTFILE1.$i
+ specials_list="$specials_list $TESTDIR/$TESTFILE1.$i"
+
+ ((i = i + 1))
+done
+
+create_pool $TESTPOOL1 mirror $specials_list
+log_must zfs create $TESTPOOL1/$TESTFS1
+log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+detach_test $TESTDIR/$TESTFILE1.1
+
+zpool iostat -v $TESTPOOL1 | grep "$TESTFILE1.1"
+if [[ $? -eq 0 ]]; then
+ log_fail "$TESTFILE1.1 should no longer be present."
+fi
+
+destroy_pool $TESTPOOL1
+
+log_note "Verify 'zpool detach' fails with non-mirrors."
+
+for type in "" "raidz" "raidz1"; do
+ create_pool $TESTPOOL1 $type $specials_list
+ log_must zfs create $TESTPOOL1/$TESTFS1
+ log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+ log_mustnot zpool detach $TESTDIR/$TESTFILE1.1
+
+ zpool iostat -v $TESTPOOL1 | grep "$TESTFILE1.1"
+ if [[ $? -ne 0 ]]; then
+ log_fail "$TESTFILE1.1 is not present."
+ fi
+
+ destroy_pool $TESTPOOL1
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/replacement/rebuild_disabled_feature.ksh b/tests/zfs-tests/tests/functional/replacement/rebuild_disabled_feature.ksh
new file mode 100755
index 000000000000..d17d83b78333
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/rebuild_disabled_feature.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) 2019, Datto Inc. All rights reserved.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# Description:
+# Verify device_rebuild feature flags.
+#
+# Strategy:
+# 1. Create a pool with all features disabled.
+# 2. Verify 'zpool replace -s' fails and the feature is disabled.
+# 3. Enable the device_rebuild feature.
+# 4. Verify 'zpool replace -s' works and the feature is active.
+# 5. Wait for the feature to return to enabled.
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+}
+
+function check_feature_flag
+{
+ feature=$1
+ pool=$2
+ expected_value=$3
+
+ value="$(zpool get -H -o property,value all $pool | \
+ egrep "$feature" | awk '{print $2}')"
+ if [ "$value" = "$expected_value" ]; then
+ log_note "$feature verified to be $value"
+ else
+ log_fail "$feature should be $expected_value but is $value"
+ fi
+}
+
+log_assert "Verify device_rebuild feature flags."
+
+ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
+
+log_onexit cleanup
+
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+log_must zpool create -d $TESTPOOL1 ${VDEV_FILES[@]}
+
+log_mustnot zpool replace -s $TESTPOOL1 ${VDEV_FILES[1]} $SPARE_VDEV_FILE
+check_feature_flag "feature@device_rebuild" "$TESTPOOL1" "disabled"
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+log_must zpool set feature@device_rebuild=enabled $TESTPOOL1
+log_must zpool replace -s $TESTPOOL1 ${VDEV_FILES[1]} $SPARE_VDEV_FILE
+check_feature_flag "feature@device_rebuild" "$TESTPOOL1" "active"
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS $ORIG_SCAN_SUSPEND_PROGRESS
+log_must zpool wait -t resilver $TESTPOOL1
+check_feature_flag "feature@device_rebuild" "$TESTPOOL1" "enabled"
+
+log_pass "Verify device_rebuild feature flags."
diff --git a/tests/zfs-tests/tests/functional/replacement/rebuild_multiple.ksh b/tests/zfs-tests/tests/functional/replacement/rebuild_multiple.ksh
new file mode 100755
index 000000000000..7775cbff4db8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/rebuild_multiple.ksh
@@ -0,0 +1,126 @@
+#!/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.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Sequential reconstruction (unlike healing reconstruction) operate on the
+# top-level vdev. This means that a sequential resilver operation can be
+# started/stopped on a different top-level vdev without impacting other
+# sequential resilvers.
+#
+# STRATEGY:
+# 1. Create a mirrored pool.
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE $SPARE_VDEV_FILE2
+}
+
+function check_history
+{
+ pool=$1
+ msg=$2
+ exp=$3
+
+ count=$(zpool history -i $pool | grep "rebuild" | grep -c "$msg")
+ if [[ "$count" -ne "$exp" ]]; then
+ log_fail "Expected $exp rebuild '$msg' messages, found $count"
+ else
+ log_note "Found $count/$exp rebuild '$msg' messages"
+ fi
+}
+
+log_assert "Rebuilds operate on the top-level vdevs"
+
+ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
+
+log_onexit cleanup
+
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]} \
+ $SPARE_VDEV_FILE $SPARE_VDEV_FILE2
+
+# Verify two sequential resilvers can run concurrently.
+log_must zpool create -f $TESTPOOL1 \
+ mirror ${VDEV_FILES[0]} ${VDEV_FILES[1]} \
+ mirror ${VDEV_FILES[2]} ${VDEV_FILES[3]}
+log_must zfs create $TESTPOOL1/$TESTFS
+
+mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS)
+log_must dd if=/dev/urandom of=$mntpnt/file bs=1M count=32
+log_must zpool sync $TESTPOOL1
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+log_must zpool replace -s $TESTPOOL1 ${VDEV_FILES[1]} $SPARE_VDEV_FILE
+log_must zpool replace -s $TESTPOOL1 ${VDEV_FILES[3]} $SPARE_VDEV_FILE2
+
+check_history $TESTPOOL1 "started" 2
+check_history $TESTPOOL1 "reset" 0
+check_history $TESTPOOL1 "complete" 0
+check_history $TESTPOOL1 "canceled" 0
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS $ORIG_SCAN_SUSPEND_PROGRESS
+log_must zpool wait -t resilver $TESTPOOL1
+
+check_history $TESTPOOL1 "complete" 2
+destroy_pool $TESTPOOL1
+
+# Verify canceling one resilver (zpool detach) does not impact others.
+log_must zpool create -f $TESTPOOL1 \
+ mirror ${VDEV_FILES[0]} ${VDEV_FILES[1]} \
+ mirror ${VDEV_FILES[2]} ${VDEV_FILES[3]}
+log_must zfs create $TESTPOOL1/$TESTFS
+
+mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS)
+log_must dd if=/dev/urandom of=$mntpnt/file bs=1M count=32
+log_must zpool sync $TESTPOOL1
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+log_must zpool replace -s $TESTPOOL1 ${VDEV_FILES[1]} $SPARE_VDEV_FILE
+log_must zpool replace -s $TESTPOOL1 ${VDEV_FILES[3]} $SPARE_VDEV_FILE2
+
+check_history $TESTPOOL1 "started" 2
+check_history $TESTPOOL1 "reset" 0
+check_history $TESTPOOL1 "complete" 0
+check_history $TESTPOOL1 "canceled" 0
+
+log_must zpool detach $TESTPOOL1 $SPARE_VDEV_FILE2
+
+check_history $TESTPOOL1 "complete" 0
+check_history $TESTPOOL1 "canceled" 1
+
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS $ORIG_SCAN_SUSPEND_PROGRESS
+log_must zpool wait -t resilver $TESTPOOL1
+
+check_history $TESTPOOL1 "complete" 1
+check_history $TESTPOOL1 "canceled" 1
+destroy_pool $TESTPOOL1
+
+log_pass "Rebuilds operate on the top-level vdevs"
diff --git a/tests/zfs-tests/tests/functional/replacement/rebuild_raidz.ksh b/tests/zfs-tests/tests/functional/replacement/rebuild_raidz.ksh
new file mode 100755
index 000000000000..c919b44b21cc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/rebuild_raidz.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, Datto Inc. All rights reserved.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Executing 'zpool replace -s' for raidz vdevs failed. Sequential
+# resilvers are only allowed for stripe/mirror pools.
+#
+# STRATEGY:
+# 1. Create a raidz pool, verify 'zpool replace -s' fails
+# 2. Create a stripe/mirror pool, verify 'zpool replace -s' passes
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+}
+
+log_assert "Sequential resilver is not allowed for raidz vdevs"
+
+ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
+
+log_onexit cleanup
+
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+
+# raidz[1-3]
+for vdev_type in "raidz" "raidz2" "raidz3"; do
+ log_must zpool create -f $TESTPOOL1 $vdev_type ${VDEV_FILES[@]}
+ log_mustnot zpool replace -s $TESTPOOL1 ${VDEV_FILES[1]} \
+ $SPARE_VDEV_FILE
+ destroy_pool $TESTPOOL1
+done
+
+# stripe
+log_must zpool create $TESTPOOL1 ${VDEV_FILES[@]}
+log_must zpool replace -s $TESTPOOL1 ${VDEV_FILES[1]} $SPARE_VDEV_FILE
+destroy_pool $TESTPOOL1
+
+# mirror
+log_must zpool create $TESTPOOL1 mirror ${VDEV_FILES[0]} ${VDEV_FILES[1]}
+log_must zpool replace -s $TESTPOOL1 ${VDEV_FILES[1]} $SPARE_VDEV_FILE
+destroy_pool $TESTPOOL1
+
+log_pass "Sequential resilver is not allowed for raidz vdevs"
diff --git a/tests/zfs-tests/tests/functional/replacement/replace_import.ksh b/tests/zfs-tests/tests/functional/replacement/replace_import.ksh
new file mode 100755
index 000000000000..35d51d93938b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/replace_import.ksh
@@ -0,0 +1,67 @@
+#!/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, Datto Inc. All rights reserved.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# Description:
+# Verify that on import an in progress replace operation is resumed.
+#
+# Strategy:
+# 1. For both healing and sequential resilvering replace:
+# a. Create a pool
+# b. Repalce a vdev with 'zpool replace' to resilver (-s) it.
+# c. Export the pool
+# d. Import the pool
+# e. Verify the 'zpool replace' resumed resilvering.
+# f. Destroy the pool
+#
+
+function cleanup
+{
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+}
+
+log_assert "Verify replace is resumed on import"
+
+ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
+
+log_onexit cleanup
+
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+
+# Verify healing and sequential resilver resume on import.
+for arg in "" "-s"; do
+ log_must zpool create -f $TESTPOOL1 ${VDEV_FILES[@]}
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+ log_must zpool replace -s $TESTPOOL1 ${VDEV_FILES[0]} $SPARE_VDEV_FILE
+ log_must is_pool_resilvering $TESTPOOL1
+ log_must zpool export $TESTPOOL1
+ log_must zpool import -d $TEST_BASE_DIR $TESTPOOL1
+ log_must is_pool_resilvering $TESTPOOL1
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS $ORIG_SCAN_SUSPEND_PROGRESS
+ log_must zpool wait -t resilver $TESTPOOL1
+ log_must is_pool_resilvered $TESTPOOL1
+ destroy_pool $TESTPOOL1
+done
+
+log_pass "Verify replace is resumed on import"
diff --git a/tests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh b/tests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh
new file mode 100755
index 000000000000..5997352284b4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/replace_rebuild.ksh
@@ -0,0 +1,158 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Replacing disks during I/O should pass for supported pools.
+#
+# STRATEGY:
+# 1. Create multidisk pools (stripe/mirror) and
+# start some random I/O
+# 2. Replace a disk in the pool with another disk.
+# 3. Verify the integrity of the file system and the rebuilding.
+#
+# NOTE: Raidz does not support the sequential resilver (-s) option.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if [[ -n "$child_pids" ]]; then
+ for wait_pid in $child_pids
+ do
+ kill $wait_pid
+ done
+ fi
+
+ if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+ fi
+
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Replacing a disk with -r during I/O completes."
+
+options=""
+options_display="default options"
+
+log_onexit cleanup
+
+[[ -n "$HOLES_FILESIZE" ]] && options=" $options -f $HOLES_FILESIZE "
+
+[[ -n "$HOLES_BLKSIZE" ]] && options="$options -b $HOLES_BLKSIZE "
+
+[[ -n "$HOLES_COUNT" ]] && options="$options -c $HOLES_COUNT "
+
+[[ -n "$HOLES_SEED" ]] && options="$options -s $HOLES_SEED "
+
+[[ -n "$HOLES_FILEOFFSET" ]] && options="$options -o $HOLES_FILEOFFSET "
+
+options="$options -r "
+
+[[ -n "$options" ]] && options_display=$options
+
+child_pids=""
+
+function replace_test
+{
+ typeset -i iters=2
+ typeset -i index=0
+ typeset opt=$1
+ typeset disk1=$2
+ typeset disk2=$3
+
+ typeset i=0
+ while [[ $i -lt $iters ]]; do
+ log_note "Invoking file_trunc with: $options_display"
+ file_trunc $options $TESTDIR/$TESTFILE.$i &
+ typeset pid=$!
+
+ sleep 1
+
+ child_pids="$child_pids $pid"
+ ((i = i + 1))
+ done
+
+ log_must zpool replace -sw $opt $TESTPOOL1 $disk1 $disk2
+
+ for wait_pid in $child_pids
+ do
+ kill $wait_pid
+ done
+ child_pids=""
+
+ log_must zpool export $TESTPOOL1
+ log_must zpool import -d $TESTDIR $TESTPOOL1
+ log_must zfs umount $TESTPOOL1/$TESTFS1
+ log_must zdb -cdui $TESTPOOL1/$TESTFS1
+ log_must zfs mount $TESTPOOL1/$TESTFS1
+ verify_pool $TESTPOOL1
+}
+
+specials_list=""
+i=0
+while [[ $i != 3 ]]; do
+ log_must truncate -s $MINVDEVSIZE $TESTDIR/$TESTFILE1.$i
+ specials_list="$specials_list $TESTDIR/$TESTFILE1.$i"
+
+ ((i = i + 1))
+done
+
+#
+# Create a replacement disk special file.
+#
+log_must truncate -s $MINVDEVSIZE $TESTDIR/$REPLACEFILE
+
+for type in "" "mirror"; do
+ for op in "" "-f"; do
+ create_pool $TESTPOOL1 $type $specials_list
+ log_must zfs create $TESTPOOL1/$TESTFS1
+ log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+ replace_test "$opt" $TESTDIR/$TESTFILE1.1 $TESTDIR/$REPLACEFILE
+
+ zpool iostat -v $TESTPOOL1 | grep "$REPLACEFILE"
+ if [[ $? -ne 0 ]]; then
+ log_fail "$REPLACEFILE is not present."
+ fi
+
+ destroy_pool $TESTPOOL1
+ log_must rm -rf /$TESTPOOL1
+ done
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/replacement/replace_resilver.ksh b/tests/zfs-tests/tests/functional/replacement/replace_resilver.ksh
new file mode 100755
index 000000000000..253cf65e452b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/replace_resilver.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 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/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Replacing disks during I/O should pass for supported pools.
+#
+# STRATEGY:
+# 1. Create multidisk pools (stripe/mirror/raidz) and
+# start some random I/O
+# 2. Replace a disk in the pool with another disk.
+# 3. Verify the integrity of the file system and the resilvering.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if [[ -n "$child_pids" ]]; then
+ for wait_pid in $child_pids
+ do
+ kill $wait_pid
+ done
+ fi
+
+ if poolexists $TESTPOOL1; then
+ destroy_pool $TESTPOOL1
+ fi
+
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Replacing a disk during I/O completes."
+
+options=""
+options_display="default options"
+
+log_onexit cleanup
+
+[[ -n "$HOLES_FILESIZE" ]] && options=" $options -f $HOLES_FILESIZE "
+
+[[ -n "$HOLES_BLKSIZE" ]] && options="$options -b $HOLES_BLKSIZE "
+
+[[ -n "$HOLES_COUNT" ]] && options="$options -c $HOLES_COUNT "
+
+[[ -n "$HOLES_SEED" ]] && options="$options -s $HOLES_SEED "
+
+[[ -n "$HOLES_FILEOFFSET" ]] && options="$options -o $HOLES_FILEOFFSET "
+
+options="$options -r "
+
+[[ -n "$options" ]] && options_display=$options
+
+child_pids=""
+
+function replace_test
+{
+ typeset -i iters=2
+ typeset -i index=0
+ typeset opt=$1
+ typeset disk1=$2
+ typeset disk2=$3
+
+ typeset i=0
+ while [[ $i -lt $iters ]]; do
+ log_note "Invoking file_trunc with: $options_display"
+ file_trunc $options $TESTDIR/$TESTFILE.$i &
+ typeset pid=$!
+
+ sleep 1
+
+ child_pids="$child_pids $pid"
+ ((i = i + 1))
+ done
+
+ log_must zpool replace -w $opt $TESTPOOL1 $disk1 $disk2
+
+ for wait_pid in $child_pids
+ do
+ kill $wait_pid
+ done
+ child_pids=""
+
+ log_must zpool export $TESTPOOL1
+ log_must zpool import -d $TESTDIR $TESTPOOL1
+ log_must zfs umount $TESTPOOL1/$TESTFS1
+ log_must zdb -cdui $TESTPOOL1/$TESTFS1
+ log_must zfs mount $TESTPOOL1/$TESTFS1
+ verify_pool $TESTPOOL1
+}
+
+specials_list=""
+i=0
+while [[ $i != 3 ]]; do
+ log_must truncate -s $MINVDEVSIZE $TESTDIR/$TESTFILE1.$i
+ specials_list="$specials_list $TESTDIR/$TESTFILE1.$i"
+
+ ((i = i + 1))
+done
+
+#
+# Create a replacement disk special file.
+#
+log_must truncate -s $MINVDEVSIZE $TESTDIR/$REPLACEFILE
+
+for type in "" "raidz" "mirror"; do
+ for op in "" "-f"; do
+ create_pool $TESTPOOL1 $type $specials_list
+ log_must zfs create $TESTPOOL1/$TESTFS1
+ log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1
+
+ replace_test "$opt" $TESTDIR/$TESTFILE1.1 $TESTDIR/$REPLACEFILE
+
+ zpool iostat -v $TESTPOOL1 | grep "$REPLACEFILE"
+ if [[ $? -ne 0 ]]; then
+ log_fail "$REPLACEFILE is not present."
+ fi
+
+ destroy_pool $TESTPOOL1
+ log_must rm -rf /$TESTPOOL1
+ done
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/replacement/replacement.cfg b/tests/zfs-tests/tests/functional/replacement/replacement.cfg
new file mode 100644
index 000000000000..271317b1c970
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/replacement.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export TESTFILE=testfile
+export TESTFILE1=testfile1
+export HOLES_FILESIZE=${HOLES_FILESIZE-"67108864"} # 64 Mb
+export HOLES_BLKSIZE=${HOLES_BLKSIZE-"512"}
+export HOLES_SEED=${HOLES_SEED-""}
+export HOLES_FILEOFFSET=${HOLES_FILEOFFSET-""}
+export HOLES_COUNT=${HOLES_COUNT-"16384"} # FILESIZE/BLKSIZE/8
+export REPLACEFILE="sparedisk"
+
+set -A VDEV_FILES $TEST_BASE_DIR/file-{1..4}
+export VDEV_FILE_SIZE=$(( $SPA_MINDEVSIZE * 2 ))
+export SPARE_VDEV_FILE=$TEST_BASE_DIR/spare-1
+export SPARE_VDEV_FILE2=$TEST_BASE_DIR/spare-2
diff --git a/tests/zfs-tests/tests/functional/replacement/resilver_restart_001.ksh b/tests/zfs-tests/tests/functional/replacement/resilver_restart_001.ksh
new file mode 100755
index 000000000000..7896b2dbe1d0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/resilver_restart_001.ksh
@@ -0,0 +1,187 @@
+#!/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
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Testing resilver restart logic both with and without the deferred resilver
+# feature enabled, verifying that resilver is not restarted when it is
+# unnecessary.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Create four filesystems with the primary cache disable to force reads
+# 3. Write four files simultaneously, one to each filesystem
+# 4. Do with and without deferred resilvers enabled
+# a. Replace a vdev with a spare & suspend resilver immediately
+# b. Verify resilver starts properly
+# c. Offline / online another vdev to introduce a new DTL range
+# d. Verify resilver restart restart or defer
+# e. Inject read errors on vdev that was offlined / onlned
+# f. Verify that resilver did not restart
+# g. Unsuspend resilver and wait for it to finish
+# h. Verify that there are two resilvers and nothing is deferred
+#
+
+function cleanup
+{
+ log_must set_tunable32 RESILVER_MIN_TIME_MS $ORIG_RESILVER_MIN_TIME
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ log_must set_tunable32 ZEVENT_LEN_MAX $ORIG_ZFS_ZEVENT_LEN_MAX
+ log_must zinject -c all
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+}
+
+# count resilver events in zpool and number of deferred rsilvers on vdevs
+function verify_restarts # <msg> <cnt> <defer>
+{
+ msg=$1
+ cnt=$2
+ defer=$3
+
+ # check the number of resilver start in events log
+ RESILVERS=$(zpool events | grep -c sysevent.fs.zfs.resilver_start)
+ log_note "expected $cnt resilver start(s)$msg, found $RESILVERS"
+ [[ "$RESILVERS" -ne "$cnt" ]] &&
+ log_fail "expected $cnt resilver start(s)$msg, found $RESILVERS"
+
+ [[ -z "$defer" ]] && return
+
+ # use zdb to find which vdevs have the resilver defer flag
+ VDEV_DEFERS=$(zdb -C $TESTPOOL1 | awk '
+ /children/ { gsub(/[^0-9]/, ""); child = $0 }
+ /com\.datto:resilver_defer$/ { print child }
+ ')
+
+ if [[ "$defer" == "-" ]]
+ then
+ [[ -n $VDEV_DEFERS ]] &&
+ log_fail "didn't expect any vdevs to have resilver deferred"
+ return
+ fi
+
+ [[ $VDEV_DEFERS -eq $defer ]] ||
+ log_fail "resilver deferred set on unexpected vdev: $VDEV_DEFERS"
+}
+
+log_assert "Check for unnecessary resilver restarts"
+
+ORIG_RESILVER_MIN_TIME=$(get_tunable RESILVER_MIN_TIME_MS)
+ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
+ORIG_ZFS_ZEVENT_LEN_MAX=$(get_tunable ZEVENT_LEN_MAX)
+
+set -A RESTARTS -- '1' '2' '2' '2'
+set -A VDEVS -- '' '' '' ''
+set -A DEFER_RESTARTS -- '1' '1' '1' '2'
+set -A DEFER_VDEVS -- '-' '2' '2' '-'
+
+VDEV_REPLACE="${VDEV_FILES[1]} $SPARE_VDEV_FILE"
+
+log_onexit cleanup
+
+# ensure that enough events will be saved
+log_must set_tunable32 ZEVENT_LEN_MAX 512
+
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+
+log_must zpool create -f -o feature@resilver_defer=disabled $TESTPOOL1 \
+ raidz ${VDEV_FILES[@]}
+
+# create 4 filesystems
+for fs in fs{0..3}
+do
+ log_must zfs create -o primarycache=none -o recordsize=1k $TESTPOOL1/$fs
+done
+
+# simultaneously write 16M to each of them
+set -A DATAPATHS /$TESTPOOL1/fs{0..3}/dat.0
+log_note "Writing data files"
+for path in ${DATAPATHS[@]}
+do
+ dd if=/dev/urandom of=$path bs=1M count=16 > /dev/null 2>&1 &
+done
+wait
+
+# test without and with deferred resilve feature enabled
+for test in "without" "with"
+do
+ log_note "Testing $test deferred resilvers"
+
+ if [[ $test == "with" ]]
+ then
+ log_must zpool set feature@resilver_defer=enabled $TESTPOOL1
+ RESTARTS=( "${DEFER_RESTARTS[@]}" )
+ VDEVS=( "${DEFER_VDEVS[@]}" )
+ VDEV_REPLACE="$SPARE_VDEV_FILE ${VDEV_FILES[1]}"
+ fi
+
+ # clear the events
+ log_must zpool events -c
+
+ # limit scanning time
+ log_must set_tunable32 RESILVER_MIN_TIME_MS 50
+
+ # initiate a resilver and suspend the scan as soon as possible
+ log_must zpool replace $TESTPOOL1 $VDEV_REPLACE
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+ # there should only be 1 resilver start
+ verify_restarts '' "${RESTARTS[0]}" "${VDEVS[0]}"
+
+ # offline then online a vdev to introduce a new DTL range after current
+ # scan, which should restart (or defer) the resilver
+ log_must zpool offline $TESTPOOL1 ${VDEV_FILES[2]}
+ log_must zpool sync $TESTPOOL1
+ log_must zpool online $TESTPOOL1 ${VDEV_FILES[2]}
+ log_must zpool sync $TESTPOOL1
+
+ # there should now be 2 resilver starts w/o defer, 1 with defer
+ verify_restarts ' after offline/online' "${RESTARTS[1]}" "${VDEVS[1]}"
+
+ # inject read io errors on vdev and verify resilver does not restart
+ log_must zinject -a -d ${VDEV_FILES[2]} -e io -T read -f 0.25 $TESTPOOL1
+ log_must cat ${DATAPATHS[1]} > /dev/null
+ log_must zinject -c all
+
+ # there should still be 2 resilver starts w/o defer, 1 with defer
+ verify_restarts ' after zinject' "${RESTARTS[2]}" "${VDEVS[2]}"
+
+ # unsuspend resilver
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ log_must set_tunable32 RESILVER_MIN_TIME_MS 3000
+
+ # wait for resilver to finish
+ log_must zpool wait -t resilver $TESTPOOL1
+ log_must is_pool_resilvered $TESTPOOL1
+
+ # wait for a few txg's to see if a resilver happens
+ log_must zpool sync $TESTPOOL1
+ log_must zpool sync $TESTPOOL1
+
+ # there should now be 2 resilver starts
+ verify_restarts ' after resilver' "${RESTARTS[3]}" "${VDEVS[3]}"
+done
+
+log_pass "Resilver did not restart unnecessarily"
diff --git a/tests/zfs-tests/tests/functional/replacement/resilver_restart_002.ksh b/tests/zfs-tests/tests/functional/replacement/resilver_restart_002.ksh
new file mode 100755
index 000000000000..48763f9b2dfa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/resilver_restart_002.ksh
@@ -0,0 +1,102 @@
+#!/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, Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Testing resilver completes when scan errors are encountered, but relevant
+# DTL's have not been lost.
+#
+# STRATEGY:
+# 1. Create a pool (1k recordsize)
+# 2. Create a 32m file (32k records)
+# 3. Inject an error halfway through the file
+# 4. Start a resilver, ensure the error is triggered and that the resilver
+# does not restart after finishing
+#
+# NB: use legacy scanning to ensure scan of specific block causes error
+#
+
+function cleanup
+{
+ log_must zinject -c all
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+ log_must set_tunable32 SCAN_LEGACY $ORIG_SCAN_LEGACY
+}
+
+log_assert "Check for resilver restarts caused by scan errors"
+
+ORIG_SCAN_LEGACY=$(get_tunable SCAN_LEGACY)
+
+log_onexit cleanup
+
+# use legacy scan to ensure injected error will be triggered
+log_must set_tunable32 SCAN_LEGACY 1
+
+ # create the pool and a 32M file (32k blocks)
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[0]} $SPARE_VDEV_FILE
+log_must zpool create -f -O recordsize=1k $TESTPOOL1 ${VDEV_FILES[0]}
+log_must dd if=/dev/urandom of=/$TESTPOOL1/file bs=1M count=32 > /dev/null 2>&1
+
+# determine objset/object
+objset=$(zdb -d $TESTPOOL1/ | sed -ne 's/.*ID \([0-9]*\).*/\1/p')
+object=$(ls -i /$TESTPOOL1/file | awk '{print $1}')
+
+# inject event to cause error during resilver
+log_must zinject -b `printf "%x:%x:0:3fff" $objset $object` $TESTPOOL1
+
+# clear events and start resilver
+log_must zpool events -c
+log_must zpool attach $TESTPOOL1 ${VDEV_FILES[0]} $SPARE_VDEV_FILE
+
+log_note "waiting for read errors to start showing up"
+for iter in {0..59}
+do
+ zpool sync $TESTPOOL1
+ err=$(zpool status $TESTPOOL1 | grep ${VDEV_FILES[0]} | awk '{print $3}')
+ (( $err > 0 )) && break
+ sleep 1
+done
+
+(( $err == 0 )) && log_fail "Unable to induce errors in resilver"
+
+log_note "waiting for resilver to finish"
+for iter in {0..59}
+do
+ finish=$(zpool events | grep "sysevent.fs.zfs.resilver_finish" | wc -l)
+ (( $finish > 0 )) && break
+ sleep 1
+done
+
+(( $finish == 0 )) && log_fail "resilver took too long to finish"
+
+# wait a few syncs to ensure that zfs does not restart the resilver
+log_must zpool sync $TESTPOOL1
+log_must zpool sync $TESTPOOL1
+
+# check if resilver was restarted
+start=$(zpool events | grep "sysevent.fs.zfs.resilver_start" | wc -l)
+(( $start != 1 )) && log_fail "resilver restarted unnecessarily"
+
+log_pass "Resilver did not restart unnecessarily from scan errors"
diff --git a/tests/zfs-tests/tests/functional/replacement/scrub_cancel.ksh b/tests/zfs-tests/tests/functional/replacement/scrub_cancel.ksh
new file mode 100755
index 000000000000..da8a0a26e333
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/scrub_cancel.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) 2019, Datto Inc. All rights reserved.
+# Copyright (c) 2020 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/replacement/replacement.cfg
+
+#
+# DESCRIPTION:
+# Verify scrub behaves as intended when contending with a healing or
+# sequential resilver.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Add a modest amount of data to the pool.
+# 3. For healing and sequential resilver:
+# a. Start scrubbing.
+# b. Verify a resilver can be started and it cancels the scrub.
+# c. Verify a scrub cannot be started when resilvering
+#
+
+function cleanup
+{
+ log_must set_tunable32 RESILVER_MIN_TIME_MS $ORIG_RESILVER_MIN_TIME
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS \
+ $ORIG_SCAN_SUSPEND_PROGRESS
+ destroy_pool $TESTPOOL1
+ rm -f ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+}
+
+log_assert "Scrub was cancelled by resilver"
+
+ORIG_RESILVER_MIN_TIME=$(get_tunable RESILVER_MIN_TIME_MS)
+ORIG_SCAN_SUSPEND_PROGRESS=$(get_tunable SCAN_SUSPEND_PROGRESS)
+
+log_onexit cleanup
+
+log_must truncate -s $VDEV_FILE_SIZE ${VDEV_FILES[@]} $SPARE_VDEV_FILE
+
+log_must zpool create -f $TESTPOOL1 ${VDEV_FILES[@]}
+log_must zfs create $TESTPOOL1/$TESTFS
+
+mntpnt=$(get_prop mountpoint $TESTPOOL1/$TESTFS)
+log_must dd if=/dev/urandom of=$mntpnt/file bs=1M count=64
+log_must zpool sync $TESTPOOL1
+
+# Request a healing or sequential resilver
+for replace_mode in "healing" "sequential"; do
+
+ #
+ # Healing resilvers abort the dsl_scan and reconfigure it for
+ # resilvering. Sequential resilvers cancel the dsl_scan and start
+ # the vdev_rebuild thread.
+ #
+ if [[ "$replace_mode" = "healing" ]]; then
+ history_msg="scan aborted, restarting"
+ flags=""
+ else
+ history_msg="scan cancelled"
+ flags="-s"
+ fi
+
+ # Limit scanning time and suspend the scan as soon as possible.
+ log_must set_tunable32 RESILVER_MIN_TIME_MS 50
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+ # Initiate a scrub.
+ log_must zpool scrub $TESTPOOL1
+
+ # Initiate a resilver to cancel the scrub.
+ log_must zpool replace $flags $TESTPOOL1 ${VDEV_FILES[1]} \
+ $SPARE_VDEV_FILE
+
+ # Verify the scrub was canceled, it may take a few seconds to exit.
+ while is_pool_scrubbing $TESTPOOL1; do
+ sleep 1
+ done
+ log_mustnot is_pool_scrubbing $TESTPOOL1
+
+ # Verify a scrub cannot be started while resilvering.
+ log_must is_pool_resilvering $TESTPOOL1
+ log_mustnot zpool scrub $TESTPOOL1
+
+ # Unsuspend resilver.
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ log_must set_tunable32 RESILVER_MIN_TIME_MS 3000
+
+ # Wait for resilver to finish then put the original back.
+ log_must zpool wait $TESTPOOL1
+ log_must zpool replace $flags -w $TESTPOOL1 $SPARE_VDEV_FILE \
+ ${VDEV_FILES[1]}
+done
+log_pass "Scrub was cancelled by resilver"
+
diff --git a/tests/zfs-tests/tests/functional/replacement/setup.ksh b/tests/zfs-tests/tests/functional/replacement/setup.ksh
new file mode 100755
index 000000000000..4132392d80a9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/replacement/setup.ksh
@@ -0,0 +1,47 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 2
+
+index=`expr $RANDOM % 2`
+case $index in
+0) log_note "Pool Type: Mirror"
+ default_mirror_setup $DISKS
+ ;;
+1) log_note "Pool Type: RAID-Z"
+ default_raidz_setup $DISKS
+ ;;
+esac
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/reservation/Makefile.am b/tests/zfs-tests/tests/functional/reservation/Makefile.am
new file mode 100644
index 000000000000..8eaf09861551
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/Makefile.am
@@ -0,0 +1,30 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/reservation
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ reservation_001_pos.ksh \
+ reservation_002_pos.ksh \
+ reservation_003_pos.ksh \
+ reservation_004_pos.ksh \
+ reservation_005_pos.ksh \
+ reservation_006_pos.ksh \
+ reservation_007_pos.ksh \
+ reservation_008_pos.ksh \
+ reservation_009_pos.ksh \
+ reservation_010_pos.ksh \
+ reservation_011_pos.ksh \
+ reservation_012_pos.ksh \
+ reservation_013_pos.ksh \
+ reservation_014_pos.ksh \
+ reservation_015_pos.ksh \
+ reservation_016_pos.ksh \
+ reservation_017_pos.ksh \
+ reservation_018_pos.ksh \
+ reservation_019_pos.ksh \
+ reservation_020_pos.ksh \
+ reservation_021_neg.ksh \
+ reservation_022_pos.ksh
+
+dist_pkgdata_DATA = \
+ reservation.cfg \
+ reservation.shlib
diff --git a/tests/zfs-tests/tests/functional/reservation/cleanup.ksh b/tests/zfs-tests/tests/functional/reservation/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation.cfg b/tests/zfs-tests/tests/functional/reservation/reservation.cfg
new file mode 100644
index 000000000000..b4f9af938623
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation.cfg
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+export RESV_DELTA=5242880
+export RESV_TOLERANCE=10485760 # Acceptable limit (10MB) diff in space stats
+export RESV_SIZE=52428800 # Default reservation size (50MB)
+export RESV_FREE_SPACE=52428800 # Amount of space (50MB) to leave free in a pool
+export RESV_NUM_FS=10 # Number of filesystems to create
+export RESV_ITER=10 # Number of iterations
+
+export BLOCK_SIZE=1048576
+export ENOSPC=28
+
+export TESTVOL=testvol$$
+export TESTVOL2=testvol2-$$
+export TESTFILE1=file1.$$
+export TESTFILE2=file2.$$
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation.shlib b/tests/zfs-tests/tests/functional/reservation/reservation.shlib
new file mode 100644
index 000000000000..49ee3b992dcc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation.shlib
@@ -0,0 +1,201 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/reservation/reservation.cfg
+
+#
+# Function to set the reservation property of a dataset to
+# 'none' and verify that it is correctly set using both the
+# "normal" 'zfs get reservation' and the '-p' option which
+# gives a numerical value.
+#
+function zero_reservation
+{
+ typeset resv_val
+ dataset=$1
+
+ log_must zfs set reservation=none $dataset
+
+ resv_val=`zfs get -H reservation $dataset | awk '{print $3}'`
+ if [[ $? -ne 0 ]]; then
+ log_fail "Unable to get reservation prop on $dataset"
+ elif [[ $resv_val != "none" ]]; then
+ log_fail "Reservation not 'none' ($resv_val) as expected"
+ fi
+
+
+ resv_val=`zfs get -pH reservation $dataset | awk '{print $3}'`
+ if [[ $? -ne 0 ]]; then
+ log_fail "Unable to get reservation prop on $dataset"
+ elif [[ $resv_val -ne 0 ]]; then
+ log_fail "Reservation not 0 ($resv_val) as expected"
+ fi
+
+ return 0
+}
+
+#
+# Utility function to see if two values are within a certain specified
+# limit of each other. Used primarily to check that a dataset's parent
+# is correctly accounting for space used/available. Need this function as
+# currently there is some slop in the way space is accounted (i.e. can't
+# do a direct comparison).
+#
+function within_limits
+{
+ typeset valA=$1
+ typeset valB=$2
+ typeset delta=$3
+
+ if ((valA <= valB)); then
+ if (((valB - valA) <= delta)); then
+ return 0
+ fi
+ elif ((valB <= valA)); then
+ if (((valA - valB) <= delta)); then
+ return 0
+ fi
+ fi
+
+ return 1
+}
+
+#
+# Function to create and mount multiple filesystems. The filesystem
+# will be named according to the name specified with a suffix value
+# taken from the loop counter.
+#
+function create_multiple_fs # num_fs base_fs_name base_mnt_name
+{
+ typeset -i iter=0
+ typeset -i count=$1
+ typeset FS_NAME=$2
+ typeset MNT_NAME=$3
+
+ while (($iter < $count)); do
+ log_must zfs create ${FS_NAME}$iter
+ log_must zfs set mountpoint=${MNT_NAME}$iter ${FS_NAME}$iter
+ ((iter = iter + 1))
+ done
+}
+
+#
+# This function compute the largest volume size which is multiple of volume
+# block size (default 8K) and not greater than the largest expected volsize.
+#
+# $1 The largest expected volume size.
+# $2 The volume block size
+#
+function floor_volsize #<largest_volsize> [volblksize]
+{
+ typeset largest_volsize=$1
+ typeset volblksize=${2:-8192}
+
+ if ((largest_volsize < volblksize)); then
+ log_fail "The largest_volsize must be greater than volblksize."
+ fi
+ typeset real_volsize
+ typeset n
+
+ ((n = largest_volsize / volblksize))
+ ((largest_volsize = volblksize * n))
+
+ print $largest_volsize
+}
+
+#
+# This function is a copy of a function by the same name in libzfs_dataset.c
+# Its purpose is to reserve additional space for volume metadata so volumes
+# don't unexpectedly run out of room.
+#
+# Note: This function can be used to do an estimate for a volume that has not
+# yet been created. In this case, $vol is not a volume, but rather a pool in
+# which a volume is going to be created. In this case, use default properties.
+#
+function volsize_to_reservation
+{
+ typeset vol=$1
+ typeset volsize=$2
+
+ typeset -i DN_MAX_INDBLKSHIFT=17
+ typeset -i SPA_BLKPTRSHIFT=7
+ typeset -i SPA_DVAS_PER_BP=3
+
+ typeset DNODES_PER_LEVEL_SHIFT=$((DN_MAX_INDBLKSHIFT - \
+ SPA_BLKPTRSHIFT))
+ typeset DNODES_PER_LEVEL=$((1 << $DNODES_PER_LEVEL_SHIFT))
+
+ if ds_is_volume $vol; then
+ typeset ncopies=$(get_prop copies $vol)
+ typeset volblocksize=$(get_prop volblocksize $vol)
+ else
+ typeset ncopies=1
+ typeset volblocksize=8192
+ fi
+ typeset nblocks=$((volsize / volblocksize))
+
+ typeset numdb=7
+ while ((nblocks > 1)); do
+ ((nblocks += DNODES_PER_LEVEL - 1))
+ ((nblocks /= DNODES_PER_LEVEL))
+ ((numdb += nblocks))
+ done
+
+ ((numdb *= SPA_DVAS_PER_BP < ncopies + 1 ? SPA_DVAS_PER_BP : \
+ ncopies + 1))
+ ((volsize *= ncopies))
+ ((numdb *= 1 << DN_MAX_INDBLKSHIFT))
+ ((volsize += numdb))
+ echo $volsize
+}
+
+#
+# This function takes a pool name as an argument, and returns the largest (give
+# or take some slop) -V value that can be used to create a volume in that pool.
+# This is necessary because during volume creation, a reservation is created
+# that will be larger than the value specified with -V, and potentially larger
+# than the available space in the pool. See volsize_to_reservation().
+#
+function largest_volsize_from_pool
+{
+ typeset pool=$1
+ typeset poolsize=$(get_prop available $pool)
+ typeset volsize=$poolsize
+ typeset nvolsize
+
+ while :; do
+ # knock 50M off the volsize each time through
+ ((volsize -= 50 * 1024 * 1024))
+ nvolsize=$(volsize_to_reservation $pool $volsize)
+ nvolsize=$(floor_volsize $nvolsize)
+ ((nvolsize < poolsize)) && break
+ done
+ echo $volsize
+}
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_001_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_001_pos.ksh
new file mode 100755
index 000000000000..b8220791f1d4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_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 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/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# ZFS allows reservations to be set on filesystems and volumes, provided
+# the reservation is less than the space available in the pool.
+#
+# STRATEGY:
+# 1) Create a regular and sparse volume
+# (filesystem already created by default_setup)
+# 2) Get the space available in the pool
+# 3) Set a reservation on the filesystem less than the space available.
+# 4) Verify that the 'reservation' property for the filesystem has
+# the correct value.
+# 5) Reset the reservation to 'none'
+# 6) Repeat steps 2-5 for both volume types
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for obj in $OBJ_LIST; do
+ destroy_dataset $obj
+ done
+}
+
+log_onexit cleanup
+
+log_assert "Verify that to set a reservation on a filesystem or volume must " \
+ "use value smaller than space available property of pool"
+
+space_avail=`get_prop available $TESTPOOL`
+
+if ! is_global_zone ; then
+ OBJ_LIST=""
+else
+ OBJ_LIST="$TESTPOOL/$TESTVOL $TESTPOOL/$TESTVOL2"
+
+ ((vol_set_size = space_avail / 4))
+ vol_set_size=$(floor_volsize $vol_set_size)
+ ((sparse_vol_set_size = space_avail * 4))
+ sparse_vol_set_size=$(floor_volsize $sparse_vol_set_size)
+
+ #
+ # Note that when creating a regular volume we are implicitly
+ # setting a reservation upon it (i.e. the size of the volume)
+ # which we reset back to zero initially.
+ #
+ log_must zfs create -V $vol_set_size $TESTPOOL/$TESTVOL
+ log_must zfs set reservation=none $TESTPOOL/$TESTVOL
+ log_must zfs set refreservation=none $TESTPOOL/$TESTVOL
+ log_must zfs create -s -V $sparse_vol_set_size $TESTPOOL/$TESTVOL2
+fi
+
+
+for obj in $TESTPOOL/$TESTFS $OBJ_LIST; do
+
+ space_avail=`get_prop available $TESTPOOL`
+ resv_size_set=`expr $space_avail - $RESV_DELTA`
+
+ #
+ # For a regular (non-sparse) volume the upper limit
+ # for reservations is not determined by the space
+ # available in the pool but rather by the size of
+ # the volume itself.
+ #
+ [[ $obj == $TESTPOOL/$TESTVOL ]] && \
+ ((resv_size_set = vol_set_size - RESV_DELTA))
+
+ log_must zfs set reservation=$resv_size_set $obj
+
+ resv_size_get=`get_prop reservation $obj`
+ if [[ $resv_size_set != $resv_size_get ]]; then
+ log_fail "Reservation not the expected value " \
+ "($resv_size_set != $resv_size_get)"
+ fi
+
+ log_must zero_reservation $obj
+
+ new_space_avail=`get_prop available $obj`
+
+ #
+ # Due to the way space is consumed and released by metadata we
+ # can't do an exact check here, but we do a basic sanity
+ # check.
+ #
+ log_must within_limits $space_avail $new_space_avail $RESV_TOLERANCE
+done
+
+log_pass "Successfully set reservation on filesystem and volume"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_002_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_002_pos.ksh
new file mode 100755
index 000000000000..8ae3593613f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Reservation values cannot exceed the amount of space available
+# in the pool. Verify that attempting to set a reservation greater
+# than this value fails.
+#
+# STRATEGY:
+# 1) Create a filesystem, regular and sparse volume
+# 2) Get the space available in the pool
+# 3) Attempt to set a reservation greater than the available space
+# on the filesystem and verify it fails.
+# 4) Verify that the reservation is still set to 'none' (or 0) on
+# the filesystem.
+# 5) Repeat 3-4 for regular and sparse volume
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ for obj in $OBJ_LIST; do
+ datasetexists $obj && log_must_busy zfs destroy -f $obj
+ done
+
+ log_must zero_reservation $TESTPOOL/$TESTFS
+}
+
+log_onexit cleanup
+
+log_assert "Reservation values cannot exceed the amount of space" \
+ " available in the pool"
+
+space_avail=`get_prop available $TESTPOOL`
+
+if ! is_global_zone ; then
+ OBJ_LIST=""
+else
+ OBJ_LIST="$TESTPOOL/$TESTVOL $TESTPOOL/$TESTVOL2"
+
+ ((vol_set_size = space_avail / 4))
+ vol_set_size=$(floor_volsize $vol_set_size)
+ ((sparse_vol_set_size = space_avail * 4))
+ sparse_vol_set_size=$(floor_volsize $sparse_vol_set_size)
+
+ log_must zfs create -V $vol_set_size $TESTPOOL/$TESTVOL
+ log_must zfs set reservation=none $TESTPOOL/$TESTVOL
+ log_must zfs create -s -V $sparse_vol_set_size $TESTPOOL/$TESTVOL2
+fi
+
+for obj in $TESTPOOL/$TESTFS $OBJ_LIST ; do
+
+ space_avail=`get_prop available $obj`
+ resv_size_set=`expr $space_avail + $RESV_DELTA`
+
+ log_must zero_reservation $obj
+ log_mustnot zfs set reservation=$resv_size_set $obj
+
+ resv_size_get=`get_prop reservation $obj`
+
+ if (($resv_size_get != 0)); then
+ log_fail "Reservation value non-zero ($resv_size_get)"
+ fi
+done
+
+log_pass "Attempting to set too large reservation failed as expected"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_003_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_003_pos.ksh
new file mode 100755
index 000000000000..48adabe72ffd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_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 2009 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/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Verify that it's possible to set a reservation on a filesystem,
+# or volume multiple times, without resetting the reservation
+# to none.
+#
+# STRATEGY:
+# 1) Create a regular volume and a sparse volume
+# 2) Get the space available in the pool
+# 3) Set a reservation on the filesystem less than the space available.
+# 4) Verify that the 'reservation' property for the filesystem has
+# the correct value.
+# 5) Repeat 2-4 for different reservation values
+# 6) Repeat 3-5 for regular and sparse volume
+#
+
+verify_runnable "both"
+
+log_assert "Verify it is possible to set reservations multiple times " \
+ "on a filesystem regular and sparse volume"
+
+function cleanup
+{
+ log_must zero_reservation $TESTPOOL/$TESTFS
+
+ for obj in $OBJ_LIST; do
+ datasetexists $obj && log_must zfs destroy -f $obj
+ done
+}
+
+log_onexit cleanup
+
+
+#
+# Set a reservation $RESV_ITER times on a dataset and verify that
+# the reservation is correctly set each time.
+#
+function multiple_resv { #dataset
+ typeset -i i=0
+
+ dataset=$1
+
+ log_must zero_reservation $dataset
+ space_avail=`get_prop available $TESTPOOL`
+
+ ((resv_size = (space_avail - RESV_DELTA) / RESV_ITER))
+
+ #
+ # For regular (non-sparse) volumes the upper limit is determined
+ # not by the space available in the pool but rather by the size
+ # of the volume itself.
+ #
+ [[ $obj == $TESTPOOL/$TESTVOL ]] && \
+ ((resv_size = (vol_set_size - RESV_DELTA) / RESV_ITER))
+
+ resv_size_set=$resv_size
+
+ while (($i < $RESV_ITER)); do
+
+ ((i = i + 1))
+
+ ((resv_size_set = resv_size * i))
+
+ log_must zfs set reservation=$resv_size_set $dataset
+
+ resv_size_get=`get_prop reservation $dataset`
+ if [[ $resv_size_set != $resv_size_get ]]; then
+ log_fail "Reservation not the expected value " \
+ "($resv_size_set != $resv_size_get)"
+ fi
+ done
+
+ log_must zero_reservation $dataset
+}
+
+space_avail=`get_prop available $TESTPOOL`
+
+if ! is_global_zone ; then
+ OBJ_LIST=""
+else
+ OBJ_LIST="$TESTPOOL/$TESTVOL $TESTPOOL/$TESTVOL2"
+
+ ((vol_set_size = space_avail / 4))
+ vol_set_size=$(floor_volsize $vol_set_size)
+ ((sparse_vol_set_size = space_avail * 4))
+ sparse_vol_set_size=$(floor_volsize $sparse_vol_set_size)
+
+
+ log_must zfs create -V $vol_set_size $TESTPOOL/$TESTVOL
+ log_must zfs set reservation=none $TESTPOOL/$TESTVOL
+ log_must zfs create -s -V $sparse_vol_set_size $TESTPOOL/$TESTVOL2
+fi
+
+for obj in $TESTPOOL/$TESTFS $OBJ_LIST ; do
+ multiple_resv $obj
+done
+
+log_pass "Multiple reservations successfully set on filesystem" \
+ " and both volume types"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_004_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_004_pos.ksh
new file mode 100755
index 000000000000..f8342ff29488
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_004_pos.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 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/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# When a dataset which has a reservation set on it is destroyed,
+# the space consumed or reserved by that dataset should be released
+# back into the pool.
+#
+# STRATEGY:
+# 1) Create a filesystem, regular and sparse volume
+# 2) Get the space used and available in the pool
+# 3) Set a reservation on the filesystem less than the space available.
+# 4) Verify that the 'reservation' property for the filesystem has
+# the correct value.
+# 5) Destroy the filesystem without resetting the reservation value.
+# 6) Verify that the space used and available totals for the pool have
+# changed by the expected amounts (within tolerances).
+# 7) Repeat steps 3-6 for a regular volume and sparse volume
+#
+
+verify_runnable "both"
+
+function cleanup {
+
+ for obj in $OBJ_LIST; do
+ datasetexists $obj && log_must_busy zfs destroy -f $obj
+ done
+}
+
+log_assert "Verify space released when a dataset with reservation is destroyed"
+
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS2
+
+space_avail=`get_prop available $TESTPOOL`
+
+if ! is_global_zone ; then
+ OBJ_LIST="$TESTPOOL/$TESTFS2"
+else
+ OBJ_LIST="$TESTPOOL/$TESTFS2 \
+ $TESTPOOL/$TESTVOL $TESTPOOL/$TESTVOL2"
+
+ ((vol_set_size = space_avail / 4))
+ vol_set_size=$(floor_volsize $vol_set_size)
+ ((sparse_vol_set_size = space_avail * 4))
+ sparse_vol_set_size=$(floor_volsize $sparse_vol_set_size)
+
+ log_must zfs create -V $vol_set_size $TESTPOOL/$TESTVOL
+ log_must zfs set refreservation=none $TESTPOOL/$TESTVOL
+ log_must zfs set reservation=none $TESTPOOL/$TESTVOL
+ log_must zfs create -s -V $sparse_vol_set_size $TESTPOOL/$TESTVOL2
+fi
+
+# re-calculate space available.
+space_avail=`get_prop available $TESTPOOL`
+
+# Calculate a large but valid reservation value.
+resv_size_set=`expr $space_avail - $RESV_DELTA`
+
+for obj in $OBJ_LIST ; do
+
+ space_avail=`get_prop available $TESTPOOL`
+ space_used=`get_prop used $TESTPOOL`
+
+ #
+ # For regular (non-sparse) volumes the upper limit is determined
+ # not by the space available in the pool but rather by the size
+ # of the volume itself.
+ #
+ [[ $obj == $TESTPOOL/$TESTVOL ]] && \
+ ((resv_size_set = vol_set_size - RESV_DELTA))
+
+ log_must zfs set reservation=$resv_size_set $obj
+
+ resv_size_get=`get_prop reservation $obj`
+ if [[ $resv_size_set != $resv_size_get ]]; then
+ log_fail "Reservation not the expected value " \
+ "($resv_size_set != $resv_size_get)"
+ fi
+
+ log_must_busy zfs destroy -f $obj
+
+ new_space_avail=`get_prop available $TESTPOOL`
+ new_space_used=`get_prop used $TESTPOOL`
+
+ #
+ # Recent changes to metaslab logic have caused these tests to expand
+ # outside of their previous tolerance. If this is discovered to be a
+ # bug, rather than a side effect of some interactions, the reservation
+ # should be halved again.
+ #
+ log_must within_limits $space_used $new_space_used $RESV_TOLERANCE
+ log_must within_limits $space_avail $new_space_avail $RESV_TOLERANCE
+done
+
+log_pass "Space correctly released when dataset is destroyed"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_005_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_005_pos.ksh
new file mode 100755
index 000000000000..4047fab0d7f9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_005_pos.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# When a reservation property of a filesystem, regular volume
+# or sparse volume is set to 'none' the space previously consumed by the
+# reservation should be released back to the pool
+#
+# STRATEGY:
+# 1) Create a filesystem, regular volume and sparse volume
+# 2) Get the space used and available in the pool
+# 3) Set a reservation on the filesystem less than the space available.
+# 4) Verify that the 'reservation' property for the filesystem has
+# the correct value.
+# 5) Reset the reservation value back to zero (or 'none')
+# 6) Verify that the space used and available totals for the pool have
+# changed by the expected amounts (within tolerances).
+# 7) Repeat steps 3-6 for a regular volume, sparse volume
+#
+
+verify_runnable "both"
+
+log_assert "Verify space released when reservation on a dataset is set "\
+ "to 'none'"
+
+function cleanup
+{
+ for obj in $OBJ_LIST; do
+ datasetexists $obj && log_must zfs destroy -f $obj
+ done
+}
+
+log_onexit cleanup
+
+space_avail=`get_prop available $TESTPOOL`
+
+if ! is_global_zone ; then
+ OBJ_LIST=""
+else
+ OBJ_LIST="$TESTPOOL/$TESTVOL $TESTPOOL/$TESTVOL2"
+ ((vol_set_size = space_avail / 4))
+ vol_set_size=$(floor_volsize $vol_set_size)
+ ((sparse_vol_set_size = space_avail * 4))
+ sparse_vol_set_size=$(floor_volsize $sparse_vol_set_size)
+
+
+ log_must zfs create -V $vol_set_size $TESTPOOL/$TESTVOL
+ log_must zfs set reservation=none $TESTPOOL/$TESTVOL
+ log_must zfs create -s -V $sparse_vol_set_size $TESTPOOL/$TESTVOL2
+fi
+
+space_avail=`get_prop available $TESTPOOL`
+space_used=`get_prop used $TESTPOOL`
+
+# Calculate a large but valid reservation value.
+resv_size_set=`expr $space_avail - $RESV_DELTA`
+
+for obj in $TESTPOOL/$TESTFS $OBJ_LIST ; do
+
+ #
+ # For regular (non-sparse) volumes the upper limit is determined
+ # not by the space available in the pool but rather by the size
+ # of the volume itself.
+ #
+ [[ $obj == $TESTPOOL/$TESTVOL ]] && \
+ ((resv_size_set = vol_set_size - RESV_DELTA))
+
+ log_must zfs set reservation=$resv_size_set $obj
+
+ resv_size_get=`get_prop reservation $obj`
+ if [[ $resv_size_set != $resv_size_get ]]; then
+ log_fail "Reservation not the expected value "\
+ "($resv_size_set != $resv_size_get)"
+ fi
+
+ log_must zfs set reservation=none $obj
+
+ new_space_avail=`get_prop available $TESTPOOL`
+ new_space_used=`get_prop used $TESTPOOL`
+
+ log_must within_limits $space_used $new_space_used $RESV_TOLERANCE
+ log_must within_limits $space_avail $new_space_avail $RESV_TOLERANCE
+done
+
+log_pass "Space correctly released when dataset reservation set to 'none'"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_006_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_006_pos.ksh
new file mode 100755
index 000000000000..ec1986c4547c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_006_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Reservations (if successfully set) guarantee a minimum amount of space
+# for a dataset. Unlike quotas however there should be no restrictions
+# on accessing space outside of the limits of the reservation (if the
+# space is available in the pool). Verify that in a filesystem with a
+# reservation set that its possible to create files both within the
+# reserved space and also outside.
+#
+# STRATEGY:
+# 1) Create a filesystem
+# 2) Get the space used and available in the pool
+# 3) Set a reservation on the filesystem
+# 4) Verify can write a file that is bigger than the reserved space
+#
+# i.e. we start writing within the reserved region and then continue
+# for 20MB outside it.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ [[ -e $TESTDIR/$TESTFILE1 ]] && log_must rm -rf $TESTDIR/$TESTFILE1
+ log_must zfs set reservation=none $TESTPOOL/$TESTFS
+}
+
+log_onexit cleanup
+
+log_assert "Verify can create files both inside and outside reserved areas"
+
+space_used=`get_prop used $TESTPOOL`
+
+log_must zfs set reservation=$RESV_SIZE $TESTPOOL/$TESTFS
+
+#
+# Calculate how many writes of BLOCK_SIZE it would take to fill
+# up RESV_SIZE + 20971520 (20 MB).
+#
+fill_size=`expr $RESV_SIZE + 20971520`
+write_count=`expr $fill_size / $BLOCK_SIZE`
+
+log_must file_write -o create -f $TESTDIR/$TESTFILE1 -b $BLOCK_SIZE \
+ -c $write_count -d 0
+
+log_pass "Able to create files inside and outside reserved area"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_007_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_007_pos.ksh
new file mode 100755
index 000000000000..48d6b40ad05a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_007_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 2007 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/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Setting a reservation on dataset should have no effect on any other
+# dataset at the same level in the hierarchy beyond using up available
+# space in the pool.
+#
+# STRATEGY:
+# 1) Create a filesystem
+# 2) Set a reservation on the filesystem
+# 3) Create another filesystem at the same level
+# 4) Set a reservation on the second filesystem
+# 5) Destroy both the filesystems
+# 6) Verify space accounted for correctly
+#
+
+verify_runnable "both"
+
+log_assert "Verify reservations on data sets doesn't affect other data sets " \
+ "at same level except for consuming space from common pool"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS2
+
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+space_avail=`get_prop available $TESTPOOL`
+space_used=`get_prop used $TESTPOOL`
+
+resv_size_set=`expr $space_avail / 3`
+
+#
+# Function which creates two datasets, sets reservations on them,
+# then destroys them and ensures that space is correctly accounted
+# for.
+#
+# Any special arguments for create are passed in via the args
+# parameter.
+#
+function create_resv_destroy { # args1 dataset1 args2 dataset2
+
+ args1=$1
+ dataset1=$2
+ args2=$3
+ dataset2=$4
+
+ log_must zfs create $args1 $dataset1
+
+ log_must zfs set reservation=$RESV_SIZE $dataset1
+
+ avail_aft_dset1=`get_prop available $TESTPOOL`
+ used_aft_dset1=`get_prop used $TESTPOOL`
+
+ log_must zfs create $args2 $dataset2
+
+ log_must zfs set reservation=$RESV_SIZE $dataset2
+
+ #
+ # After destroying the second dataset the space used and
+ # available totals should revert back to the values they
+ # had after creating the first dataset.
+ #
+ log_must zfs destroy -f $dataset2
+
+ avail_dest_dset2=`get_prop available $TESTPOOL`
+ used_dest_dset2=`get_prop used $TESTPOOL`
+
+ log_must within_limits $avail_aft_dset1 $avail_dest_dset2 $RESV_TOLERANCE
+ log_must within_limits $used_aft_dset1 $used_dest_dset2 $RESV_TOLERANCE
+
+
+ # After destroying the first dataset the space used and
+ # space available totals should revert back to the values
+ # they had when the pool was first created.
+ log_must zfs destroy -f $dataset1
+
+ avail_dest_dset1=`get_prop available $TESTPOOL`
+ used_dest_dset1=`get_prop used $TESTPOOL`
+
+ log_must within_limits $avail_dest_dset1 $space_avail $RESV_TOLERANCE
+ log_must within_limits $used_dest_dset1 $space_used $RESV_TOLERANCE
+}
+
+create_resv_destroy "" $TESTPOOL/$TESTFS1 "" $TESTPOOL/$TESTFS2
+create_resv_destroy "" $TESTPOOL/$TESTFS2 "" $TESTPOOL/$TESTFS1
+
+log_pass "Verify reservations on data sets doesn't affect other data sets at" \
+ " same level except for consuming space from common pool"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_008_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_008_pos.ksh
new file mode 100755
index 000000000000..a0cd039b1839
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_008_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Setting a reservation reserves a defined minimum amount of space for
+# a dataset, and prevents other datasets using that space. Verify that
+# reducing the reservation on a filesystem allows other datasets in
+# the pool to use that space.
+#
+# STRATEGY:
+# 1) Create multiple filesystems
+# 2) Set reservations on all bar one of the filesystems
+# 3) Fill up the one non-reserved filesystem
+# 4) Reduce one of the reservations and verify can write more
+# data into the non-reserved filesystem
+#
+
+verify_runnable "both"
+
+log_assert "Verify reducing reservation allows other datasets to use space"
+
+function cleanup
+{
+ typeset -i loop=0
+ while (($loop < $RESV_NUM_FS)); do
+ datasetexists $TESTPOOL/${TESTFS}$loop && \
+ log_must zfs destroy -f $TESTPOOL/${TESTFS}$loop
+
+ [[ -d ${TESTDIR}$loop ]] && log_must rm -r ${TESTDIR}$loop
+
+ ((loop = loop + 1))
+ done
+}
+
+log_onexit cleanup
+
+log_must create_multiple_fs $RESV_NUM_FS $TESTPOOL/$TESTFS $TESTDIR
+
+space_avail=`get_prop available $TESTPOOL`
+space_used=`get_prop used $TESTPOOL`
+
+#
+# To make sure this test doesn't take too long to execute on
+# large pools, we calculate a reservation setting which when
+# applied to all bar one of the filesystems (RESV_NUM_FS-1) will
+# ensure we have RESV_FREE_SPACE left free in the pool, which we will
+# be able to quickly fill.
+#
+resv_space_avail=`expr $space_avail - $RESV_FREE_SPACE`
+num_resv_fs=`expr $RESV_NUM_FS - 1` # Number of FS to which resv will be applied
+resv_size_set=`expr $resv_space_avail / $num_resv_fs`
+
+#
+# We set the reservations now, rather than when we created the filesystems
+# to allow us to take into account space used by the filesystem metadata
+#
+# Note we don't set a reservation on the first filesystem we created,
+# hence num=1 rather than zero below.
+#
+typeset -i num=1
+while (($num < $RESV_NUM_FS)); do
+ log_must zfs set reservation=$resv_size_set $TESTPOOL/$TESTFS$num
+ ((num = num + 1))
+done
+
+space_avail_still=`get_prop available $TESTPOOL`
+
+fill_size=`expr $space_avail_still + $RESV_TOLERANCE`
+write_count=`expr $fill_size / $BLOCK_SIZE`
+
+# Now fill up the first filesystem (which doesn't have a reservation set
+# and thus will use up whatever free space is left in the pool).
+num=0
+log_note "Writing to $TESTDIR$num/$TESTFILE1"
+
+file_write -o create -f $TESTDIR$num/$TESTFILE1 -b $BLOCK_SIZE \
+ -c $write_count -d 0
+ret=$?
+if (($ret != $ENOSPC)); then
+ log_fail "Did not get ENOSPC as expected (got $ret)."
+fi
+
+# Remove the reservation on one of the other filesystems and verify
+# can write more data to the original non-reservation filesystem.
+num=1
+log_must zfs set reservation=none $TESTPOOL/${TESTFS}$num
+num=0
+log_must file_write -o create -f ${TESTDIR}$num/$TESTFILE2 \
+ -b $(getconf PAGESIZE) -c 1000 -d 0
+
+log_pass "reducing reservation allows other datasets to use space"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_009_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_009_pos.ksh
new file mode 100755
index 000000000000..171577def5ef
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_009_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# In pool with a full filesystem and another filesystem with a reservation
+# setting the reservation on the second filesystem to 'none' should allow more
+# data to be written to the first filesystem.
+#
+#
+# STRATEGY:
+# 1) Create a filesystem as a dataset
+# 2) Create a filesystem at the same level
+# 3) Set a reservation on the dataset filesystem
+# 4) Fill up the filesystem
+# 5) Set the reservation on the dataset filesystem to 'none'
+# 6) Verify we can write more data to the first filesystem
+#
+
+verify_runnable "both"
+
+log_assert "Setting top level dataset reservation to 'none' allows more data " \
+ "to be written to top level filesystem"
+
+function cleanup
+{
+ log_must rm -rf $TESTDIR/$TESTFILE1
+ log_must rm -rf $TESTDIR/$TESTFILE2
+ log_must zfs destroy -f $TESTPOOL/$TESTFS1
+}
+
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS1
+
+space_avail=`get_prop available $TESTPOOL`
+
+#
+# To make sure this test doesn't take too long to execute on
+# large pools, we calculate a reservation setting which when
+# applied to the dataset will ensure we have RESV_FREE_SPACE
+# left free in the pool which we can quickly fill.
+#
+((resv_size_set = space_avail - RESV_FREE_SPACE))
+
+log_must zfs set reservation=$resv_size_set $TESTPOOL/$TESTFS1
+
+space_avail_still=`get_prop available $TESTPOOL`
+
+fill_size=`expr $space_avail_still + $RESV_TOLERANCE`
+write_count=`expr $fill_size / $BLOCK_SIZE`
+
+# Now fill up the filesystem (which doesn't have a reservation set
+# and thus will use up whatever free space is left in the pool).
+file_write -o create -f $TESTDIR/$TESTFILE1 -b $BLOCK_SIZE \
+ -c $write_count -d 0
+ret=$?
+if (($ret != $ENOSPC)); then
+ log_fail "Did not get ENOSPC as expected (got $ret)."
+fi
+
+log_must zfs set reservation=none $TESTPOOL/$TESTFS1
+
+log_must file_write -o create -f $TESTDIR/$TESTFILE2 \
+ -b $(getconf PAGESIZE) -c 1000 -d 0
+
+log_pass "Setting top level dataset reservation to 'none' allows more " \
+ "data to be written to the top level filesystem"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_010_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_010_pos.ksh
new file mode 100755
index 000000000000..2ca279a4a437
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_010_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 2007 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/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# In pool with a full filesystem and a filesystem with a reservation
+# destroying another filesystem should allow more data to be written to
+# the full filesystem
+#
+#
+# STRATEGY:
+# 1) Create a filesystem as dataset
+# 2) Create a filesystem at the same level
+# 3) Set a reservation on the dataset filesystem
+# 4) Fill up the second filesystem
+# 5) Destroy the dataset filesystem
+# 6) Verify can write more data to the full filesystem
+#
+
+verify_runnable "both"
+
+log_assert "Destroying top level filesystem with reservation allows more " \
+ "data to be written to another top level filesystem"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy $TESTPOOL/$TESTFS1
+
+ [[ -e $TESTDIR/$TESTFILE1 ]] && log_must rm -rf $TESTDIR/$TESTFILE1
+ [[ -e $TESTDIR/$TESTFILE2 ]] && log_must rm -rf $TESTDIR/$TESTFILE2
+}
+
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS1
+
+space_avail=`get_prop available $TESTPOOL`
+
+#
+# To make sure this test doesn't take too long to execute on
+# large pools, we calculate a reservation setting which when
+# applied to the dataset filesystem will ensure we have
+# RESV_FREE_SPACE left free in the pool.
+#
+((resv_size_set = space_avail - RESV_FREE_SPACE))
+
+log_must zfs set reservation=$resv_size_set $TESTPOOL/$TESTFS1
+
+space_avail_still=`get_prop available $TESTPOOL`
+
+fill_size=`expr $space_avail_still + $RESV_TOLERANCE`
+write_count=`expr $fill_size / $BLOCK_SIZE`
+
+# Now fill up the filesystem (which doesn't have a reservation set
+# and thus will use up whatever free space is left in the pool).
+file_write -o create -f $TESTDIR/$TESTFILE1 -b $BLOCK_SIZE -c $write_count -d 0
+ret=$?
+if (($ret != $ENOSPC)); then
+ log_fail "Did not get ENOSPC as expected (got $ret)."
+fi
+
+log_must zfs destroy -f $TESTPOOL/$TESTFS1
+
+log_must file_write -o create -f $TESTDIR/$TESTFILE2 \
+ -b $(getconf PAGESIZE) -c 1000 -d 0
+
+log_pass "Destroying top level filesystem with reservation allows more data " \
+ "to be written to another top level filesystem"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_011_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_011_pos.ksh
new file mode 100755
index 000000000000..a6abe9db6a13
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_011_pos.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# ZFS has two mechanisms dealing with space for datasets, namely
+# reservations and quotas. Setting one should not affect the other,
+# provided the values are legal (i.e. enough space in pool etc).
+#
+# STRATEGY:
+# 1) Create one filesystem
+# 2) Get the current quota setting
+# 3) Set a reservation
+# 4) Verify that the quota value remains unchanged
+#
+
+verify_runnable "both"
+
+log_assert "Verify reservation settings do not affect quota settings"
+
+function cleanup
+{
+ log_must zero_reservation $TESTPOOL/$TESTFS
+}
+
+log_onexit cleanup
+
+space_avail=`get_prop available $TESTPOOL`
+
+((resv_size_set = (space_avail - RESV_DELTA) / 2))
+
+fs_quota=`zfs get quota $TESTPOOL/$TESTFS`
+
+log_must zfs set reservation=$resv_size_set $TESTPOOL/$TESTFS
+
+new_fs_quota=`zfs get quota $TESTPOOL/$TESTFS`
+
+if [[ $fs_quota != $new_fs_quota ]]; then
+ log_fail "Quota value on $TESTFS has changed " \
+ "($fs_quota != $new_fs_quota)"
+fi
+
+log_pass "Quota settings unaffected by reservation settings"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_012_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_012_pos.ksh
new file mode 100755
index 000000000000..5ab0952b1910
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_012_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 2009 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/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# A reservation guarantees a certain amount of space for a dataset.
+# Nothing else which happens in the same pool should affect that
+# space, i.e. even if the rest of the pool fills up the reserved
+# space should still be accessible.
+#
+# STRATEGY:
+# 1) Create 2 filesystems
+# 2) Set a reservation on one filesystem
+# 3) Fill up the other filesystem (which does not have a reservation
+# set) until all space is consumed
+# 4) Verify can still write to the filesystem which has a reservation
+#
+
+verify_runnable "both"
+
+log_assert "Verify reservations protect space"
+
+function cleanup
+{
+ log_must zfs destroy -f $TESTPOOL/$TESTFS2
+ log_must zero_reservation $TESTPOOL/$TESTFS
+
+ [[ -e $TESTDIR/$TESTFILE2 ]] && log_must rm -rf $TESTDIR/$TESTFILE2
+ [[ -d $TESTDIR2 ]] && log_must rm -rf $TESTDIR2
+}
+
+log_onexit cleanup
+
+log_must zfs create $TESTPOOL/$TESTFS2
+log_must zfs set mountpoint=$TESTDIR2 $TESTPOOL/$TESTFS2
+
+space_avail=`get_prop available $TESTPOOL`
+
+((resv_size_set = space_avail - RESV_FREE_SPACE))
+
+log_must zfs set reservation=$resv_size_set $TESTPOOL/$TESTFS
+
+((write_count = (RESV_FREE_SPACE + RESV_TOLERANCE) / BLOCK_SIZE))
+
+file_write -o create -f $TESTDIR2/$TESTFILE1 -b $BLOCK_SIZE -c $write_count \
+ -d 0
+ret=$?
+if [[ $ret != $ENOSPC ]]; then
+ log_fail "Did not get ENOSPC (got $ret) for non-reserved filesystem"
+fi
+
+((write_count = (RESV_FREE_SPACE - RESV_TOLERANCE) / BLOCK_SIZE))
+log_must file_write -o create -f $TESTDIR/$TESTFILE2 -b $BLOCK_SIZE -c \
+ $write_count -d 0
+
+log_pass "Reserved space preserved correctly"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_013_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_013_pos.ksh
new file mode 100755
index 000000000000..6a80bb575dc4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_013_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Reservation properties on data objects should be preserved when the
+# pool within which they are contained is exported and then re-imported.
+#
+#
+# STRATEGY:
+# 1) Create a filesystem as dataset
+# 2) Create another filesystem at the same level
+# 3) Create a regular volume at the same level
+# 4) Create a sparse volume at the same level
+# 5) Create a filesystem within the dataset filesystem
+# 6) Set reservations on all filesystems
+# 7) Export the pool
+# 8) Re-import the pool
+# 9) Verify that the reservation settings are correct
+#
+
+verify_runnable "global"
+
+log_assert "Reservation properties preserved across exports and imports"
+
+function cleanup
+{
+ for obj in $OBJ_LIST; do
+ datasetexists $obj && log_must zfs destroy -f $obj
+ done
+
+ log_must zero_reservation $TESTPOOL/$TESTFS
+}
+log_onexit cleanup
+
+OBJ_LIST="$TESTPOOL/$TESTFS1/$TESTFS2 $TESTPOOL/$TESTFS1 $TESTPOOL/$TESTVOL \
+ $TESTPOOL/$TESTVOL2"
+
+log_must zfs create $TESTPOOL/$TESTFS1
+log_must zfs create $TESTPOOL/$TESTFS1/$TESTFS2
+
+space_avail=$(get_prop available $TESTPOOL)
+[[ $? -ne 0 ]] && \
+ log_fail "Unable to get space available property for $TESTPOOL"
+
+typeset -il resv_set=space_avail/5
+resv_set=$(floor_volsize $resv_set)
+typeset -il sparse_vol_set_size=space_avail*5
+sparse_vol_set_size=$(floor_volsize $sparse_vol_set_size)
+
+# When initially created, a regular volume's reservation property is set
+# equal to its size (unlike a sparse volume), so we don't need to set it
+# explicitly later on
+log_must zfs create -V $resv_set $TESTPOOL/$TESTVOL
+log_must zfs create -s -V $sparse_vol_set_size $TESTPOOL/$TESTVOL2
+
+log_must zfs set reservation=$resv_set $TESTPOOL/$TESTFS
+log_must zfs set reservation=$resv_set $TESTPOOL/$TESTFS1
+log_must zfs set reservation=$resv_set $TESTPOOL/$TESTFS1/$TESTFS2
+log_must zfs set reservation=$resv_set $TESTPOOL/$TESTVOL2
+
+log_must zpool export $TESTPOOL
+log_must zpool import $TESTPOOL
+
+for obj in $TESTPOOL/$TESTFS $OBJ_LIST; do
+
+ if [[ $obj == $TESTPOOL/$TESTVOL ]]; then
+ expected=$(volsize_to_reservation $obj $resv_set)
+ found=$(get_prop refreservation $obj)
+ else
+ expected=$resv_set
+ found=$(get_prop reservation $obj)
+ fi
+
+ [[ $found != $expected ]] && \
+ log_fail "Reservation property for $obj incorrect. Expected " \
+ "$expected but got $found."
+done
+
+log_pass "Reservation properties preserved across exports and imports"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_014_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_014_pos.ksh
new file mode 100755
index 000000000000..e8bd91d00e68
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_014_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# A reservation cannot exceed the quota on a dataset
+#
+# STRATEGY:
+# 1) Create a filesystem and volume
+# 2) Set a quota on the filesystem
+# 3) Attempt to set a reservation larger than the quota. Verify
+# that the attempt fails.
+# 4) Repeat 2-3 for volume
+#
+
+verify_runnable "both"
+
+log_assert "Verify cannot set reservation larger than quota"
+
+function cleanup
+{
+ #
+ # Note we don't destroy $TESTFS as it's used by other tests
+ for obj in $OBJ_LIST ; do
+ datasetexists $obj && log_must zfs destroy -f $obj
+ done
+
+ log_must zero_reservation $TESTPOOL/$TESTFS
+}
+log_onexit cleanup
+
+space_avail=`get_prop available $TESTPOOL`
+
+if ! is_global_zone ; then
+ OBJ_LIST=""
+else
+ OBJ_LIST="$TESTPOOL/$TESTVOL $TESTPOOL/$TESTVOL2"
+
+ ((vol_set_size = space_avail / 4))
+ vol_set_size=$(floor_volsize $vol_set_size)
+ ((sparse_vol_set_size = space_avail * 4))
+ sparse_vol_set_size=$(floor_volsize $sparse_vol_set_size)
+
+ log_must zfs create -V $vol_set_size $TESTPOOL/$TESTVOL
+ log_must zfs create -s -V $sparse_vol_set_size $TESTPOOL/$TESTVOL2
+fi
+
+for obj in $TESTPOOL/$TESTFS $OBJ_LIST ; do
+
+ space_avail=`get_prop available $obj`
+ ((quota_set_size = space_avail / 3))
+
+ #
+ # Volumes do not support quota so only need to explicitly
+ # set quotas for filesystems.
+ #
+ # The maximum reservation value that can be set on a volume
+ # is determined by the quota set on its parent filesystems or
+ # the amount of space in the pool, whichever is smaller.
+ #
+ if [[ $obj == $TESTPOOL/$TESTFS ]]; then
+ log_must zfs set quota=$quota_set_size $obj
+ ((resv_set_size = quota_set_size + RESV_SIZE))
+ elif [[ $obj == $TESTPOOL/$TESTVOL || $obj == $TESTPOOL/$TESTVOL2 ]]
+ then
+ resv_set_size=`expr $space_avail + $RESV_DELTA`
+ fi
+
+ orig_quota=`get_prop quota $obj`
+
+ log_mustnot zfs set reservation=$resv_set_size $obj
+ new_quota=`get_prop quota $obj`
+
+ if [[ $orig_quota != $new_quota ]]; then
+ log_fail "Quota value changed from $orig_quota " \
+ "to $new_quota"
+ fi
+
+ if [[ $obj == $TESTPOOL/$TESTFS ]]; then
+ log_must zfs set quota=none $obj
+ fi
+done
+
+log_pass "As expected cannot set reservation larger than quota"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_015_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_015_pos.ksh
new file mode 100755
index 000000000000..d67f8c7ec2f6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_015_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# In pool with a full filesystem and a regular volume with an implicit
+# reservation, setting the reservation on the volume to 'none' should allow
+# more data to be written to the filesystem.
+#
+#
+# STRATEGY:
+# 1) Create a regular non-sparse volume (which implicitly sets the reservation
+# property to a value equal to the volume size)
+# 2) Create a filesystem at the same level
+# 3) Fill up the filesystem
+# 4) Set the reservation on the volume to 'none'
+# 5) Verify can write more data to the filesystem
+#
+
+verify_runnable "global"
+
+log_assert "Setting volume reservation to 'none' allows more data to be " \
+ "written to top level filesystem"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTVOL && \
+ log_must zfs destroy $TESTPOOL/$TESTVOL
+
+ [[ -e $TESTDIR/$TESTFILE1 ]] && log_must rm -rf $TESTDIR/$TESTFILE1
+ [[ -e $TESTDIR/$TESTFILE2 ]] && log_must rm -rf $TESTDIR/$TESTFILE2
+}
+log_onexit cleanup
+
+space_avail=$(largest_volsize_from_pool $TESTPOOL)
+
+#
+# To make sure this test doesn't take too long to execute on
+# large pools, we calculate a volume size which when applied
+# to the volume will ensure we have RESV_FREE_SPACE
+# left free in the pool which we can quickly fill.
+#
+((resv_size_set = space_avail - RESV_FREE_SPACE))
+resv_size_set=$(floor_volsize $resv_size_set)
+
+log_must zfs create -V $resv_size_set $TESTPOOL/$TESTVOL
+
+space_avail_still=`get_prop available $TESTPOOL`
+
+fill_size=$((space_avail_still + $RESV_TOLERANCE))
+write_count=$((fill_size / BLOCK_SIZE))
+
+# Now fill up the filesystem (which doesn't have a reservation set
+# and thus will use up whatever free space is left in the pool).
+file_write -o create -f $TESTDIR/$TESTFILE1 -b $BLOCK_SIZE -c $write_count -d 0
+ret=$?
+if (($ret != $ENOSPC)); then
+ log_fail "Did not get ENOSPC as expected (got $ret)."
+fi
+
+log_must zfs set refreservation=none $TESTPOOL/$TESTVOL
+
+log_must file_write -o create -f $TESTDIR/$TESTFILE2 \
+ -b $(getconf PAGESIZE) -c 1000 -d 0
+
+log_pass "Setting top level volume reservation to 'none' allows more " \
+ "data to be written to the top level filesystem"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_016_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_016_pos.ksh
new file mode 100755
index 000000000000..cbb1db658b33
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_016_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# In pool with a full filesystem and a regular volume (with implicit
+# reservation) destroying the volume should allow more data to be written
+# to the filesystem
+#
+#
+# STRATEGY:
+# 1) Create a regular (non-sparse) volume
+# 2) Create a filesystem at the same level
+# 3) Fill up the filesystem
+# 4) Destroy the volume
+# 5) Verify can write more data to the filesystem
+#
+
+verify_runnable "global"
+
+log_assert "Destroying a regular volume with reservation allows more data to" \
+ " be written to top level filesystem"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTVOL && \
+ log_must zfs destroy $TESTPOOL/$TESTVOL
+
+ [[ -e $TESTDIR/$TESTFILE1 ]] && log_must rm -rf $TESTDIR/$TESTFILE1
+ [[ -e $TESTDIR/$TESTFILE2 ]] && log_must rm -rf $TESTDIR/$TESTFILE2
+}
+log_onexit cleanup
+
+space_avail=$(largest_volsize_from_pool $TESTPOOL)
+
+#
+# To make sure this test doesn't take too long to execute on
+# large pools, we calculate a volume size which will ensure we
+# have RESV_FREE_SPACE left free in the pool.
+#
+((vol_set_size = space_avail - RESV_FREE_SPACE))
+vol_set_size=$(floor_volsize $vol_set_size)
+
+# Creating a regular volume implicitly sets its reservation
+# property to the same value.
+log_must zfs create -V $vol_set_size $TESTPOOL/$TESTVOL
+
+space_avail_still=$(get_prop available $TESTPOOL)
+fill_size=$((space_avail_still + $RESV_TOLERANCE))
+write_count=$((fill_size / BLOCK_SIZE))
+
+# Now fill up the filesystem (which doesn't have a reservation set
+# and thus will use up whatever free space is left in the pool).
+file_write -o create -f $TESTDIR/$TESTFILE1 -b $BLOCK_SIZE -c $write_count -d 0
+ret=$?
+if (($ret != $ENOSPC)); then
+ log_fail "Did not get ENOSPC as expected (got $ret)."
+fi
+
+log_must zfs destroy -f $TESTPOOL/$TESTVOL
+
+log_must file_write -o create -f $TESTDIR/$TESTFILE2 \
+ -b $(getconf PAGESIZE) -c 1000 -d 0
+
+log_pass "Destroying volume with reservation allows more data to be written " \
+ "to top level filesystem"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_017_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_017_pos.ksh
new file mode 100755
index 000000000000..bb3af67d24d3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_017_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# For a sparse volume changes to the volsize are not reflected in the
+# reservation.
+#
+# STRATEGY:
+# 1) Create a regular and sparse volume
+# 2) Get the space available in the pool
+# 3) Set reservation with various sizes on the regular and sparse volumes
+# 4) Verify that the 'reservation' property for the regular volume has
+# the correct value.
+# 5) Verify that the 'reservation' property for the sparse volume is set to
+# 'none'
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset vol
+
+ for vol in $regvol $sparsevol; do
+ destroy_dataset $vol
+ done
+}
+log_onexit cleanup
+
+log_assert "Verify that the volsize changes of sparse volumes are not " \
+ "reflected in the reservation."
+log_onexit cleanup
+
+# Create a regular and sparse volume for testing.
+regvol=$TESTPOOL/$TESTVOL
+sparsevol=$TESTPOOL/$TESTVOL2
+log_must zfs create -V 64M $regvol
+log_must zfs create -s -V 64M $sparsevol
+
+typeset vsize=$(get_prop available $TESTPOOL)
+typeset iterate=10
+typeset regreserv
+typeset sparsereserv
+typeset volblocksize=$(get_prop volblocksize $regvol)
+typeset blknum=0
+typeset randomblknum
+((blknum = vsize / volblocksize))
+
+while ((iterate > 1)); do
+ ((randomblknum = 1 + RANDOM % blknum))
+ # Make sure volsize is a multiple of volume block size
+ ((vsize = randomblknum * volblocksize))
+ log_must zfs set volsize=$vsize $regvol
+ log_must zfs set volsize=$vsize $sparsevol
+ vsize=$(volsize_to_reservation $regvol $vsize)
+ regreserv=$(get_prop refreservation $regvol)
+ sparsereserv=$(get_prop reservation $sparsevol)
+ ((sparsereserv == vsize)) && \
+ log_fail "volsize changes of sparse volume is reflected in " \
+ "reservation (expected $vsize, got $sparsereserv)."
+ ((regreserv != vsize)) && \
+ log_fail "volsize changes of regular volume is not reflected " \
+ "in reservation (expected $vsize, got $regreserv)."
+ ((iterate = iterate - 1))
+done
+
+log_pass "The volsize changes of sparse volumes are not reflected in the " \
+ "reservation"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh
new file mode 100755
index 000000000000..0969a6877316
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_018_pos.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Verify that reservation doesn't inherit its value from parent.
+#
+# STRATEGY:
+# 1) Create a filesystem tree
+# 2) Set reservation for parents
+# 3) Verify that the 'reservation' for descendent doesnot inherit the value.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $fs_child && log_must zfs destroy $fs_child
+ log_must zfs set reservation=$reserv_val $fs
+}
+
+log_onexit cleanup
+
+log_assert "Verify that reservation doesnot inherit its value from parent."
+
+fs=$TESTPOOL/$TESTFS
+fs_child=$TESTPOOL/$TESTFS/$TESTFS
+
+space_avail=$(get_prop available $fs)
+reserv_val=$(get_prop reservation $fs)
+typeset reservsize=$space_avail
+((reservsize = reservsize / 2))
+log_must zfs set reservation=$reservsize $fs
+
+log_must zfs create $fs_child
+rsv_space=$(get_prop reservation $fs_child)
+[[ $rsv_space == $reservsize ]] && \
+ log_fail "The reservation of child dataset inherits its value from parent."
+
+log_pass "reservation doesnot inherit its value from parent as expected."
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_019_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_019_pos.ksh
new file mode 100755
index 000000000000..45da06a9f42f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_019_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 2018 Joyent, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# A thin provisioned volume can become thick provisioned with 'zfs set
+# refreservation=auto'.
+#
+# STRATEGY:
+# 1) Create a sparse value.
+# 2) Use zfs set refreservation=auto to make it thick provisioned.
+# 3) Verify that refreservation is now the size predicted by
+# volsize_to_reservation().
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_dataset "$TESTPOOL/$TESTVOL" "-f"
+}
+
+log_onexit cleanup
+
+log_assert "A thin provisioned volume can become thick provisioned with" \
+ "'zfs set refreservation=auto'."
+
+space_avail=$(get_prop available $TESTPOOL)
+(( vol_size = (space_avail / 2) & ~(1024 * 1024 - 1) ))
+
+vol=$TESTPOOL/$TESTVOL
+
+# Create sparse vol and verify
+log_must zfs create -V $vol_size -s $vol
+resv=$(get_prop refreservation $vol)
+log_must test $resv -eq 0
+
+# Set refreservation
+log_must zfs set refreservation=auto $vol
+
+# Verify
+resv=$(get_prop refreservation $vol)
+expected=$(volsize_to_reservation $vol $vol_size)
+log_must test $resv -eq $expected
+
+log_pass "Setting refreservation=auto set refreservation to expected value"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_020_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_020_pos.ksh
new file mode 100755
index 000000000000..68d46d0a0eea
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_020_pos.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 2018 Joyent, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Cloning a thick provisioned volume results in a sparse volume
+#
+# STRATEGY:
+# 1) Create a thick provisioned volume.
+# 2) Snapshot and clone it.
+# 3) Verify that the clone is sparse.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ # Destroy first vol and descendants in one go.
+ destroy_dataset "$TESTPOOL/$TESTVOL" "-Rf"
+}
+
+log_onexit cleanup
+
+log_assert "Cloning a thick provisioned volume results in a sparse volume"
+
+space_avail=$(get_prop available $TESTPOOL)
+(( vol_size = (space_avail / 4) & ~(1024 * 1024 - 1) ))
+
+vol=$TESTPOOL/$TESTVOL
+snap=$vol@clone
+vol2=$TESTPOOL/$TESTVOL2
+
+# Create sparse vol and verify
+log_must zfs create -V $vol_size $vol
+resv=$(get_prop refreservation $vol)
+expected=$(volsize_to_reservation $vol $vol_size)
+log_must test $resv -eq $expected
+
+# Clone it
+log_must zfs snapshot $snap
+log_must zfs clone $snap $vol2
+
+# Verify
+resv=$(get_prop refreservation $vol2)
+log_must test $resv -eq 0
+
+log_pass "Cloning a thick provisioned volume results in a sparse volume"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_021_neg.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_021_neg.ksh
new file mode 100755
index 000000000000..c99a82c5db71
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_021_neg.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 2018 Joyent, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# The use of refreservation=auto on a filesystem does not change the
+# refreservation and results in an error.
+#
+# STRATEGY:
+# 1) Create a filesystem
+# 2) Verify that zfs set refreservation=auto fails without changing
+# refreservation from none.
+# 3) Set refreservation to a valid value.
+# 4) Verify that zfs set refreservation=auto fails without changing
+# refreservation from the previous value.
+#
+
+verify_runnable "both"
+
+fs=$TESTPOOL/$TESTFS/$(basename $0).$$
+
+function cleanup
+{
+ destroy_dataset "$fs" "-f"
+}
+
+log_onexit cleanup
+
+log_assert "refreservation=auto on a filesystem generates an error without" \
+ "changing refreservation"
+
+space_avail=$(get_prop available $TESTPOOL)
+(( fs_size = space_avail / 4 ))
+
+# Create a filesystem with no refreservation
+log_must zfs create $fs
+resv=$(get_prop refreservation $fs)
+log_must test $resv -eq 0
+
+# Verify that refreservation=auto fails without altering refreservation
+log_mustnot zfs set refreservation=auto $fs
+resv=$(get_prop refreservation $fs)
+log_must test $resv -eq 0
+
+# Set refreservation and verify
+log_must zfs set refreservation=$fs_size $fs
+resv=$(get_prop refreservation $fs)
+log_must test $resv -eq $fs_size
+
+# Verify that refreservation=auto fails without altering refreservation
+log_mustnot zfs set refreservation=auto $fs
+resv=$(get_prop refreservation $fs)
+log_must test $resv -eq $fs_size
+
+log_pass "refreservation=auto does not work on filesystems, as expected"
diff --git a/tests/zfs-tests/tests/functional/reservation/reservation_022_pos.ksh b/tests/zfs-tests/tests/functional/reservation/reservation_022_pos.ksh
new file mode 100755
index 000000000000..879dc5da5a85
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/reservation_022_pos.ksh
@@ -0,0 +1,82 @@
+#!/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 Joyent, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/reservation/reservation.shlib
+
+#
+# DESCRIPTION:
+#
+# Cloning a volume with -o refreservation=auto creates a thick provisioned
+# volume
+#
+# STRATEGY:
+# 1) Create a sparse volume.
+# 2) Snapshot and clone it, using clone -o refreservation=auto.
+# 3) Verify that the clone has refreservation that matches the size predicted by
+# volsize_to_reservation().
+# 4) Snapshot this second volume and clone it, using clone -o
+# refreservation=auto.
+# 5) Verify that the second clone has refreservation that matches the size
+# predicted by volsize_to_reservation().
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ # Destroy first vol and descendants in one go.
+ destroy_dataset "$TESTPOOL/$TESTVOL" "-Rf"
+}
+
+log_onexit cleanup
+
+log_assert "Cloning a volume with -o refreservation=auto creates a thick" \
+ "provisioned volume"
+
+space_avail=$(get_prop available $TESTPOOL)
+(( vol_size = (space_avail / 4) & ~(1024 * 1024 - 1) ))
+
+vol=$TESTPOOL/$TESTVOL
+vol2=$TESTPOOL/$TESTVOL2
+vol3=$TESTPOOL/$TESTVOL2-again
+
+# Create sparse vol and verify
+log_must zfs create -s -V $vol_size $vol
+resv=$(get_prop refreservation $vol)
+log_must test $resv -eq 0
+
+# Clone it
+snap=$vol@clone
+log_must zfs snapshot $snap
+log_must zfs clone -o refreservation=auto $snap $vol2
+
+# Verify it is thick provisioned
+resv=$(get_prop refreservation $vol2)
+expected=$(volsize_to_reservation $vol2 $vol_size)
+log_must test $resv -eq $expected
+
+# Clone the thick provisioned volume
+snap=$vol2@clone
+log_must zfs snapshot $snap
+log_must zfs clone -o refreservation=auto $snap $vol3
+
+# Verify new newest clone is also thick provisioned
+resv=$(get_prop refreservation $vol3)
+expected=$(volsize_to_reservation $vol3 $vol_size)
+log_must test $resv -eq $expected
+
+log_pass "Cloning a thick provisioned volume results in a sparse volume"
diff --git a/tests/zfs-tests/tests/functional/reservation/setup.ksh b/tests/zfs-tests/tests/functional/reservation/setup.ksh
new file mode 100755
index 000000000000..c39034783555
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/reservation/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_setup_noexit ${DISKS%% *}
+log_pass
diff --git a/tests/zfs-tests/tests/functional/rootpool/Makefile.am b/tests/zfs-tests/tests/functional/rootpool/Makefile.am
new file mode 100644
index 000000000000..ca5ad14fdbb1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rootpool/Makefile.am
@@ -0,0 +1,7 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/rootpool
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ rootpool_002_neg.ksh \
+ rootpool_003_neg.ksh \
+ rootpool_007_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/rootpool/cleanup.ksh b/tests/zfs-tests/tests/functional/rootpool/cleanup.ksh
new file mode 100755
index 000000000000..8f043259fb91
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rootpool/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/rootpool/rootpool_002_neg.ksh b/tests/zfs-tests/tests/functional/rootpool/rootpool_002_neg.ksh
new file mode 100755
index 000000000000..32bacf753a0e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rootpool/rootpool_002_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) 2013, 2016 by Delphix. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# the zfs rootpool/rootfs can not be destroyed
+#
+# STRATEGY:
+# 1) check if the current system is installed as zfs root
+# 2) get the rootpool
+# 3) try to destroy the rootpool, which should fail
+# 4) try to destroy the rootpool filesystem, which should fail
+#
+
+verify_runnable "global"
+log_assert "zpool/zfs destroy <rootpool> should fail"
+
+typeset rootpool=$(get_rootpool)
+typeset tmpfile="$TEST_BASE_DIR/mounted-datasets.$$"
+
+# Collect the currently mounted ZFS filesystems, so that we can repair any
+# damage done by the attempted pool destroy. The destroy itself should fail,
+# but some filesystems can become unmounted in the process, and aren't
+# automatically remounted.
+mount -p | awk '{if ($4 == "zfs") print $1}' > $tmpfile
+
+log_mustnot zpool destroy $rootpool
+
+# Remount any filesystems that the destroy attempt unmounted.
+while read ds; do
+ mounted $ds || log_must zfs mount $ds
+done < $tmpfile
+rm -f $tmpfile
+
+log_mustnot zfs destroy $rootpool
+
+log_pass "rootpool/rootfs can not be destroyed"
diff --git a/tests/zfs-tests/tests/functional/rootpool/rootpool_003_neg.ksh b/tests/zfs-tests/tests/functional/rootpool/rootpool_003_neg.ksh
new file mode 100755
index 000000000000..3bb5d12edddf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rootpool/rootpool_003_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 2009 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
+
+#
+# DESCRIPTION:
+#
+# system related filesystems can not be renamed or destroyed
+#
+# STRATEGY:
+#
+# 1) check if the current system is installed as zfs rootfs
+# 2) get the rootfs
+# 3) try to rename the rootfs to some newfs, which should fail.
+# 4) try to destroy the rootfs, which should fail.
+# 5) try to destroy the rootfs with -f which should fail
+# 6) try to destroy the rootfs with -fR which should fail
+#
+
+verify_runnable "global"
+log_assert "system related filesystems can not be renamed or destroyed"
+
+typeset rootpool=$(get_rootpool)
+typeset rootfs=$(get_rootfs)
+
+log_mustnot zfs rename $rootfs $rootpool/newfs
+log_mustnot zfs rename -f $rootfs $rootpool/newfs
+
+log_mustnot zfs destroy $rootfs
+log_mustnot zfs destroy -f $rootfs
+
+log_pass "system related filesystems can not be renamed or destroyed"
diff --git a/tests/zfs-tests/tests/functional/rootpool/rootpool_007_pos.ksh b/tests/zfs-tests/tests/functional/rootpool/rootpool_007_pos.ksh
new file mode 100755
index 000000000000..e4d4268cc08e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rootpool/rootpool_007_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# the zfs rootfilesystem's compression property can be set to gzip[1-9]
+#
+# STRATEGY:
+# 1) check if the current system is installed as zfs root
+# 2) get the rootfs
+# 3) set the rootfs's compression to gzip 1-9 which should not fail.
+#
+
+verify_runnable "global"
+
+function cleanup {
+ [[ -n "$orig_compress" ]] && \
+ log_must zfs set compression=$orig_compress $rootfs
+}
+
+typeset assert_msg="the zfs rootfs's compression property can be set to \
+ gzip and gzip[1-9]"
+
+log_onexit cleanup
+log_assert $assert_msg
+
+typeset rootpool=$(get_rootpool)
+typeset rootfs=$(get_pool_prop bootfs $rootpool)
+typeset orig_compress=$(get_prop compression $rootfs)
+
+set -A gtype "gzip" "gzip-1" "gzip-2" "gzip-3" "gzip-4" "gzip-5" \
+ "gzip-6" "gzip-7" "gzip-8" "gzip-9"
+
+typeset -i i=0
+while (( i < ${#gtype[@]} )); do
+ log_must zfs set compression=${gtype[i]} $rootfs
+ (( i += 1 ))
+done
+
+log_pass $assert_msg
diff --git a/tests/zfs-tests/tests/functional/rootpool/setup.ksh b/tests/zfs-tests/tests/functional/rootpool/setup.ksh
new file mode 100755
index 000000000000..8d8097108190
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rootpool/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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+#
+# This functionality is supported under Linux, but these test cases
+# are disabled by default since they manipulate the systems root pool.
+#
+if is_linux || is_freebsd; then
+ log_unsupported "Supported but disabled by default"
+fi
diff --git a/tests/zfs-tests/tests/functional/rsend/Makefile.am b/tests/zfs-tests/tests/functional/rsend/Makefile.am
new file mode 100644
index 000000000000..cf6c727dfa16
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/Makefile.am
@@ -0,0 +1,63 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/rsend
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ recv_dedup.ksh \
+ recv_dedup_encrypted_zvol.ksh \
+ rsend_001_pos.ksh \
+ rsend_002_pos.ksh \
+ rsend_003_pos.ksh \
+ rsend_004_pos.ksh \
+ rsend_005_pos.ksh \
+ rsend_006_pos.ksh \
+ rsend_007_pos.ksh \
+ rsend_008_pos.ksh \
+ rsend_009_pos.ksh \
+ rsend_010_pos.ksh \
+ rsend_011_pos.ksh \
+ rsend_012_pos.ksh \
+ rsend_013_pos.ksh \
+ rsend_014_pos.ksh \
+ rsend_016_neg.ksh \
+ rsend_019_pos.ksh \
+ rsend_020_pos.ksh \
+ rsend_021_pos.ksh \
+ rsend_022_pos.ksh \
+ rsend_024_pos.ksh \
+ send_encrypted_files.ksh \
+ send_encrypted_hierarchy.ksh \
+ send_encrypted_props.ksh \
+ send_encrypted_truncated_files.ksh \
+ send-c_embedded_blocks.ksh \
+ send-c_incremental.ksh \
+ send-c_lz4_disabled.ksh \
+ send-c_mixed_compression.ksh \
+ send-c_props.ksh \
+ send-c_recv_dedup.ksh \
+ send-c_recv_lz4_disabled.ksh \
+ send-c_resume.ksh \
+ send-c_stream_size_estimate.ksh \
+ send-c_verify_contents.ksh \
+ send-c_verify_ratio.ksh \
+ send-c_volume.ksh \
+ send-c_zstreamdump.ksh \
+ send-cpL_varied_recsize.ksh \
+ send-L_toggle.ksh \
+ send_freeobjects.ksh \
+ send_partial_dataset.ksh \
+ send_realloc_dnode_size.ksh \
+ send_realloc_files.ksh \
+ send_realloc_encrypted_files.ksh \
+ send_spill_block.ksh \
+ send_holds.ksh \
+ send_hole_birth.ksh \
+ send_mixed_raw.ksh \
+ send-wR_encrypted_zvol.ksh
+
+dist_pkgdata_DATA = \
+ dedup.zsend.bz2 \
+ dedup_encrypted_zvol.bz2 \
+ dedup_encrypted_zvol.zsend.bz2 \
+ fs.tar.gz \
+ rsend.cfg \
+ rsend.kshlib
diff --git a/tests/zfs-tests/tests/functional/rsend/cleanup.ksh b/tests/zfs-tests/tests/functional/rsend/cleanup.ksh
new file mode 100755
index 000000000000..063fe9dd1f61
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/cleanup.ksh
@@ -0,0 +1,47 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+verify_runnable "both"
+
+if is_global_zone ; then
+ destroy_pool $POOL
+ destroy_pool $POOL2
+ poolexists $POOL3 && destroy_pool $POOL3
+else
+ cleanup_pool $POOL
+ cleanup_pool $POOL2
+ poolexists $POOL3 && cleanup_pool $POOL3
+fi
+log_must rm -rf $BACKDIR $TESTDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/rsend/dedup.zsend.bz2 b/tests/zfs-tests/tests/functional/rsend/dedup.zsend.bz2
new file mode 100644
index 000000000000..585e14852662
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/dedup.zsend.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/rsend/dedup_encrypted_zvol.bz2 b/tests/zfs-tests/tests/functional/rsend/dedup_encrypted_zvol.bz2
new file mode 100644
index 000000000000..73a5742fc302
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/dedup_encrypted_zvol.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/rsend/dedup_encrypted_zvol.zsend.bz2 b/tests/zfs-tests/tests/functional/rsend/dedup_encrypted_zvol.zsend.bz2
new file mode 100644
index 000000000000..04a6cb53f040
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/dedup_encrypted_zvol.zsend.bz2
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/rsend/fs.tar.gz b/tests/zfs-tests/tests/functional/rsend/fs.tar.gz
new file mode 100644
index 000000000000..cb6861c155b7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/fs.tar.gz
Binary files differ
diff --git a/tests/zfs-tests/tests/functional/rsend/recv_dedup.ksh b/tests/zfs-tests/tests/functional/rsend/recv_dedup.ksh
new file mode 100755
index 000000000000..e6e282a1c6f8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/recv_dedup.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) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Verifies that we can receive a dedup send stream by processing it with
+# "zstream redup".
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/recv "-r"
+ rm -r /$TESTPOOL/tar
+ rm $sendfile
+}
+log_onexit cleanup
+
+log_assert "Verify zfs can receive dedup send streams with 'zstream redup'"
+
+typeset sendfile_compressed=$STF_SUITE/tests/functional/rsend/dedup.zsend.bz2
+typeset sendfile=/$TESTPOOL/dedup.zsend
+typeset tarfile=$STF_SUITE/tests/functional/rsend/fs.tar.gz
+
+log_must eval "bzcat <$sendfile_compressed >$sendfile"
+log_must zfs create $TESTPOOL/recv
+log_must eval "zstream redup $sendfile | zfs recv -d $TESTPOOL/recv"
+
+log_must mkdir /$TESTPOOL/tar
+log_must tar --directory /$TESTPOOL/tar -xzf $tarfile
+log_must diff -r /$TESTPOOL/tar /$TESTPOOL/recv
+
+log_pass "zfs can receive dedup send streams with 'zstream redup'"
diff --git a/tests/zfs-tests/tests/functional/rsend/recv_dedup_encrypted_zvol.ksh b/tests/zfs-tests/tests/functional/rsend/recv_dedup_encrypted_zvol.ksh
new file mode 100755
index 000000000000..569fcd893e7d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/recv_dedup_encrypted_zvol.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) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Verifies that we can receive a dedup send stream of a zvol by processing it
+# with "zstream redup".
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/recv "-r"
+ rm $sendfile
+ rm $volfile
+ rm $keyfile
+}
+log_onexit cleanup
+
+log_assert "Verify zfs can receive raw, recursive, and deduplicated send streams"
+
+typeset keyfile=/$TESTPOOL/pkey
+typeset recvdev=$ZVOL_DEVDIR/$TESTPOOL/recv
+typeset sendfile_compressed=$STF_SUITE/tests/functional/rsend/dedup_encrypted_zvol.zsend.bz2
+typeset sendfile=/$TESTPOOL/dedup_encrypted_zvol.zsend
+typeset volfile_compressed=$STF_SUITE/tests/functional/rsend/dedup_encrypted_zvol.bz2
+typeset volfile=/$TESTPOOL/dedup_encrypted_zvol
+
+log_must eval "echo 'password' > $keyfile"
+
+log_must eval "bzcat <$sendfile_compressed >$sendfile"
+log_must eval "zstream redup $sendfile | zfs recv $TESTPOOL/recv"
+
+log_must zfs load-key $TESTPOOL/recv
+block_device_wait
+
+log_must eval "bzcat <$volfile_compressed >$volfile"
+log_must diff $volfile $recvdev
+
+log_pass "zfs can receive raw, recursive, and deduplicated send streams"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend.cfg b/tests/zfs-tests/tests/functional/rsend/rsend.cfg
new file mode 100644
index 000000000000..8400ecfe35b4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend.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.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+export BACKDIR=${TEST_BASE_DIR%%/}/backdir-rsend
+
+export DISK1=$(echo $DISKS | awk '{print $1}')
+export DISK2=$(echo $DISKS | awk '{print $2}')
+export DISK3=$(echo $DISKS | awk '{print $3}')
+
+export POOL=$TESTPOOL
+export POOL2=$TESTPOOL2
+export POOL3=$TESTPOOL3
+export FS=$TESTFS
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend.kshlib b/tests/zfs-tests/tests/functional/rsend/rsend.kshlib
new file mode 100644
index 000000000000..c82b0f008e32
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend.kshlib
@@ -0,0 +1,850 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2018 by Delphix. All rights reserved.
+# Copyright (c) 2020 by Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
+. $STF_SUITE/tests/functional/rsend/rsend.cfg
+
+#
+# Set up test model which includes various datasets
+#
+# @final
+# @snapB
+# @init
+# |
+# ______ pclone
+# | /
+# |@psnap
+# || @final
+# ||@final @final @snapC
+# ||@snapC @snapC @snapB
+# ||@snapA @snapB @snapA
+# ||@init @init @init
+# ||| | |
+# $pool -------- $FS ------- fs1 ------- fs2
+# \ \\_____ \ |
+# vol vol \____ \ @fsnap
+# | | \ \ \
+# @init @vsnap | ------------ fclone
+# @snapA @init \ | |
+# @final @snapB \ | @init
+# @snapC vclone @snapA
+# @final | @final
+# @init
+# @snapC
+# @final
+#
+# $1 pool name
+#
+function setup_test_model
+{
+ typeset pool=$1
+
+ log_must zfs create -p $pool/$FS/fs1/fs2
+
+ log_must zfs snapshot $pool@psnap
+ log_must zfs clone $pool@psnap $pool/pclone
+
+ if is_global_zone ; then
+ log_must zfs create -V 16M $pool/vol
+ log_must zfs create -V 16M $pool/$FS/vol
+ block_device_wait
+
+ log_must zfs snapshot $pool/$FS/vol@vsnap
+ log_must zfs clone $pool/$FS/vol@vsnap $pool/$FS/vclone
+ block_device_wait
+ fi
+
+ log_must snapshot_tree $pool/$FS/fs1/fs2@fsnap
+ log_must zfs clone $pool/$FS/fs1/fs2@fsnap $pool/$FS/fs1/fclone
+ log_must zfs snapshot -r $pool@init
+
+ log_must snapshot_tree $pool@snapA
+ log_must snapshot_tree $pool@snapC
+ log_must snapshot_tree $pool/pclone@snapB
+ log_must snapshot_tree $pool/$FS@snapB
+ log_must snapshot_tree $pool/$FS@snapC
+ log_must snapshot_tree $pool/$FS/fs1@snapA
+ log_must snapshot_tree $pool/$FS/fs1@snapB
+ log_must snapshot_tree $pool/$FS/fs1@snapC
+ log_must snapshot_tree $pool/$FS/fs1/fclone@snapA
+
+ if is_global_zone ; then
+ log_must zfs snapshot $pool/vol@snapA
+ log_must zfs snapshot $pool/$FS/vol@snapB
+ log_must zfs snapshot $pool/$FS/vol@snapC
+ log_must zfs snapshot $pool/$FS/vclone@snapC
+ fi
+
+ log_must zfs snapshot -r $pool@final
+
+ return 0
+}
+
+#
+# Cleanup the BACKDIR and given pool content and all the sub datasets
+#
+# $1 pool name
+#
+function cleanup_pool
+{
+ typeset pool=$1
+ log_must rm -rf $BACKDIR/*
+
+ if is_global_zone ; then
+ log_must_busy zfs destroy -Rf $pool
+ else
+ typeset list=$(zfs list -H -r -t all -o name $pool)
+ for ds in $list ; do
+ if [[ $ds != $pool ]] ; then
+ if datasetexists $ds ; then
+ log_must_busy zfs destroy -Rf $ds
+ fi
+ fi
+ done
+ fi
+
+ typeset mntpnt=$(get_prop mountpoint $pool)
+ if ! ismounted $pool ; then
+ # Make sure mountpoint directory is empty
+ if [[ -d $mntpnt ]]; then
+ log_must rm -rf $mntpnt/*
+ fi
+
+ log_must zfs mount $pool
+ fi
+ if [[ -d $mntpnt ]]; then
+ rm -rf $mntpnt/*
+ fi
+
+ return 0
+}
+
+function cleanup_pools
+{
+ cleanup_pool $POOL2
+ destroy_pool $POOL3
+}
+
+function cmp_md5s {
+ typeset file1=$1
+ typeset file2=$2
+
+ typeset sum1=$(md5digest $file1)
+ typeset sum2=$(md5digest $file2)
+ test "$sum1" = "$sum2"
+}
+
+#
+# Detect if the given two filesystems have same sub-datasets
+#
+# $1 source filesystem
+# $2 destination filesystem
+#
+function cmp_ds_subs
+{
+ typeset src_fs=$1
+ typeset dst_fs=$2
+
+ zfs list -r -H -t all -o name $src_fs > $BACKDIR/src1
+ zfs list -r -H -t all -o name $dst_fs > $BACKDIR/dst1
+
+ eval sed -e 's:^$src_fs:PREFIX:g' < $BACKDIR/src1 > $BACKDIR/src
+ eval sed -e 's:^$dst_fs:PREFIX:g' < $BACKDIR/dst1 > $BACKDIR/dst
+
+ diff $BACKDIR/src $BACKDIR/dst
+ typeset -i ret=$?
+
+ rm -f $BACKDIR/src $BACKDIR/dst $BACKDIR/src1 $BACKDIR/dst1
+
+ return $ret
+}
+
+#
+# Compare all the directories and files in two filesystems
+#
+# $1 source filesystem
+# $2 destination filesystem
+#
+function cmp_ds_cont
+{
+ typeset src_fs=$1
+ typeset dst_fs=$2
+
+ typeset srcdir dstdir
+ srcdir=$(get_prop mountpoint $src_fs)
+ dstdir=$(get_prop mountpoint $dst_fs)
+
+ diff -r $srcdir $dstdir > /dev/null 2>&1
+ return $?
+}
+
+#
+# Compare the given two dataset properties
+#
+# $1 dataset 1
+# $2 dataset 2
+#
+function cmp_ds_prop
+{
+ typeset dtst1=$1
+ typeset dtst2=$2
+ typeset -a props=("type" "origin" "volblocksize" "acltype" "dnodesize" \
+ "atime" "canmount" "checksum" "compression" "copies" "devices" \
+ "exec" "quota" "readonly" "recordsize" "reservation" "setuid" \
+ "snapdir" "version" "volsize" "xattr" "mountpoint");
+ if is_freebsd; then
+ props+=("jailed")
+ else
+ props+=("zoned")
+ fi
+
+ for prop in $props;
+ do
+ zfs get -H -o property,value,source $prop $dtst1 >> \
+ $BACKDIR/dtst1
+ zfs get -H -o property,value,source $prop $dtst2 >> \
+ $BACKDIR/dtst2
+ done
+
+ eval sed -e 's:$dtst1:PREFIX:g' < $BACKDIR/dtst1 > $BACKDIR/dtst1
+ eval sed -e 's:$dtst2:PREFIX:g' < $BACKDIR/dtst2 > $BACKDIR/dtst2
+
+ diff $BACKDIR/dtst1 $BACKDIR/dtst2
+ typeset -i ret=$?
+
+ rm -f $BACKDIR/dtst1 $BACKDIR/dtst2
+
+ return $ret
+
+}
+
+#
+# Random create directories and files
+#
+# $1 directory
+#
+function random_tree
+{
+ typeset dir=$1
+
+ if [[ -d $dir ]]; then
+ rm -rf $dir
+ fi
+ mkdir -p $dir
+ typeset -i ret=$?
+
+ typeset -i nl nd nf
+ ((nl = RANDOM % 6 + 1))
+ ((nd = RANDOM % 3 ))
+ ((nf = RANDOM % 5 ))
+ mktree -b $dir -l $nl -d $nd -f $nf
+ ((ret |= $?))
+
+ return $ret
+}
+
+#
+# Put data in filesystem and take snapshot
+#
+# $1 snapshot name
+#
+function snapshot_tree
+{
+ typeset snap=$1
+ typeset ds=${snap%%@*}
+ typeset type=$(get_prop "type" $ds)
+
+ typeset -i ret=0
+ if [[ $type == "filesystem" ]]; then
+ typeset mntpnt=$(get_prop mountpoint $ds)
+ ((ret |= $?))
+
+ if ((ret == 0)) ; then
+ eval random_tree $mntpnt/${snap##$ds}
+ ((ret |= $?))
+ fi
+ fi
+
+ if ((ret == 0)) ; then
+ zfs snapshot $snap
+ ((ret |= $?))
+ fi
+
+ return $ret
+}
+
+#
+# Destroy the given snapshot and stuff
+#
+# $1 snapshot
+#
+function destroy_tree
+{
+ typeset -i ret=0
+ typeset snap
+ for snap in "$@" ; do
+ log_must_busy zfs destroy $snap
+
+ typeset ds=${snap%%@*}
+ typeset type=$(get_prop "type" $ds)
+ if [[ $type == "filesystem" ]]; then
+ typeset mntpnt=$(get_prop mountpoint $ds)
+ if [[ -n $mntpnt ]]; then
+ rm -rf $mntpnt/$snap
+ fi
+ fi
+ done
+
+ return 0
+}
+
+#
+# Get all the sub-datasets of give dataset with specific suffix
+#
+# $1 Given dataset
+# $2 Suffix
+#
+function getds_with_suffix
+{
+ typeset ds=$1
+ typeset suffix=$2
+
+ typeset list=$(zfs list -r -H -t all -o name $ds | grep "$suffix$")
+
+ echo $list
+}
+
+#
+# Output inherited properties which is edited for file system
+#
+function fs_inherit_prop
+{
+ typeset fs_prop
+ if is_global_zone ; then
+ fs_prop=$(zfs inherit 2>&1 | \
+ awk '$2=="YES" && $3=="YES" {print $1}')
+ if ! is_te_enabled ; then
+ fs_prop=$(echo $fs_prop | grep -v "mlslabel")
+ fi
+ else
+ fs_prop=$(zfs inherit 2>&1 | \
+ awk '$2=="YES" && $3=="YES" {print $1}'|
+ egrep -v "devices|mlslabel|sharenfs|sharesmb|zoned")
+ fi
+
+ echo $fs_prop
+}
+
+#
+# Output inherited properties for volume
+#
+function vol_inherit_prop
+{
+ echo "checksum readonly"
+}
+
+#
+# Get the destination dataset to compare
+#
+function get_dst_ds
+{
+ typeset srcfs=$1
+ typeset dstfs=$2
+
+ #
+ # If the srcfs is not pool
+ #
+ if ! zpool list $srcfs > /dev/null 2>&1 ; then
+ eval dstfs="$dstfs/${srcfs#*/}"
+ fi
+
+ echo $dstfs
+}
+
+#
+# Make test files
+#
+# $1 Number of files to create
+# $2 Maximum file size
+# $3 File ID offset
+# $4 File system to create the files on
+#
+function mk_files
+{
+ nfiles=$1
+ maxsize=$2
+ file_id_offset=$3
+ fs=$4
+ bs=512
+
+ for ((i=0; i<$nfiles; i=i+1)); do
+ file_name="/$fs/file-$maxsize-$((i+$file_id_offset))"
+ file_size=$((($RANDOM * $RANDOM % ($maxsize - 1)) + 1))
+
+ #
+ # Create an interesting mix of files which contain both
+ # data blocks and holes for more realistic test coverage.
+ # Half the files are created as sparse then partially filled,
+ # the other half is dense then a hole is punched in the file.
+ #
+ if [ $((RANDOM % 2)) -eq 0 ]; then
+ truncate -s $file_size $file_name || \
+ log_fail "Failed to create $file_name"
+ dd if=/dev/urandom of=$file_name \
+ bs=$bs count=$(($file_size / 2 / $bs)) \
+ seek=$(($RANDOM % (($file_size / 2 / $bs) + 1))) \
+ conv=notrunc >/dev/null 2>&1 || \
+ log_fail "Failed to create $file_name"
+ else
+ dd if=/dev/urandom of=$file_name \
+ bs=$file_size count=1 >/dev/null 2>&1 || \
+ log_fail "Failed to create $file_name"
+ dd if=/dev/zero of=$file_name \
+ bs=$bs count=$(($file_size / 2 / $bs)) \
+ seek=$(($RANDOM % (($file_size / 2 / $bs) + 1))) \
+ conv=notrunc >/dev/null 2>&1 || \
+ log_fail "Failed to create $file_name"
+ fi
+ done
+ echo Created $nfiles files of random sizes up to $maxsize bytes
+}
+
+#
+# Remove test files
+#
+# $1 Number of files to remove
+# $2 Maximum file size
+# $3 File ID offset
+# $4 File system to remove the files from
+#
+function rm_files
+{
+ nfiles=$1
+ maxsize=$2
+ file_id_offset=$3
+ fs=$4
+
+ for ((i=0; i<$nfiles; i=i+1)); do
+ rm -f /$fs/file-$maxsize-$((i+$file_id_offset))
+ done
+ echo Removed $nfiles files of random sizes up to $maxsize bytes
+}
+
+#
+# Simulate a random set of operations which could be reasonably expected
+# to occur on an average filesystem.
+#
+# $1 Number of files to modify
+# $2 Maximum file size
+# $3 File system to modify the file on
+# $4 Enabled xattrs (optional)
+#
+function churn_files
+{
+ nfiles=$1
+ maxsize=$2
+ fs=$3
+ xattrs=${4:-1}
+
+ #
+ # Remove roughly half of the files in order to make it more
+ # likely that a dnode will be reallocated.
+ #
+ for ((i=0; i<$nfiles; i=i+1)); do
+ file_name="/$fs/file-$i"
+
+ if [[ -e $file_name ]]; then
+ if [ $((RANDOM % 2)) -eq 0 ]; then
+ rm $file_name || \
+ log_fail "Failed to remove $file_name"
+ fi
+ fi
+ done
+
+ #
+ # Remount the filesystem to simulate normal usage. This resets
+ # the last allocated object id allowing for new objects to be
+ # reallocated in the locations of previously freed objects.
+ #
+ log_must zfs unmount $fs
+ log_must zfs mount $fs
+
+ for i in {0..$nfiles}; do
+ file_name="/$fs/file-$i"
+ file_size=$((($RANDOM * $RANDOM % ($maxsize - 1)) + 1))
+
+ #
+ # When the file exists modify it in one of five ways to
+ # simulate normal usage:
+ # - (20%) Remove and set and extended attribute on the file
+ # - (20%) Overwrite the existing file
+ # - (20%) Truncate the existing file to a random length
+ # - (20%) Truncate the existing file to zero length
+ # - (20%) Remove the file
+ #
+ # Otherwise create the missing file. 20% of the created
+ # files will be small and use embedded block pointers, the
+ # remainder with have random sizes up to the maximum size.
+ # Three extended attributes are attached to all of the files.
+ #
+ if [[ -e $file_name ]]; then
+ value=$((RANDOM % 5))
+ if [ $value -eq 0 -a $xattrs -ne 0 ]; then
+ attrname="testattr$((RANDOM % 3))"
+ attrlen="$(((RANDOM % 1000) + 1))"
+ attrvalue="$(random_string VALID_NAME_CHAR \
+ $attrlen)"
+ rm_xattr $attrname $file_name || \
+ log_fail "Failed to remove $attrname"
+ set_xattr $attrname "$attrvalue" $file_name || \
+ log_fail "Failed to set $attrname"
+ elif [ $value -eq 1 ]; then
+ dd if=/dev/urandom of=$file_name \
+ bs=$file_size count=1 >/dev/null 2>&1 || \
+ log_fail "Failed to overwrite $file_name"
+ elif [ $value -eq 2 ]; then
+ truncate -s $file_size $file_name || \
+ log_fail "Failed to truncate $file_name"
+ elif [ $value -eq 3 ]; then
+ truncate -s 0 $file_name || \
+ log_fail "Failed to truncate $file_name"
+ else
+ rm $file_name || \
+ log_fail "Failed to remove $file_name"
+ fi
+ else
+ if [ $((RANDOM % 5)) -eq 0 ]; then
+ file_size=$((($RANDOM % 64) + 1))
+ fi
+
+ dd if=/dev/urandom of=$file_name \
+ bs=$file_size count=1 >/dev/null 2>&1 || \
+ log_fail "Failed to create $file_name"
+
+ if [ $xattrs -ne 0 ]; then
+ for j in {0..2}; do
+ attrname="testattr$j"
+ attrlen="$(((RANDOM % 1000) + 1))"
+ attrvalue="$(random_string \
+ VALID_NAME_CHAR $attrlen)"
+ set_xattr $attrname \
+ "$attrvalue" $file_name || \
+ log_fail "Failed to set $attrname"
+ done
+ fi
+ fi
+ done
+
+ return 0
+}
+
+#
+# Mess up a send file's contents
+#
+# $1 The send file path
+#
+function mess_send_file
+{
+ file=$1
+
+ filesize=$(stat_size $file)
+
+ offset=$(($RANDOM * $RANDOM % $filesize))
+
+ # The random offset might truncate the send stream to be
+ # smaller than the DRR_BEGIN record. If this happens, then
+ # the receiving system won't have enough info to create the
+ # partial dataset at all. We use zstreamdump to check for
+ # this and retry in this case.
+ nr_begins=$(head -c $offset $file | zstreamdump | \
+ grep DRR_BEGIN | awk '{ print $5 }')
+ while [ "$nr_begins" -eq 0 ]; do
+ offset=$(($RANDOM * $RANDOM % $filesize))
+ nr_begins=$(head -c $offset $file | zstreamdump | \
+ grep DRR_BEGIN | awk '{ print $5 }')
+ done
+
+ if (($RANDOM % 7 <= 1)); then
+ #
+ # We corrupt 2 bytes to minimize the chance that we
+ # write the same value that's already there.
+ #
+ log_must eval "dd if=/dev/urandom of=$file conv=notrunc " \
+ "bs=1 count=2 seek=$offset >/dev/null 2>&1"
+ else
+ log_must truncate -s $offset $file
+ fi
+}
+
+#
+# Diff the send/receive filesystems
+#
+# $1 The sent filesystem
+# $2 The received filesystem
+#
+function file_check
+{
+ sendfs=$1
+ recvfs=$2
+
+ if [[ -d /$recvfs/.zfs/snapshot/a && -d \
+ /$sendfs/.zfs/snapshot/a ]]; then
+ diff -r /$recvfs/.zfs/snapshot/a /$sendfs/.zfs/snapshot/a
+ [[ $? -eq 0 ]] || log_fail "Differences found in snap a"
+ fi
+ if [[ -d /$recvfs/.zfs/snapshot/b && -d \
+ /$sendfs/.zfs/snapshot/b ]]; then
+ diff -r /$recvfs/.zfs/snapshot/b /$sendfs/.zfs/snapshot/b
+ [[ $? -eq 0 ]] || log_fail "Differences found in snap b"
+ fi
+}
+
+#
+# Resume test helper
+#
+# $1 The ZFS send command
+# $2 The filesystem where the streams are sent
+# $3 The receive filesystem
+#
+function resume_test
+{
+ sendcmd=$1
+ streamfs=$2
+ recvfs=$3
+
+ stream_num=1
+ log_must eval "$sendcmd >/$streamfs/$stream_num"
+
+ for ((i=0; i<2; i=i+1)); do
+ mess_send_file /$streamfs/$stream_num
+ log_mustnot zfs recv -suv $recvfs </$streamfs/$stream_num
+ stream_num=$((stream_num+1))
+
+ token=$(zfs get -Hp -o value receive_resume_token $recvfs)
+ log_must eval "zfs send -t $token >/$streamfs/$stream_num"
+ [[ -f /$streamfs/$stream_num ]] || \
+ log_fail "NO FILE /$streamfs/$stream_num"
+ done
+ log_must zfs recv -suv $recvfs </$streamfs/$stream_num
+}
+
+function get_resume_token
+{
+ sendcmd=$1
+ streamfs=$2
+ recvfs=$3
+
+ log_must eval "$sendcmd > /$streamfs/1"
+ mess_send_file /$streamfs/1
+ log_mustnot zfs recv -suv $recvfs < /$streamfs/1 2>&1
+ token=$(zfs get -Hp -o value receive_resume_token $recvfs)
+ echo "$token" > /$streamfs/resume_token
+
+ return 0
+}
+
+#
+# Setup filesystems for the resumable send/receive tests
+#
+# $1 The "send" filesystem
+# $2 The "recv" filesystem
+#
+function test_fs_setup
+{
+ typeset sendfs=$1
+ typeset recvfs=$2
+ typeset streamfs=$3
+ typeset sendpool=${sendfs%%/*}
+ typeset recvpool=${recvfs%%/*}
+
+ datasetexists $sendfs && log_must_busy zfs destroy -r $sendpool
+ datasetexists $recvfs && log_must_busy zfs destroy -r $recvpool
+ datasetexists $streamfs && log_must_busy zfs destroy -r $streamfs
+
+ if datasetexists $sendfs || zfs create -o compress=lz4 $sendfs; then
+ mk_files 1000 256 0 $sendfs &
+ mk_files 1000 131072 0 $sendfs &
+ mk_files 100 1048576 0 $sendfs &
+ mk_files 10 10485760 0 $sendfs &
+ mk_files 1 104857600 0 $sendfs &
+ log_must wait
+ log_must zfs snapshot $sendfs@a
+
+ rm_files 200 256 0 $sendfs &
+ rm_files 200 131072 0 $sendfs &
+ rm_files 20 1048576 0 $sendfs &
+ rm_files 2 10485760 0 $sendfs &
+ log_must wait
+
+ mk_files 400 256 0 $sendfs &
+ mk_files 400 131072 0 $sendfs &
+ mk_files 40 1048576 0 $sendfs &
+ mk_files 4 10485760 0 $sendfs &
+ log_must wait
+
+ log_must zfs snapshot $sendfs@b
+ log_must eval "zfs send -v $sendfs@a >/$sendpool/initial.zsend"
+ log_must eval "zfs send -v -i @a $sendfs@b " \
+ ">/$sendpool/incremental.zsend"
+ fi
+
+ log_must zfs create -o compress=lz4 $streamfs
+}
+
+#
+# Check to see if the specified features are set in a send stream.
+# The values for these features are found in include/sys/zfs_ioctl.h
+#
+# $1 The stream file
+# $2-$n The flags expected in the stream
+#
+function stream_has_features
+{
+ typeset file=$1
+ shift
+
+ [[ -f $file ]] || log_fail "Couldn't find file: $file"
+ typeset flags=$(cat $file | zstreamdump | \
+ awk '/features =/ {features = $3} END {print features}')
+ typeset -A feature
+ feature[dedup]="1"
+ feature[dedupprops]="2"
+ feature[sa_spill]="4"
+ feature[embed_data]="10000"
+ feature[lz4]="20000"
+ feature[mooch_byteswap]="40000"
+ feature[large_blocks]="80000"
+ feature[resuming]="100000"
+ feature[redacted]="200000"
+ feature[compressed]="400000"
+
+ typeset flag known derived=0
+ for flag in "$@"; do
+ known=${feature[$flag]}
+ [[ -z $known ]] && log_fail "Unknown feature: $flag"
+
+ derived=$(printf "%x" $((0x${flags} & 0x${feature[$flag]})))
+ [[ $derived = $known ]] || return 1
+ done
+
+ return 0
+}
+
+#
+# Given a send stream, verify that the size of the stream matches what's
+# expected based on the source or target dataset. If the stream is an
+# incremental stream, subtract the size of the source snapshot before
+# comparing. This function does not currently handle incremental streams
+# that remove data.
+#
+# $1 The zstreamdump output file
+# $2 The dataset to compare against
+# This can be a source of a send or recv target (fs, not snapshot)
+# $3 The percentage below which verification is deemed a failure
+# $4 The source snapshot of an incremental send
+#
+
+function verify_stream_size
+{
+ typeset stream=$1
+ typeset ds=$2
+ typeset percent=${3:-90}
+ typeset inc_src=$4
+
+ [[ -f $stream ]] || log_fail "No such file: $stream"
+ datasetexists $ds || log_fail "No such dataset: $ds"
+
+ typeset stream_size=$(cat $stream | zstreamdump | sed -n \
+ 's/ Total payload size = \(.*\) (0x.*)/\1/p')
+
+ typeset inc_size=0
+ if [[ -n $inc_src ]]; then
+ inc_size=$(get_prop lrefer $inc_src)
+ if stream_has_features $stream compressed; then
+ inc_size=$(get_prop refer $inc_src)
+ fi
+ fi
+
+ if stream_has_features $stream compressed; then
+ ds_size=$(get_prop refer $ds)
+ else
+ ds_size=$(get_prop lrefer $ds)
+ fi
+ ds_size=$((ds_size - inc_size))
+
+ within_percent $stream_size $ds_size $percent || log_fail \
+ "$stream_size $ds_size differed by too much"
+}
+
+# Cleanup function for tests involving resumable send
+function resume_cleanup
+{
+ typeset sendfs=$1
+ typeset streamfs=$2
+ typeset sendpool=${sendfs%%/*}
+
+ datasetexists $sendfs && log_must_busy zfs destroy -r $sendfs
+ datasetexists $streamfs && log_must_busy zfs destroy -r $streamfs
+ cleanup_pool $POOL2
+ rm -f /$sendpool/initial.zsend /$sendpool/incremental.zsend
+}
+
+# Randomly set the property to one of the enumerated values.
+function rand_set_prop
+{
+ typeset dtst=$1
+ typeset prop=$2
+ shift 2
+ typeset value=$(random_get $@)
+
+ log_must eval "zfs set $prop='$value' $dtst"
+}
+
+# Generate a recursive checksum of a filesystem which includes the file
+# contents and any associated extended attributes.
+function recursive_cksum
+{
+ case "$(uname)" in
+ FreeBSD)
+ find $1 -type f -exec sh -c 'sha256 -q {}; lsextattr -q \
+ system {} | sha256 -q; lsextattr -q user {} | sha256 -q' \
+ \; | sort | sha256 -q
+ ;;
+ *)
+ find $1 -type f -exec sh -c 'sha256sum {}; getfattr \
+ --absolute-names --only-values -d {} | sha256sum' \; | \
+ sort -k 2 | awk '{ print $1 }' | sha256sum | \
+ awk '{ print $1 }'
+ ;;
+ esac
+}
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_001_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_001_pos.ksh
new file mode 100755
index 000000000000..3864d8a7d1bd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_001_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# zfs send -R send replication stream up to the named snap.
+#
+# STRATEGY:
+# 1. Back up all the data from POOL/FS
+# 2. Verify all the datasets and data can be recovered in POOL2
+# 3. Back up all the data from root filesystem POOL2
+# 4. Verify all the data can be recovered, too
+#
+
+verify_runnable "both"
+
+log_assert "zfs send -R send replication stream up to the named snap."
+log_onexit cleanup_pool $POOL2
+
+#
+# Verify the entire pool and sub-ds can be backup and restored.
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+
+dstds=$(get_dst_ds $POOL $POOL2)
+log_must cmp_ds_subs $POOL $dstds
+log_must cmp_ds_cont $POOL $dstds
+
+# Cleanup POOL2
+log_must cleanup_pool $POOL2
+
+#
+# Verify all the filesystem and sub-fs can be backup and restored.
+#
+log_must eval "zfs send -R $POOL/$FS@final > $BACKDIR/fs-final-R"
+log_must eval "zfs receive -d $POOL2 < $BACKDIR/fs-final-R"
+
+dstds=$(get_dst_ds $POOL/$FS $POOL2)
+log_must cmp_ds_subs $POOL/$FS $dstds
+log_must cmp_ds_cont $POOL/$FS $dstds
+
+log_pass "zfs send -R send replication stream up to the named snap."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_002_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_002_pos.ksh
new file mode 100755
index 000000000000..f2c1e03937e2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# zfs send -I sends all incrementals from fs@init to fs@final.
+#
+# STRATEGY:
+# 1. Create several snapshots in pool2
+# 2. Send -I @snapA @final
+# 3. Destroy all the snapshot except @snapA
+# 4. Make sure all the snapshots and content are recovered
+#
+
+verify_runnable "both"
+
+log_assert "zfs send -I sends all incrementals from fs@init to fs@final."
+log_onexit cleanup_pool $POOL2
+
+#
+# Duplicate POOL2
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-R"
+
+if is_global_zone ; then
+ #
+ # Verify send -I will backup all the incrementals in pool
+ #
+ log_must eval "zfs send -I $POOL2@init $POOL2@final > " \
+ "$BACKDIR/pool-init-final-I"
+ log_must destroy_tree $POOL2@final $POOL2@snapC $POOL2@snapA
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-init-final-I"
+ log_must cmp_ds_subs $POOL $POOL2
+ log_must cmp_ds_cont $POOL $POOL2
+fi
+
+dstds=$(get_dst_ds $POOL $POOL2)
+
+#
+# Verify send -I will backup all the incrementals in filesystem
+#
+log_must eval "zfs send -I @init $dstds/$FS@final > $BACKDIR/fs-init-final-I"
+log_must destroy_tree $dstds/$FS@final $dstds/$FS@snapC $dstds/$FS@snapB
+log_must eval "zfs receive -d -F $dstds < $BACKDIR/fs-init-final-I"
+log_must cmp_ds_subs $POOL $dstds
+log_must cmp_ds_cont $POOL $dstds
+
+if is_global_zone ; then
+ #
+ # Verify send -I will backup all the incrementals in volume
+ #
+ dataset=$POOL2/$FS/vol
+ log_must eval "zfs send -I @vsnap $dataset@final > " \
+ "$BACKDIR/vol-vsnap-final-I"
+ log_must destroy_tree $dataset@final $dataset@snapC \
+ $dataset@snapB $dataset@init
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/vol-vsnap-final-I"
+ log_must cmp_ds_subs $POOL $POOL2
+ log_must cmp_ds_cont $POOL $POOL2
+fi
+
+log_pass "zfs send -I sends all incrementals from fs@init to fs@final."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_003_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_003_pos.ksh
new file mode 100755
index 000000000000..2ace6737b14e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# zfs send -I dataset@init to clone@snap can create a clone
+#
+# STRATEGY:
+# 1. Setup test model
+# 2. send -I pool@init to clone@snap
+# 3. Verify the clone and snapshot can be recovered via receive
+# 4. Verify the similar operating in filesystem and volume
+#
+
+verify_runnable "both"
+
+log_assert "zfs send -I send all incrementals from dataset@init to clone@snap"
+log_onexit cleanup_pool $POOL2
+
+#
+# Duplicate POOL2
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-R"
+
+if is_global_zone ; then
+ #
+ # Verify send -I backup all incrementals from pool
+ #
+ log_must eval "zfs send -I $POOL2@psnap $POOL2/pclone@final > " \
+ "$BACKDIR/pool-clone-I"
+ log_must_busy zfs destroy -rf $POOL2/pclone
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-clone-I"
+ log_must cmp_ds_subs $POOL $POOL2
+ log_must cmp_ds_cont $POOL $POOL2
+fi
+
+dstds=$(get_dst_ds $POOL $POOL2)
+
+#
+# Verify send -I backup all incrementals from filesystem
+#
+ds=$dstds/$FS/fs1
+log_must eval "zfs send -I $ds/fs2@fsnap $ds/fclone@final > " \
+ "$BACKDIR/fs-clone-I"
+log_must_busy zfs destroy -rf $ds/fclone
+log_must eval "zfs receive -F $ds/fclone < $BACKDIR/fs-clone-I"
+
+log_must cmp_ds_subs $POOL $dstds
+log_must cmp_ds_cont $POOL $dstds
+
+if is_global_zone ; then
+ #
+ # Verify send -I backup all incrementals from volume
+ #
+ ds=$POOL2/$FS
+ log_must eval "zfs send -I $ds/vol@vsnap $ds/vclone@final > " \
+ "$BACKDIR/vol-clone-I"
+ log_must_busy zfs destroy -rf $ds/vclone
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/vol-clone-I"
+ log_must cmp_ds_subs $POOL $POOL2
+ log_must cmp_ds_cont $POOL $POOL2
+fi
+
+log_pass "zfs send -I send all incrementals from dataset@init to clone@snap"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_004_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_004_pos.ksh
new file mode 100755
index 000000000000..c0b36b2329e7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_004_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# zfs send -R -i send incremental from fs@init to fs@final.
+#
+# STRATEGY:
+# 1. Create a set of snapshots and fill with data.
+# 2. Create sub filesystems.
+# 3. Create final snapshot
+# 4. Verify zfs send -R -i will backup all the datasets which has
+# snapshot suffix @final
+#
+
+verify_runnable "both"
+
+log_assert "zfs send -R -i send incremental from fs@init to fs@final."
+log_onexit cleanup_pool $POOL2
+
+#
+# Duplicate POOL2 for testing
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+
+if is_global_zone ; then
+ #
+ # Testing send -R -i backup from pool
+ #
+ srclist=$(getds_with_suffix $POOL2 @final)
+ interlist="$srclist $(getds_with_suffix $POOL2 @snapC)"
+ interlist="$interlist $(getds_with_suffix $POOL2 @snapB)"
+ interlist="$interlist $(getds_with_suffix $POOL2 @snapA)"
+
+ log_must eval "zfs send -R -i @init $POOL2@final > " \
+ "$BACKDIR/pool-init-final-iR"
+ log_must destroy_tree $interlist
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-init-final-iR"
+
+ # Get current datasets with suffix @final
+ dstlist=$(getds_with_suffix $POOL2 @final)
+ if [[ $srclist != $dstlist ]]; then
+ log_fail "Unexpected: srclist($srclist) != dstlist($dstlist)"
+ fi
+ log_must cmp_ds_cont $POOL $POOL2
+fi
+
+dstds=$(get_dst_ds $POOL $POOL2)
+#
+# Testing send -R -i backup from filesystem
+#
+log_must eval "zfs send -R -i @init $dstds/$FS@final > " \
+ "$BACKDIR/fs-init-final-iR"
+
+srclist=$(getds_with_suffix $dstds/$FS @final)
+interlist="$srclist $(getds_with_suffix $dstds/$FS @snapC)"
+interlist="$interlist $(getds_with_suffix $dstds/$FS @snapB)"
+interlist="$interlist $(getds_with_suffix $dstds/$FS @snapA)"
+log_must destroy_tree $interlist
+if is_global_zone ; then
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/fs-init-final-iR"
+else
+ zfs receive -F -d $dstds/$FS < $BACKDIR/fs-init-final-iR
+fi
+
+dstlist=$(getds_with_suffix $dstds/$FS @final)
+if [[ $srclist != $dstlist ]]; then
+ log_fail "Unexpected: srclist($srclist) != dstlist($dstlist)"
+fi
+log_must cmp_ds_cont $POOL $POOL2
+
+if is_global_zone ; then
+ #
+ # Testing send -R -i backup from volume
+ #
+ srclist=$(getds_with_suffix $POOL2/$FS/vol @final)
+ log_must eval "zfs send -R -i @init $POOL2/$FS/vol@final > " \
+ "$BACKDIR/vol-init-final-iR"
+ log_must destroy_tree $srclist
+ log_must eval "zfs receive -d $POOL2 < $BACKDIR/vol-init-final-iR"
+
+ dstlist=$(getds_with_suffix $POOL2/$FS/vol @final)
+ if [[ $srclist != $dstlist ]]; then
+ log_fail "Unexpected: srclist($srclist) != dstlist($dstlist)"
+ fi
+ log_must cmp_ds_cont $POOL $POOL2
+fi
+
+log_pass "zfs send -R -i send incremental from fs@init to fs@final."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_005_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_005_pos.ksh
new file mode 100755
index 000000000000..4d156690e38a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_005_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# zfs send -R -I send all the incremental between fs@init with fs@final
+#
+# STRATEGY:
+# 1. Setup test model
+# 2. Send -R -I @init @final on pool
+# 3. Destroy all the snapshots which is later than @init
+# 4. Verify receive can restore all the snapshots and data
+# 5. Do the same test on filesystem and volume
+#
+
+verify_runnable "both"
+
+log_assert "zfs send -R -I send all the incremental between @init with @final"
+log_onexit cleanup_pool $POOL2
+
+#
+# Duplicate POOL2 for testing
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+
+if is_global_zone ; then
+ #
+ # Testing send -R -I from pool
+ #
+ log_must eval "zfs send -R -I @init $POOL2@final > " \
+ "$BACKDIR/pool-init-final-IR"
+ list=$(getds_with_suffix $POOL2 @snapA)
+ list="$list $(getds_with_suffix $POOL2 @snapB)"
+ list="$list $(getds_with_suffix $POOL2 @snapC)"
+ list="$list $(getds_with_suffix $POOL2 @final)"
+ log_must destroy_tree $list
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-init-final-IR"
+ log_must cmp_ds_cont $POOL $POOL2
+fi
+
+dstds=$(get_dst_ds $POOL $POOL2)
+#
+# Testing send -R -I from filesystem
+#
+log_must eval "zfs send -R -I @init $dstds/$FS@final > " \
+ "$BACKDIR/fs-init-final-IR"
+list=$(getds_with_suffix $dstds/$FS @snapA)
+list="$list $(getds_with_suffix $dstds/$FS @snapB)"
+list="$list $(getds_with_suffix $dstds/$FS @snapC)"
+list="$list $(getds_with_suffix $dstds/$FS @final)"
+log_must destroy_tree $list
+if is_global_zone ; then
+ log_must eval "zfs receive -d -F $dstds < $BACKDIR/fs-init-final-IR"
+else
+ zfs receive -d -F $dstds < $BACKDIR/fs-init-final-IR
+fi
+log_must cmp_ds_subs $POOL $dstds
+log_must cmp_ds_cont $POOL $dstds
+
+if is_global_zone ; then
+ #
+ # Testing send -I -R for volume
+ #
+ vol=$POOL2/$FS/vol
+ log_must eval "zfs send -R -I @init $vol@final > " \
+ "$BACKDIR/vol-init-final-IR"
+ log_must destroy_tree $vol@snapB $vol@snapC $vol@final
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/vol-init-final-IR"
+ log_must cmp_ds_subs $POOL $POOL2
+ log_must cmp_ds_cont $POOL $POOL2
+fi
+
+log_pass "zfs send -R -I send all the incremental between @init with @final"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_006_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_006_pos.ksh
new file mode 100755
index 000000000000..8c598f4ec29c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_006_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Rename snapshot name will not change the dependent order.
+#
+# STRATEGY:
+# 1. Set up a set of datasets.
+# 2. Rename part of snapshots.
+# 3. Send -R all the POOL
+# 4. Verify snapshot name will not change the dependent order.
+#
+
+verify_runnable "both"
+
+# Source Target
+#
+set -A snaps "$POOL@init" "$POOL@snap0" \
+ "$POOL@snapA" "$POOL@snap1" \
+ "$POOL@snapC" "$POOL@snap2" \
+ "$POOL@final" "$POOL@init"
+
+function cleanup
+{
+ log_must cleanup_pool $POOL
+ log_must cleanup_pool $POOL2
+
+ log_must setup_test_model $POOL
+}
+
+log_assert "Rename snapshot name will not change the dependent order."
+log_onexit cleanup
+
+typeset -i i=0
+while ((i < ${#snaps[@]})); do
+ log_must zfs rename -r ${snaps[$i]} ${snaps[((i+1))]}
+
+ ((i += 2))
+done
+
+#
+# Duplicate POOL2 for testing
+#
+log_must eval "zfs send -R $POOL@init > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+
+dstds=$(get_dst_ds $POOL $POOL2)
+log_must cmp_ds_subs $POOL $dstds
+log_must cmp_ds_cont $POOL $dstds
+
+log_pass "Rename snapshot name will not change the dependent order."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_007_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_007_pos.ksh
new file mode 100755
index 000000000000..29e9f1859579
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_007_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/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Rename parent filesystem name will not change the dependent order.
+#
+# STRATEGY:
+# 1. Separately rename pool clone, filesystem and volume name.
+# 2. Send -R all the POOL
+# 3. Verify renamed dataset will not change the snapshot dependent order.
+#
+
+verify_runnable "both"
+
+set -A dtst \
+ "$POOL/pclone" "$POOL/$FS/pclone" \
+ "$POOL/$FS/fs1/fs2" "$POOL/fs2"
+if is_global_zone ; then
+ typeset -i n=${#dtst[@]}
+ dtst[((n))]="$POOL/vol"; dtst[((n+1))]="$POOL/$FS/fs1/vol"
+fi
+
+function cleanup
+{
+ log_must cleanup_pool $POOL
+ log_must cleanup_pool $POOL2
+
+ log_must setup_test_model $POOL
+}
+
+log_assert "Rename parent filesystem name will not change the dependent order."
+log_onexit cleanup
+
+typeset -i i=0
+while ((i < ${#dtst[@]})); do
+ log_must zfs rename ${dtst[$i]} ${dtst[((i+1))]}
+
+ ((i += 2))
+done
+
+#
+# Verify zfs send -R should succeed
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+dstds=$(get_dst_ds $POOL $POOL2)
+log_must cmp_ds_subs $POOL $dstds
+
+#
+# Verify zfs send -R -I should succeed
+#
+log_must eval "zfs send -R -I @init $dstds@final > " \
+ "$BACKDIR/pool-init-final-IR"
+list=$(getds_with_suffix $dstds @snapA)
+list="$list $(getds_with_suffix $dstds @snapB)"
+list="$list $(getds_with_suffix $dstds @snapC)"
+list="$list $(getds_with_suffix $dstds @final)"
+log_must destroy_tree $list
+if is_global_zone ; then
+ log_must eval "zfs receive -d -F $dstds < $BACKDIR/pool-init-final-IR"
+else
+ zfs receive -d -F $dstds < $BACKDIR/pool-init-final-IR
+fi
+log_must cmp_ds_subs $POOL $dstds
+
+log_pass "Rename parent filesystem name will not change the dependent order."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_008_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_008_pos.ksh
new file mode 100755
index 000000000000..531478760457
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_008_pos.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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Changes made by 'zfs promote' can be properly received.
+#
+# STRATEGY:
+# 1. Separately promote pool clone, filesystem clone and volume clone.
+# 2. Recursively backup all the POOL and restore in POOL2
+# 3. Verify all the datasets and properties were properly received.
+#
+
+verify_runnable "both"
+
+# See issue: https://github.com/zfsonlinux/zfs/issues/6066
+log_unsupported "Occasionally hangs"
+
+# Origin Clone
+#
+set -A dtst "$POOL" "$POOL/pclone" \
+ "$POOL/$FS/fs1/fs2" "$POOL/$FS/fs1/fclone"
+if is_global_zone ; then
+ typeset -i n=${#dtst[@]}
+ dtst[((n))]="$POOL/$FS/vol"; dtst[((n+1))]="$POOL/$FS/vclone"
+fi
+
+function cleanup
+{
+ typeset origin
+ typeset -i i=0
+ while ((i < ${#dtst[@]})); do
+ origin=$(get_prop origin ${dtst[$i]})
+
+ if [[ $origin != "-" ]]; then
+ log_must zfs promote ${dtst[$i]}
+ fi
+
+ ((i += 2))
+ done
+
+ origin=$(get_prop origin $POOL2)
+ if [[ $origin != "-" ]]; then
+ log_must zfs promote $POOL2
+ fi
+ log_must cleanup_pool $POOL2
+}
+
+log_assert "Changes made by 'zfs promote' can be properly received."
+log_onexit cleanup
+
+typeset -i i=0
+while ((i < ${#dtst[@]})); do
+ log_must zfs promote ${dtst[((i+1))]}
+
+ ((i += 2))
+done
+
+#
+# Verify zfs send -R should succeed
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+
+dstds=$(get_dst_ds $POOL $POOL2)
+#
+# Define all the POOL/POOL2 datasets pair
+#
+set -A pair "$POOL" "$dstds" \
+ "$POOL/$FS" "$dstds/$FS" \
+ "$POOL/$FS/fs1" "$dstds/$FS/fs1" \
+ "$POOL/$FS/fs1/fs2" "$dstds/$FS/fs1/fs2" \
+ "$POOL/pclone" "$dstds/pclone" \
+ "$POOL/$FS/fs1/fclone" "$dstds/$FS/fs1/fclone"
+
+if is_global_zone ; then
+ typeset -i n=${#pair[@]}
+ pair[((n))]="$POOL/vol"; pair[((n+1))]="$dstds/vol"
+ pair[((n+2))]="$POOL/$FS/vol" pair[((n+3))]="$dstds/$FS/vol"
+fi
+
+#
+# Verify all the sub-datasets can be properly received.
+#
+log_must cmp_ds_subs $POOL $dstds
+typeset -i i=0
+while ((i < ${#pair[@]})); do
+ log_must cmp_ds_cont ${pair[$i]} ${pair[((i+1))]}
+ log_must cmp_ds_prop ${pair[$i]} ${pair[((i+1))]}
+
+ ((i += 2))
+done
+
+# Verify the original filesystem can be promoted
+log_must zfs promote $dstds
+if is_global_zone ; then
+ log_must zfs promote $dstds/$FS/vol
+fi
+log_must zfs promote $dstds/$FS/fs1/fs2
+
+log_pass "Changes made by 'zfs promote' can be properly received."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_009_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_009_pos.ksh
new file mode 100755
index 000000000000..7d858d92d511
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_009_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# zfs receive can handle out of space correctly.
+#
+# STRATEGY:
+# 1. Create two pools, one is big and another is small.
+# 2. Fill the big pool with data.
+# 3. Take snapshot and backup the whole pool.
+# 4. Receive this stream in small pool.
+# 5. Verify zfs receive can handle the out of space error correctly.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if datasetexists bpool ; then
+ log_must_busy zpool destroy -f bpool
+ fi
+ if datasetexists spool ; then
+ log_must_busy zpool destroy -f spool
+ fi
+}
+
+log_assert "Verify zfs receive can handle out of space correctly."
+log_onexit cleanup
+
+log_must mkfile $MINVDEVSIZE $TESTDIR/bfile
+log_must mkfile $SPA_MINDEVSIZE $TESTDIR/sfile
+log_must zpool create bpool $TESTDIR/bfile
+log_must zpool create spool $TESTDIR/sfile
+
+#
+# Test out of space on sub-filesystem
+#
+log_must zfs create bpool/fs
+log_must mkfile 30M /bpool/fs/file
+
+log_must zfs snapshot bpool/fs@snap
+log_must eval "zfs send -R bpool/fs@snap > $BACKDIR/fs-R"
+log_mustnot eval "zfs receive -d -F spool < $BACKDIR/fs-R"
+
+log_must datasetnonexists spool/fs
+log_must ismounted spool
+
+#
+# Test out of space on top filesystem
+#
+log_must mv /bpool/fs/file /bpool
+log_must_busy zfs destroy -rf bpool/fs
+
+log_must zfs snapshot bpool@snap
+log_must eval "zfs send -R bpool@snap > $BACKDIR/bpool-R"
+log_mustnot eval "zfs receive -d -F spool < $BACKDIR/bpool-R"
+
+log_must datasetnonexists spool/fs
+log_must ismounted spool
+
+log_pass "zfs receive can handle out of space correctly."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_010_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_010_pos.ksh
new file mode 100755
index 000000000000..e76f5c5c8620
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# ZFS can handle stream with multiple identical (same GUID) snapshots
+#
+# STRATEGY:
+# 1. Recursively backup snapshot
+# 2. Restore it to the given filesystem
+# 3. Resend the snapshot again
+# 4. Verify this stream can be restore to this filesystem again
+#
+
+verify_runnable "both"
+
+log_assert "ZFS can handle stream with multiple identical (same GUID) snapshots"
+log_onexit cleanup_pool $POOL2
+
+log_must zfs create $POOL2/$FS
+log_must zfs snapshot $POOL2/$FS@snap
+
+#
+# First round restore the stream
+#
+log_must eval "zfs send -R $POOL2/$FS@snap > $BACKDIR/fs-R"
+log_must eval "zfs receive -d -F $POOL2/$FS < $BACKDIR/fs-R"
+
+#
+# In order to avoid 'zfs send -R' failed, create snapshot for
+# all the sub-systems
+#
+list=$(zfs list -r -H -o name -t filesystem $POOL2/$FS)
+for item in $list ; do
+ if datasetnonexists $item@snap ; then
+ log_must zfs snapshot $item@snap
+ fi
+done
+
+#
+# Second round restore the stream
+#
+log_must eval "zfs send -R $POOL2/$FS@snap > $BACKDIR/fs-R"
+dstds=$(get_dst_ds $POOL2/$FS $POOL2/$FS)
+log_must eval "zfs receive -d -F $dstds < $BACKDIR/fs-R"
+
+log_pass "ZFS can handle stream with multiple identical (same GUID) snapshots"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_011_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_011_pos.ksh
new file mode 100755
index 000000000000..68f0e13927dc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_011_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Changes made by 'zfs inherit' can be properly received.
+#
+# STRATEGY:
+# 1. Inherit property for filesystem and volume
+# 2. Send and restore them in the target pool
+# 3. Verify all the datasets can be properly backup and receive
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must cleanup_pool $POOL
+ log_must cleanup_pool $POOL2
+
+ log_must setup_test_model $POOL
+}
+
+log_assert "Verify changes made by 'zfs inherit' can be properly received."
+log_onexit cleanup
+
+#
+# Setting all the $FS properties as local value,
+#
+for prop in $(fs_inherit_prop); do
+ value=$(get_prop $prop $POOL/$FS)
+ log_must zfs set $prop=$value $POOL/$FS
+done
+
+#
+# Inherit properties in sub-datasets
+#
+for ds in "$POOL/$FS/fs1" "$POOL/$FS/fs1/fs2" "$POOL/$FS/fs1/fclone" ; do
+ for prop in $(fs_inherit_prop) ; do
+ zfs inherit $prop $ds
+ if (($? !=0 )); then
+ log_fail "zfs inherit $prop $ds"
+ fi
+ done
+done
+if is_global_zone ; then
+ for prop in $(vol_inherit_prop) ; do
+ zfs inherit $prop $POOL/$FS/vol
+ if (($? !=0 )); then
+ log_fail "zfs inherit $prop $POOL/$FS/vol"
+ fi
+ done
+fi
+
+#
+# Verify datasets can be backup and restore correctly
+# Unmount $POOL/$FS to avoid two fs mount in the same mountpoint
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-R"
+log_must zfs unmount -f $POOL/$FS
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-R"
+
+dstds=$(get_dst_ds $POOL $POOL2)
+#
+# Define all the POOL/POOL2 datasets pair
+#
+set -A pair "$POOL" "$dstds" \
+ "$POOL/$FS" "$dstds/$FS" \
+ "$POOL/$FS/fs1" "$dstds/$FS/fs1" \
+ "$POOL/$FS/fs1/fs2" "$dstds/$FS/fs1/fs2" \
+ "$POOL/pclone" "$dstds/pclone" \
+ "$POOL/$FS/fs1/fclone" "$dstds/$FS/fs1/fclone"
+
+if is_global_zone ; then
+ typeset -i n=${#pair[@]}
+ pair[((n))]="$POOL/vol"; pair[((n+1))]="$dstds/vol"
+ pair[((n+2))]="$POOL/$FS/vol" pair[((n+3))]="$dstds/$FS/vol"
+fi
+
+#
+# Verify all the sub-datasets can be properly received.
+#
+log_must cmp_ds_subs $POOL $dstds
+typeset -i i=0
+while ((i < ${#pair[@]})); do
+ log_must cmp_ds_prop ${pair[$i]} ${pair[((i+1))]}
+ ((i += 2))
+done
+
+log_pass "Changes made by 'zfs inherit' can be properly received."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh
new file mode 100755
index 000000000000..0441f7ff32be
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_012_pos.ksh
@@ -0,0 +1,186 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016, Delphix. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# zfs send -R will backup all the filesystem properties correctly.
+#
+# STRATEGY:
+# 1. Setting properties for all the filesystem and volumes randomly
+# 2. Backup all the data from POOL by send -R
+# 3. Restore all the data in POOL2
+# 4. Verify all the properties in the two pools are the same
+#
+
+verify_runnable "global"
+
+function edited_prop
+{
+ typeset behaviour=$1
+ typeset ds=$2
+ typeset backfile=$TESTDIR/edited_prop_$ds
+
+ case $behaviour in
+ "get")
+ typeset props=$(zfs inherit 2>&1 | \
+ awk '$2=="YES" {print $1}' | \
+ egrep -v "^vol|\.\.\.$")
+ for item in $props ; do
+ if [[ $item == "mlslabel" ]] && \
+ ! is_te_enabled ; then
+ continue
+ fi
+ zfs get -H -o property,value $item $ds >> \
+ $backfile
+ if (($? != 0)); then
+ log_fail "zfs get -H -o property,value"\
+ "$item $ds > $backfile"
+ fi
+ done
+ ;;
+ "set")
+ if [[ ! -f $backfile ]] ; then
+ log_fail "$ds need backup properties firstly."
+ fi
+
+ typeset prop value
+ while read prop value ; do
+ eval zfs set $prop='$value' $ds
+ if (($? != 0)); then
+ log_fail "zfs set $prop=$value $ds"
+ fi
+ done < $backfile
+ ;;
+ *)
+ log_fail "Unrecognized behaviour: $behaviour"
+ esac
+}
+
+function cleanup
+{
+ log_must cleanup_pool $POOL
+ log_must cleanup_pool $POOL2
+
+ log_must edited_prop "set" $POOL
+ log_must edited_prop "set" $POOL2
+
+ typeset prop
+ for prop in $(fs_inherit_prop) ; do
+ log_must zfs inherit $prop $POOL
+ log_must zfs inherit $prop $POOL2
+ done
+
+ log_must setup_test_model $POOL
+
+ if [[ -d $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR/*
+ fi
+}
+
+log_assert "Verify zfs send -R will backup all the filesystem properties " \
+ "correctly."
+log_onexit cleanup
+
+log_must edited_prop "get" $POOL
+log_must edited_prop "get" $POOL2
+
+for fs in "$POOL" "$POOL/pclone" "$POOL/$FS" "$POOL/$FS/fs1" \
+ "$POOL/$FS/fs1/fs2" "$POOL/$FS/fs1/fclone" ; do
+ rand_set_prop $fs aclinherit "discard" "noallow" "secure" "passthrough"
+ rand_set_prop $fs checksum "on" "off" "fletcher2" "fletcher4" "sha256"
+ rand_set_prop $fs acltype "off" "noacl" "posixacl"
+ rand_set_prop $fs atime "on" "off"
+ rand_set_prop $fs checksum "on" "off" "fletcher2" "fletcher4" "sha256"
+ rand_set_prop $fs compression "${compress_prop_vals[@]}"
+ rand_set_prop $fs copies "1" "2" "3"
+ rand_set_prop $fs devices "on" "off"
+ rand_set_prop $fs exec "on" "off"
+ rand_set_prop $fs quota "512M" "1024M"
+ rand_set_prop $fs recordsize "512" "2K" "8K" "32K" "128K"
+ rand_set_prop $fs dnodesize "legacy" "auto" "1k" "2k" "4k" "8k" "16k"
+ rand_set_prop $fs setuid "on" "off"
+ rand_set_prop $fs snapdir "hidden" "visible"
+ if ! is_freebsd; then
+ rand_set_prop $fs xattr "on" "off"
+ fi
+ rand_set_prop $fs user:prop "aaa" "bbb" "23421" "()-+?"
+done
+
+for vol in "$POOL/vol" "$POOL/$FS/vol" ; do
+ rand_set_prop $vol checksum "on" "off" "fletcher2" "fletcher4" "sha256"
+ rand_set_prop $vol compression "${compress_prop_vals[@]}"
+ rand_set_prop $vol readonly "on" "off"
+ rand_set_prop $vol copies "1" "2" "3"
+ rand_set_prop $vol user:prop "aaa" "bbb" "23421" "()-+?"
+done
+
+
+# Verify inherited property can be received
+rand_set_prop $POOL redundant_metadata "all" "most"
+rand_set_prop $POOL sync "standard" "always" "disabled"
+
+#
+# Duplicate POOL2 for testing
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+
+#
+# Define all the POOL/POOL2 datasets pair
+#
+set -A pair "$POOL" "$POOL2" \
+ "$POOL/$FS" "$POOL2/$FS" \
+ "$POOL/$FS/fs1" "$POOL2/$FS/fs1" \
+ "$POOL/$FS/fs1/fs2" "$POOL2/$FS/fs1/fs2" \
+ "$POOL/pclone" "$POOL2/pclone" \
+ "$POOL/$FS/fs1/fclone" "$POOL2/$FS/fs1/fclone" \
+ "$POOL/vol" "$POOL2/vol" \
+ "$POOL/$FS/vol" "$POOL2/$FS/vol"
+
+typeset -i i=0
+while ((i < ${#pair[@]})); do
+ log_must cmp_ds_prop ${pair[$i]} ${pair[((i+1))]}
+
+ ((i += 2))
+done
+
+
+zpool upgrade -v | grep "Snapshot properties" > /dev/null 2>&1
+if (( $? == 0 )) ; then
+ i=0
+ while ((i < ${#pair[@]})); do
+ log_must cmp_ds_prop ${pair[$i]}@final ${pair[((i+1))]}@final
+ ((i += 2))
+ done
+fi
+
+log_pass "Verify zfs send -R will backup all the filesystem properties " \
+ "correctly."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_013_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_013_pos.ksh
new file mode 100755
index 000000000000..110e56144674
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_013_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# zfs receive -dF with incremental stream will destroy all the
+# dataset that not exist on the sender side.
+#
+# STRATEGY:
+# 1. Setup test model
+# 2. Send -R @final on pool
+# 3. Destroy some dataset within the @final, and create @destroy
+# 4. Send -R -I @final @destroy on pool
+# 5. Verify receive -dF will destroy all the dataset that not exist
+# on the sender side.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ cleanup_pool $POOL2
+ cleanup_pool $POOL
+ log_must setup_test_model $POOL
+}
+
+log_assert "zfs receive -dF will destroy all the dataset that not exist" \
+ "on the sender side"
+log_onexit cleanup
+
+cleanup
+
+#
+# Duplicate POOL2 for testing
+#
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -dF $POOL2 < $BACKDIR/pool-final-R"
+
+log_must_busy zfs destroy -Rf $POOL/$FS
+log_must_busy zfs destroy -Rf $POOL/pclone
+
+if is_global_zone ; then
+ log_must_busy zfs destroy -Rf $POOL/vol
+fi
+log_must zfs snapshot -r $POOL@destroy
+
+log_must eval "zfs send -R -I @final $POOL@destroy > " \
+ "$BACKDIR/pool-final-destroy-IR"
+log_must eval "zfs receive -dF $POOL2 < $BACKDIR/pool-final-destroy-IR"
+
+dstds=$(get_dst_ds $POOL $POOL2)
+log_must cmp_ds_subs $POOL $dstds
+log_must cmp_ds_cont $POOL $dstds
+
+log_pass "zfs receive -dF will destroy all the dataset that not exist" \
+ "on the sender side"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_014_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_014_pos.ksh
new file mode 100755
index 000000000000..47fc2f1bead4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_014_pos.ksh
@@ -0,0 +1,56 @@
+#!/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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify that a pool imported readonly can be sent and received.
+#
+# Strategy:
+# 1. Make the source pool readonly, and receive it into pool2.
+# 2. Reset pool2, and repeat the send from a non-root fs of the source pool.
+# 3. Make the source pool read-write again.
+#
+
+verify_runnable "both"
+
+log_assert "zfs send will work on filesystems and volumes in a read-only pool."
+log_onexit cleanup_pool $POOL2
+
+log_must zpool export $POOL
+log_must zpool import -o readonly=on $POOL
+log_must eval "zfs send -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+
+dstds=$(get_dst_ds $POOL $POOL2)
+log_must cmp_ds_subs $POOL $dstds
+log_must cmp_ds_cont $POOL $dstds
+
+log_must cleanup_pool $POOL2
+
+log_must eval "zfs send -R $POOL/$FS@final > $BACKDIR/fs-final-R"
+log_must eval "zfs receive -d $POOL2 < $BACKDIR/fs-final-R"
+log_must_busy zpool export $POOL
+log_must zpool import $POOL
+
+dstds=$(get_dst_ds $POOL/$FS $POOL2)
+log_must cmp_ds_subs $POOL/$FS $dstds
+log_must cmp_ds_cont $POOL/$FS $dstds
+
+log_pass "zfs send will work on filesystems and volumes in a read-only pool."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_016_neg.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_016_neg.ksh
new file mode 100755
index 000000000000..6dfb3423fdf9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_016_neg.ksh
@@ -0,0 +1,33 @@
+#!/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) 2014, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify that error conditions don't cause panics in zfs send
+#
+# Strategy:
+# 1. Perform a zfs incremental send from a bookmark that doesn't exist
+#
+
+verify_runnable "both"
+
+log_neg eval "zfs send -i \#bla $POOl/$FS@final > /dev/null"
+
+log_pass "Ensure that error conditions cause appropriate failures."
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh
new file mode 100755
index 000000000000..673d1d072be4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_019_pos.ksh
@@ -0,0 +1,54 @@
+#!/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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify resumability of a full and incremental ZFS send/receive in the
+# presence of a corrupted stream.
+#
+# Strategy:
+# 1. Start a full ZFS send, redirect output to a file
+# 2. Mess up the contents of the stream state file on disk
+# 3. Try ZFS receive, which should fail with a checksum mismatch error
+# 4. ZFS send to the stream state file again using the receive_resume_token
+# 5. ZFS receive and verify the receive completes successfully
+# 6. Repeat steps on an incremental ZFS send
+# 7. Repeat the entire procedure for a dataset at the pool root
+#
+
+verify_runnable "both"
+
+log_assert "Verify resumability of a full and incremental ZFS send/receive " \
+ "in the presence of a corrupted stream"
+log_onexit resume_cleanup $sendfs $streamfs
+
+sendfs=$POOL/sendfs
+recvfs=$POOL3/recvfs
+streamfs=$POOL2/stream
+
+for sendfs in $POOL2/sendfs $POOL3; do
+ test_fs_setup $sendfs $recvfs $streamfs
+ resume_test "zfs send -v $sendfs@a" $streamfs $recvfs
+ resume_test "zfs send -v -i @a $sendfs@b" $streamfs $recvfs
+ file_check $sendfs $recvfs
+done
+
+log_pass "Verify resumability of a full and incremental ZFS send/receive " \
+ "in the presence of a corrupted stream"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh
new file mode 100755
index 000000000000..b7ecf90916ba
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_020_pos.ksh
@@ -0,0 +1,50 @@
+#!/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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify resumability of a full ZFS send/receive with the -D (dedup) flag in
+# the presence of a corrupted stream.
+#
+# Strategy:
+# 1. Start a full ZFS send with the -D flag (dedup), redirect output to a file
+# 2. Mess up the contents of the stream state file on disk
+# 3. Try ZFS receive, which should fail with a checksum mismatch error
+# 4. ZFS send to the stream state file again using the receive_resume_token
+# 5. ZFS receive and verify the receive completes successfully
+#
+
+verify_runnable "both"
+
+log_assert "Verify resumability of full ZFS send/receive with the -D " \
+ "(dedup) flag"
+
+sendfs=$POOL/sendfs
+recvfs=$POOL2/recvfs
+streamfs=$POOL/stream
+
+log_onexit resume_cleanup $sendfs $streamfs
+
+test_fs_setup $sendfs $recvfs $streamfs
+resume_test "zfs send -D -v $sendfs@a" $streamfs $recvfs
+file_check $sendfs $recvfs
+
+log_pass "Verify resumability of full ZFS send/receive with the -D " \
+ "(dedup) flag"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh
new file mode 100755
index 000000000000..50f2b8890a5c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_021_pos.ksh
@@ -0,0 +1,53 @@
+#!/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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify resumability of a full and incremental ZFS send/receive with the
+# -e (embedded) flag in the presence of a corrupted stream.
+#
+# Strategy:
+# 1. Start a full ZFS send with the -e flag (embedded), redirect output to
+# a file
+# 2. Mess up the contents of the stream state file on disk
+# 3. Try ZFS receive, which should fail with a checksum mismatch error
+# 4. ZFS send to the stream state file again using the receive_resume_token
+# 5. ZFS receive and verify the receive completes successfully
+# 6. Repeat steps on an incremental ZFS send
+#
+
+verify_runnable "both"
+
+log_assert "Verify resumability of a full and incremental ZFS send/receive " \
+ "with the -e (embedded) flag"
+
+sendfs=$POOL/sendfs
+recvfs=$POOL2/recvfs
+streamfs=$POOL/stream
+
+log_onexit resume_cleanup $sendfs $streamfs
+
+test_fs_setup $sendfs $recvfs $streamfs
+resume_test "zfs send -v -e $sendfs@a" $streamfs $recvfs
+resume_test "zfs send -v -e -i @a $sendfs@b" $streamfs $recvfs
+file_check $sendfs $recvfs
+
+log_pass "Verify resumability of a full and incremental ZFS send/receive " \
+ "with the -e (embedded) flag"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh
new file mode 100755
index 000000000000..cb68b1c3b27d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_022_pos.ksh
@@ -0,0 +1,61 @@
+#!/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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify resumability of an incremental ZFS send/receive with ZFS bookmarks in
+# the presence of a corrupted stream.
+#
+# Strategy:
+# 1. Bookmark a ZFS snapshot
+# 2. Destroy the ZFS snapshot
+# 3. Destroy the filesystem for the receive
+# 4. Verify receive of the full send stream
+# 5. Start an incremental ZFS send of the ZFS bookmark, redirect output to a
+# file
+# 6. Mess up the contents of the stream state file on disk
+# 7. Try ZFS receive, which should fail with a checksum mismatch error
+# 8. ZFS send to the stream state file again using the receive_resume_token
+# 9. ZFS receive and verify the receive completes successfully
+#
+
+verify_runnable "both"
+
+log_assert "Verify resumability of an incremental ZFS send/receive with ZFS " \
+ "bookmarks"
+
+sendfs=$POOL/sendfs
+recvfs=$POOL2/recvfs
+streamfs=$POOL/stream
+
+log_onexit resume_cleanup $sendfs $streamfs
+
+test_fs_setup $sendfs $recvfs $streamfs
+log_must zfs bookmark $sendfs@a $sendfs#bm_a
+log_must_busy zfs destroy $sendfs@a
+log_must zfs receive -v $recvfs </$POOL/initial.zsend
+resume_test "zfs send -i \#bm_a $sendfs@b" $streamfs $recvfs
+log_must_busy zfs destroy -r -f $sendfs
+log_must zfs receive -v $sendfs </$POOL/initial.zsend
+log_must zfs receive -v $sendfs </$POOL/incremental.zsend
+file_check $sendfs $recvfs
+
+log_pass "Verify resumability of an incremental ZFS send/receive with ZFS " \
+ "bookmarks"
diff --git a/tests/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh b/tests/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh
new file mode 100755
index 000000000000..2d9fb01af10f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/rsend_024_pos.ksh
@@ -0,0 +1,53 @@
+#!/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) 2014, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify resumability of a full ZFS send/receive with the source filesystem
+# unmounted.
+#
+# Strategy:
+# 1. Destroy the filesystem for the receive
+# 2. Unmount the source filesystem
+# 3. Start a full ZFS send, redirect output to a file
+# 4. Mess up the contents of the stream state file on disk
+# 5. Try ZFS receive, which should fail with a checksum mismatch error
+# 6. ZFS send to the stream state file again using the receive_resume_token
+# 7. ZFS receive and verify the receive completes successfully
+#
+
+verify_runnable "both"
+
+log_assert "Verify resumability of a full ZFS send/receive with the source " \
+ "filesystem unmounted"
+
+sendfs=$POOL/sendfs
+recvfs=$POOL2/recvfs
+streamfs=$POOL/stream
+
+log_onexit resume_cleanup $sendfs $streamfs
+
+test_fs_setup $sendfs $recvfs $streamfs
+log_must zfs unmount -f $sendfs
+resume_test "zfs send $sendfs" $streamfs $recvfs
+file_check $sendfs $recvfs
+
+log_pass "Verify resumability of a full ZFS send/receive with the source " \
+ "filesystem unmounted"
diff --git a/tests/zfs-tests/tests/functional/rsend/send-L_toggle.ksh b/tests/zfs-tests/tests/functional/rsend/send-L_toggle.ksh
new file mode 100755
index 000000000000..483efcc60548
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-L_toggle.ksh
@@ -0,0 +1,65 @@
+#!/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/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify that send -L can be changed to on in an incremental.
+# Verify that send -L can not be turned off in an incremental.
+#
+
+function cleanup
+{
+ log_must_busy zfs destroy -r $TESTPOOL/fs
+ log_must_busy zfs destroy -r $TESTPOOL/recv
+}
+
+verify_runnable "both"
+
+log_assert "Verify toggling send -L works as expected"
+log_onexit cleanup
+
+log_must zfs create -o compression=on -o recordsize=1m $TESTPOOL/fs
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/fs/file bs=1024 count=1500
+
+log_must zfs snapshot $TESTPOOL/fs@snap
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/fs/file bs=1024 count=1500 conv=notrunc seek=2048
+
+log_must zfs snapshot $TESTPOOL/fs@snap2
+
+log_must zfs create $TESTPOOL/recv
+
+log_must zfs send -c $TESTPOOL/fs@snap | zfs recv $TESTPOOL/recv/noL-noL
+log_must zfs send -c -i @snap $TESTPOOL/fs@snap2| zfs recv $TESTPOOL/recv/noL-noL
+log_must diff /$TESTPOOL/fs/file /$TESTPOOL/recv/noL-noL/file
+
+log_must zfs send -c -L $TESTPOOL/fs@snap | zfs recv $TESTPOOL/recv/L-L
+log_must zfs send -c -L -i @snap $TESTPOOL/fs@snap2 | zfs recv $TESTPOOL/recv/L-L
+log_must diff /$TESTPOOL/fs/file /$TESTPOOL/recv/L-L/file
+
+log_must zfs send -c $TESTPOOL/fs@snap | zfs recv $TESTPOOL/recv/noL-L
+log_must zfs send -c -L -i @snap $TESTPOOL/fs@snap2 | zfs recv $TESTPOOL/recv/noL-L
+log_must diff /$TESTPOOL/fs/file /$TESTPOOL/recv/noL-L/file
+
+log_must zfs send -c -L $TESTPOOL/fs@snap | zfs recv $TESTPOOL/recv/L-noL
+log_mustnot zfs send -c -i @snap $TESTPOOL/fs@snap2 | zfs recv $TESTPOOL/recv/L-noL
+log_must diff /$TESTPOOL/fs/.zfs/snapshot/snap/file /$TESTPOOL/recv/L-noL/file
+
+log_pass "Verify toggling send -L works as expected"
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_embedded_blocks.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_embedded_blocks.ksh
new file mode 100755
index 000000000000..70f79b3173b7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_embedded_blocks.ksh
@@ -0,0 +1,109 @@
+#!/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/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/include/properties.shlib
+
+#
+# Description:
+# Verify that compressed streams can contain embedded blocks.
+#
+# Strategy:
+# 1. Create a filesystem with compressible data and embedded blocks.
+# 2. Verify the created streams can be received correctly.
+# 3. Verify the presence / absence of embedded blocks in the compressed stream,
+# as well as the receiving file system.
+#
+
+verify_runnable "both"
+
+log_assert "Verify that compressed streams can contain embedded blocks."
+log_onexit cleanup_pool $POOL2
+
+typeset objs obj recsize
+typeset sendfs=$POOL2/sendfs
+typeset recvfs=$POOL2/recvfs
+typeset stream=$BACKDIR/stream
+typeset dump=$BACKDIR/dump
+typeset recvfs2=$POOL2/recvfs2
+typeset stream2=$BACKDIR/stream2
+typeset dump2=$BACKDIR/dump2
+log_must zfs create -o compress=lz4 $sendfs
+log_must zfs create -o compress=lz4 $recvfs
+log_must zfs create -o compress=lz4 $recvfs2
+typeset dir=$(get_prop mountpoint $sendfs)
+
+# Populate the send dataset with compressible data and embedded block files.
+write_compressible $dir 16m
+for recsize in "${recsize_prop_vals[@]}"; do
+ # For lz4, this method works for blocks up to 16k, but not larger
+ [[ $recsize -eq $((32 * 1024)) ]] && break
+
+ if is_linux || is_freebsd; then
+ log_must truncate -s $recsize $dir/$recsize
+ log_must dd if=/dev/urandom of=$dir/$recsize \
+ seek=$((recsize - 8)) bs=1 count=8 conv=notrunc
+ else
+ log_must mkholes -h 0:$((recsize - 8)) -d $((recsize - 8)):8 \
+ $dir/$recsize
+ fi
+done
+
+# Generate the streams and zstreamdump output.
+log_must zfs snapshot $sendfs@now
+log_must eval "zfs send -c $sendfs@now >$stream"
+log_must eval "zstreamdump -v <$stream >$dump"
+log_must eval "zfs recv -d $recvfs <$stream"
+cmp_ds_cont $sendfs $recvfs
+verify_stream_size $stream $sendfs
+log_mustnot stream_has_features $stream embed_data
+
+log_must eval "zfs send -c -e $sendfs@now >$stream2"
+log_must eval "zstreamdump -v <$stream2 >$dump2"
+log_must eval "zfs recv -d $recvfs2 <$stream2"
+cmp_ds_cont $sendfs $recvfs2
+verify_stream_size $stream2 $sendfs
+log_must stream_has_features $stream2 embed_data
+
+# Verify embedded blocks are present only when expected.
+for recsize in "${recsize_prop_vals[@]}"; do
+ [[ $recsize -eq $((32 * 1024)) ]] && break
+
+ typeset send_obj=$(get_objnum $(get_prop mountpoint $sendfs)/$recsize)
+ typeset recv_obj=$(get_objnum \
+ $(get_prop mountpoint $recvfs/sendfs)/$recsize)
+ typeset recv2_obj=$(get_objnum \
+ $(get_prop mountpoint $recvfs2/sendfs)/$recsize)
+
+ log_must eval "zdb -ddddd $sendfs $send_obj >$BACKDIR/sendfs.zdb"
+ log_must eval "zdb -ddddd $recvfs/sendfs $recv_obj >$BACKDIR/recvfs.zdb"
+ log_must eval "zdb -ddddd $recvfs2/sendfs $recv2_obj >$BACKDIR/recvfs2.zdb"
+
+ grep -q "EMBEDDED" $BACKDIR/sendfs.zdb || \
+ log_fail "Obj $send_obj not embedded in $sendfs"
+ grep -q "EMBEDDED" $BACKDIR/recvfs.zdb || \
+ log_fail "Obj $recv_obj not embedded in $recvfs"
+ grep -q "EMBEDDED" $BACKDIR/recvfs2.zdb || \
+ log_fail "Obj $recv2_obj not embedded in $recvfs2"
+
+ grep -q "WRITE_EMBEDDED object = $send_obj offset = 0" $dump && \
+ log_fail "Obj $obj embedded in zstreamdump output"
+ grep -q "WRITE_EMBEDDED object = $send_obj offset = 0" $dump2 || \
+ log_fail "Obj $obj not embedded in zstreamdump output"
+done
+
+log_pass "Compressed streams can contain embedded blocks."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_incremental.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_incremental.ksh
new file mode 100755
index 000000000000..d673282c9355
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_incremental.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) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify that compressed send works correctly with incremental sends.
+#
+# Strategy:
+# 1. Randomly choose either a -i or -I incremental.
+# 2. Generate compressed incremental replication streams for a pool, a
+# descendant dataset, and a volume.
+# 3. Receive these streams verifying both the contents, and intermediate
+# snapshots are present or absent as appropriate to the -i or -I option.
+#
+
+verify_runnable "both"
+
+log_assert "Verify compressed send works with incremental send streams."
+log_onexit cleanup_pool $POOL2
+
+typeset opt=$(random_get "-i" "-I")
+typeset final dstlist list vol
+
+log_must eval "zfs send -R $POOL@final > $BACKDIR/final"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/final"
+
+function do_checks
+{
+ log_must cmp_ds_cont $POOL $POOL2
+ [[ $opt = "-I" ]] && log_must cmp_ds_subs $POOL $POOL2
+ [[ $opt = "-i" ]] && log_mustnot cmp_ds_subs $POOL $POOL2
+
+ [[ $1 != "clean" ]] && return
+
+ cleanup_pool $POOL2
+ log_must eval "zfs send -R $POOL@final > $BACKDIR/final"
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/final"
+}
+
+if is_global_zone; then
+ # Send from the pool root
+ final=$(getds_with_suffix $POOL2 @final)
+ list="$final $(getds_with_suffix $POOL2 @snapA)"
+ list="$list $(getds_with_suffix $POOL2 @snapB)"
+ list="$list $(getds_with_suffix $POOL2 @snapC)"
+
+ log_must eval "zfs send -c -R $opt @init $POOL2@final >$BACKDIR/pool"
+ log_must destroy_tree $list
+ log_must eval "zfs recv -d -F $POOL2 <$BACKDIR/pool"
+
+ dstlist=$(getds_with_suffix $POOL2 @final)
+ [[ $final != $dstlist ]] && log_fail "$final != $dstlist"
+
+ do_checks clean
+
+ # Send of a volume
+ vol=$POOL2/$FS/vol
+ final=$(getds_with_suffix $vol @final)
+ log_must eval "zfs send -c -R $opt @init $vol@final >$BACKDIR/vol"
+ log_must destroy_tree $vol@snapB $vol@snapC $vol@final
+ log_must eval "zfs recv -d -F $POOL2 <$BACKDIR/vol"
+
+ dstlist=$(getds_with_suffix $POOL2/$FS/vol @final)
+ [[ $final != $dstlist ]] && log_fail "$final != $dstlist"
+
+ do_checks clean
+fi
+
+# Send of a descendant fs
+final=$(getds_with_suffix $POOL2/$FS @final)
+list="$final $(getds_with_suffix $POOL2/$FS @snapA)"
+list="$list $(getds_with_suffix $POOL2/$FS @snapB)"
+list="$list $(getds_with_suffix $POOL2/$FS @snapC)"
+
+log_must eval "zfs send -c -R $opt @init $POOL2/$FS@final >$BACKDIR/fs"
+log_must destroy_tree $list
+log_must eval "zfs recv -d -F $POOL2 <$BACKDIR/fs"
+
+dstlist=$(getds_with_suffix $POOL2/$FS @final)
+[[ $final != $dstlist ]] && log_fail "$final != $dstlist"
+
+do_checks
+
+log_pass "Compressed send works with incremental send streams."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_lz4_disabled.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_lz4_disabled.ksh
new file mode 100755
index 000000000000..666e11f702f8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_lz4_disabled.ksh
@@ -0,0 +1,73 @@
+#!/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/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify a pool without the lz4 feature enabled can create compressed send
+# streams, and that they can be received into pools with or without the
+# lz4 feature.
+#
+# Strategy:
+# 1. For each of an uncompressed, and gzip dataset created from a pool with
+# the lz4 feature disabled, receive the stream into a pool with and without
+# the feature enabled.
+#
+
+verify_runnable "both"
+
+log_assert "Verify compressed streams are rejected if incompatible."
+
+typeset send_ds=$POOL2/testds
+typeset recv_ds=$POOL3/testds
+
+function cleanup
+{
+ poolexists $POOL2 && destroy_pool $POOL2
+ poolexists $POOL3 && destroy_pool $POOL3
+ log_must zpool create $POOL2 $DISK2
+}
+log_onexit cleanup
+
+datasetexists $POOL2 && log_must zpool destroy $POOL2
+log_must zpool create -d $POOL2 $DISK2
+
+for compress in off gzip; do
+ for pool_opt in '' -d; do
+ poolexists $POOL3 && destroy_pool $POOL3
+ log_must zpool create $pool_opt $POOL3 $DISK3
+
+ datasetexists $send_ds && log_must_busy zfs destroy -r $send_ds
+ datasetexists $recv_ds && log_must_busy zfs destroy -r $recv_ds
+
+ log_must zfs create -o compress=$compress $send_ds
+ typeset dir=$(get_prop mountpoint $send_ds)
+ write_compressible $dir 16m
+ log_must zfs snapshot $send_ds@full
+
+ log_must eval "zfs send -c $send_ds@full >$BACKDIR/full-c"
+ log_must eval "zfs recv $recv_ds <$BACKDIR/full-c"
+
+ log_must_busy zfs destroy -r $recv_ds
+
+ log_must eval "zfs send $send_ds@full >$BACKDIR/full"
+ log_must eval "zfs recv $recv_ds <$BACKDIR/full"
+ done
+done
+
+log_pass "Compressed streams are rejected if incompatible."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_mixed_compression.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_mixed_compression.ksh
new file mode 100755
index 000000000000..22e91c011b31
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_mixed_compression.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) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/include/properties.shlib
+
+#
+# Description:
+# Verify datasets using mixed compression algorithms can be received.
+#
+# Strategy:
+# 1. Write data with each of the available compression algorithms
+# 2. Receive a full compressed send, and verify the data and compression ratios
+#
+
+verify_runnable "both"
+
+log_assert "Verify datasets using mixed compression algorithms can be received."
+log_onexit cleanup_pool $POOL2
+
+send_ds=$POOL2/sendfs
+recv_ds=$POOL2/recvfs
+
+log_must zfs create $send_ds
+
+for prop in "${compress_prop_vals[@]}"; do
+ log_must zfs set compress=$prop $send_ds
+ write_compressible $(get_prop mountpoint $send_ds) 16m
+done
+
+log_must zfs set compress=off $send_ds
+log_must zfs snapshot $send_ds@full
+log_must eval "zfs send -c $send_ds@full >$BACKDIR/full"
+log_must eval "zfs recv $recv_ds <$BACKDIR/full"
+
+verify_stream_size $BACKDIR/full $send_ds
+verify_stream_size $BACKDIR/full $recv_ds
+log_must cmp_ds_cont $send_ds $recv_ds
+
+log_pass "Datasets using mixed compression algorithms can be received."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_props.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_props.ksh
new file mode 100755
index 000000000000..6e95c2c30b67
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_props.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) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/include/properties.shlib
+
+#
+# Description:
+# Verify compressed send streams can still preserve properties
+#
+# Strategy:
+# 1. Randomly modify the properties in the src pool
+# 2. Send a full compressed stream with -p to preserve properties
+# 3. Verify all the received properties match the source datasets
+# 4. Repeat the process with -R instead of -p
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ destroy_pool $POOL
+ destroy_pool $POOL2
+ log_must zpool create $POOL $DISK1
+ log_must zpool create $POOL2 $DISK2
+ log_must setup_test_model $POOL
+}
+
+log_assert "Compressed send doesn't interfere with preservation of properties"
+log_onexit cleanup
+
+typeset -a datasets=("" "/pclone" "/$FS" "/$FS/fs1" "/$FS/fs1/fs2"
+ "/$FS/fs1/fclone" "/vol" "/$FS/vol")
+
+typeset ds
+for opt in "-p" "-R"; do
+ for ds in ${datasets[@]}; do
+ randomize_ds_props $POOL$ds
+ done
+
+ log_must eval "zfs send -c $opt $POOL@final > $BACKDIR/pool-final$opt"
+ log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final$opt"
+
+ for ds in ${datasets[@]}; do
+ log_must cmp_ds_prop $POOL$ds $POOL2$ds
+ log_must cmp_ds_prop $POOL$ds@final $POOL2$ds@final
+ done
+
+ # Don't cleanup the second time, since we do that on exit anyway.
+ [[ $opt = "-p" ]] && cleanup
+done
+
+log_pass "Compressed send doesn't interfere with preservation of properties"
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_recv_dedup.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_recv_dedup.ksh
new file mode 100755
index 000000000000..cef81617b13b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_recv_dedup.ksh
@@ -0,0 +1,55 @@
+#!/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/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify that we can receive a compressed stream into a deduped filesystem.
+#
+# Strategy:
+# 1. Write heavily duplicated data to a filesystem and create a compressed
+# full stream.
+# 2. Verify that the stream can be received correctly into a dedup=verify
+# filesystem.
+#
+
+verify_runnable "both"
+
+log_pass "Verify a compressed stream can be received into a deduped filesystem"
+log_onexit cleanup_pool $POOL2
+
+typeset sendfs=$POOL2/sendfs
+typeset recvfs=$POOL2/recvfs
+typeset stream0=$BACKDIR/stream.0
+typeset stream1=$BACKDIR/stream.1
+typeset inc=$BACKDIR/stream.inc
+
+log_must zfs create -o compress=lz4 $sendfs
+log_must zfs create -o compress=lz4 -o dedup=verify $recvfs
+typeset dir=$(get_prop mountpoint $sendfs)
+for i in {0..10}; do
+ log_must file_write -o overwrite -f $dir/file.$i -d R -b 4096 -c 1000
+done
+log_must zfs snapshot $sendfs@snap0
+log_must eval "zfs send -c $sendfs@snap0 >$stream0"
+
+# Finally, make sure the receive works correctly.
+log_must eval "zfs recv -d $recvfs <$stream0"
+cmp_ds_cont $sendfs $recvfs
+
+log_pass "The compressed stream could be received into a deduped filesystem"
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_recv_lz4_disabled.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_recv_lz4_disabled.ksh
new file mode 100755
index 000000000000..20a8c5481224
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_recv_lz4_disabled.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) 2015, Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/include/properties.shlib
+
+#
+# Description:
+# Verify a pool without the lz4 feature gracefully rejects a compressed stream
+# because on any sending pool that supports it, metadata will be compressed
+# with lz4 even if user data is not compressed.
+#
+# Strategy:
+# 1. For each of an uncompressed, gzip and lz4 dataset, do the following
+# receives into a pool without the lz4 feature:
+# 2. Attempt to receive the compressed stream (should fail)
+# 3. Attempt to receive the uncompressed stream (should succeed)
+#
+
+verify_runnable "both"
+
+log_assert "Verify compressed streams are rejected if incompatible."
+
+typeset send_ds=$POOL2/testds
+typeset recv_ds=$POOL3/testds
+
+function cleanup
+{
+ poolexists $POOL2 && destroy_pool $POOL2
+ poolexists $POOL3 && destroy_pool $POOL3
+ log_must zpool create $POOL2 $DISK2
+}
+log_onexit cleanup
+
+datasetexists $POOL3 && log_must zpool destroy $POOL3
+log_must zpool create -d $POOL3 $DISK3
+
+for compress in "${compress_prop_vals[@]}"; do
+ datasetexists $send_ds && log_must_busy zfs destroy -r $send_ds
+ datasetexists $recv_ds && log_must_busy zfs destroy -r $recv_ds
+
+ log_must zfs create -o compress=$compress $send_ds
+ typeset dir=$(get_prop mountpoint $send_ds)
+ write_compressible $dir 16m
+ log_must zfs snapshot $send_ds@full
+
+ log_must eval "zfs send -c $send_ds@full >$BACKDIR/full-c"
+ log_mustnot eval "zfs recv $recv_ds <$BACKDIR/full-c"
+
+ log_must eval "zfs send $send_ds@full >$BACKDIR/full"
+ log_must eval "zfs recv $recv_ds <$BACKDIR/full"
+done
+
+log_pass "Compressed streams are rejected if incompatible."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_resume.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_resume.ksh
new file mode 100755
index 000000000000..05ba5ed244d9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_resume.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) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify resumability of full and incremental ZFS send/receive with the -c
+# (compress) flag in the presence of a corrupted stream.
+#
+# Strategy:
+# 1. Start a full ZFS send with the -c flag (compress), redirect output to
+# a file
+# 2. Mess up the contents of the stream state file on disk
+# 3. Try ZFS receive, which should fail with a checksum mismatch error
+# 4. ZFS send to the stream state file again using the receive_resume_token
+# 5. ZFS receive and verify the receive completes successfully
+# 6. Repeat steps on an incremental ZFS send
+#
+
+verify_runnable "both"
+
+sendfs=$POOL/sendfs
+recvfs=$POOL2/recvfs
+streamfs=$POOL/stream
+
+log_assert "Verify compressed send streams can be resumed if interrupted"
+log_onexit resume_cleanup $sendfs $streamfs
+
+test_fs_setup $sendfs $recvfs $streamfs
+resume_test "zfs send -c -v $sendfs@a" $streamfs $recvfs
+resume_test "zfs send -c -v -i @a $sendfs@b" $streamfs $recvfs
+file_check $sendfs $recvfs
+
+log_pass "Compressed send streams can be resumed if interrupted"
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_stream_size_estimate.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_stream_size_estimate.ksh
new file mode 100755
index 000000000000..840b5f085967
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_stream_size_estimate.ksh
@@ -0,0 +1,97 @@
+#!/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, Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/include/properties.shlib
+
+#
+# Description:
+# Verify the stream size estimate given by -P accounts for compressed send.
+# Verify the stream size given by -P accounts for compressed send."
+#
+# Strategy:
+# 1. For datasets of varied compression types do the following:
+# 2. Write data, verify stream size estimates with and without -c
+#
+
+verify_runnable "both"
+typeset send_ds="$POOL2/testfs"
+typeset send_vol="$POOL2/vol"
+typeset send_voldev="$ZVOL_DEVDIR/$POOL2/vol"
+typeset file="$BACKDIR/file.0"
+typeset megs="16"
+typeset compress
+
+function get_estimated_size
+{
+ typeset cmd=$1
+ typeset ds=${cmd##* }
+ if is_freebsd; then
+ mkdir -p $BACKDIR
+ typeset tmpfile=$(TMPDIR=$BACKDIR mktemp)
+ else
+ typeset tmpfile=$(mktemp -p $BACKDIR)
+ fi
+
+ eval "$cmd >$tmpfile"
+ [[ $? -eq 0 ]] || log_fail "get_estimated_size: $cmd"
+ typeset size=$(eval "awk '\$2 == \"$ds\" {print \$3}' $tmpfile")
+ rm -f $tmpfile
+
+ echo $size
+}
+
+log_assert "Verify the stream size given by -P accounts for compressed send."
+log_onexit cleanup_pool $POOL2
+
+write_compressible $BACKDIR ${megs}m
+
+for compress in "${compress_prop_vals[@]}"; do
+ datasetexists $send_ds && log_must_busy zfs destroy -r $send_ds
+ datasetexists $send_vol && log_must_busy zfs destroy -r $send_vol
+ log_must zfs create -o compress=$compress $send_ds
+ log_must zfs create -V 1g -o compress=$compress $send_vol
+ block_device_wait
+
+ typeset dir=$(get_prop mountpoint $send_ds)
+ log_must cp $file $dir
+ log_must zfs snapshot $send_ds@snap
+ log_must dd if=$file of=$send_voldev
+ log_must zfs snapshot $send_vol@snap
+
+ typeset ds_size=$(get_estimated_size "zfs send -nP $send_ds@snap")
+ typeset ds_lrefer=$(get_prop lrefer $send_ds)
+ within_percent $ds_size $ds_lrefer 90 || log_fail \
+ "$ds_size and $ds_lrefer differed by too much"
+
+ typeset vol_size=$(get_estimated_size "zfs send -nP $send_vol@snap")
+ typeset vol_lrefer=$(get_prop lrefer $send_vol)
+ within_percent $vol_size $vol_lrefer 90 || log_fail \
+ "$vol_size and $vol_lrefer differed by too much"
+
+ typeset ds_csize=$(get_estimated_size "zfs send -nP -c $send_ds@snap")
+ typeset ds_refer=$(get_prop refer $send_ds)
+ within_percent $ds_csize $ds_refer 90 || log_fail \
+ "$ds_csize and $ds_refer differed by too much"
+
+ typeset vol_csize=$(get_estimated_size "zfs send -nP -c $send_vol@snap")
+ typeset vol_refer=$(get_prop refer $send_vol)
+ within_percent $vol_csize $vol_refer 90 || log_fail \
+ "$vol_csize and $vol_refer differed by too much"
+done
+
+log_pass "The stream size given by -P accounts for compressed send."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_verify_contents.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_verify_contents.ksh
new file mode 100755
index 000000000000..0a5d56bebe32
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_verify_contents.ksh
@@ -0,0 +1,55 @@
+#!/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/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify compressed send streams replicate data and datasets
+#
+# Strategy:
+# 1. Back up all the data from POOL/FS
+# 2. Verify all the datasets and data can be recovered in POOL2
+# 3. Back up all the data from root filesystem POOL2
+# 4. Verify all the data can be recovered, too
+#
+
+verify_runnable "both"
+
+log_assert "zfs send -c -R send replication stream up to the named snap."
+log_onexit cleanup_pool $POOL2
+
+# Verify the entire pool and descendants can be backed up and restored.
+log_must eval "zfs send -c -R $POOL@final > $BACKDIR/pool-final-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/pool-final-R"
+
+dstds=$(get_dst_ds $POOL $POOL2)
+log_must cmp_ds_subs $POOL $dstds
+log_must cmp_ds_cont $POOL $dstds
+
+# Cleanup POOL2
+log_must cleanup_pool $POOL2
+
+# Verify all the filesystems and descendants can be backed up and restored.
+log_must eval "zfs send -c -R $POOL/$FS@final > $BACKDIR/fs-final-R"
+log_must eval "zfs receive -d $POOL2 < $BACKDIR/fs-final-R"
+
+dstds=$(get_dst_ds $POOL/$FS $POOL2)
+log_must cmp_ds_subs $POOL/$FS $dstds
+log_must cmp_ds_cont $POOL/$FS $dstds
+
+log_pass "zfs send -c -R send replication stream up to the named snap."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_verify_ratio.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_verify_ratio.ksh
new file mode 100755
index 000000000000..b7d978624f2b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_verify_ratio.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) 2015, Delphix. All rights reserved.
+# Copyright (c) 2019, Kjeld Schouten-Lebbing. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/include/properties.shlib
+
+#
+# Description:
+# Verify that the amount of data in a send -c stream matches compressratio.
+#
+# Strategy:
+# 1. For random compression types, and compressible / incompressible data:
+# 2. Create a snap with data
+# 3. Compare the size of the stream with the data on the dataset, adjusted
+# by compressratio for normal send, and compared to used for send -c.
+#
+
+verify_runnable "both"
+
+log_assert "Verify send -c streams are compressed"
+log_onexit cleanup_pool $POOL2
+
+typeset sendfs=$POOL2/$FS
+typeset megs=128
+
+for prop in "${compress_prop_vals[@]}"; do
+ for compressible in 'yes' 'no'; do
+ log_must zfs create -o compress=$prop $sendfs
+
+ if [[ $compressible = 'yes' ]]; then
+ write_compressible $(get_prop mountpoint $sendfs) \
+ ${megs}m
+ else
+ typeset file="$(get_prop mountpoint $sendfs)/ddfile"
+ log_must dd if=/dev/urandom of=$file bs=1024k count=$megs
+ fi
+
+ log_must zfs snapshot $sendfs@snap
+
+ # Calculate the sizes and verify the compression ratio.
+ log_must eval "zfs send $sendfs@snap >$BACKDIR/uncompressed"
+ verify_stream_size $BACKDIR/uncompressed $sendfs
+
+ log_must eval "zfs send -c $sendfs@snap >$BACKDIR/compressed"
+ verify_stream_size $BACKDIR/compressed $sendfs
+
+ log_must rm $BACKDIR/uncompressed $BACKDIR/compressed
+ log_must_busy zfs destroy -r $sendfs
+ done
+done
+
+log_pass "Verify send -c streams are compressed"
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_volume.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_volume.ksh
new file mode 100755
index 000000000000..988ed91b9918
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_volume.ksh
@@ -0,0 +1,78 @@
+#!/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/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify that compressed send correctly handles volumes
+#
+# Strategy:
+# 1. Write compressible data into a volume, take a snap
+# 2. Verify the compressed stream is the correct size, and has the correct data
+# 3. Repeat step 2 for an incremental compressed stream
+#
+
+function cleanup
+{
+ log_must_busy zfs destroy -r $vol
+ cleanup_pool $POOL2
+}
+
+verify_runnable "both"
+
+log_assert "Verify compressed send works with volumes"
+log_onexit cleanup
+
+typeset vol="$POOL/newvol"
+typeset vol2="$POOL2/newvol"
+typeset voldev="$ZVOL_DEVDIR/$POOL/newvol"
+typeset voldev2="$ZVOL_DEVDIR/$POOL2/newvol"
+typeset data1=$BACKDIR/file.0
+typeset data2=$BACKDIR/file.1
+typeset megs=8
+
+log_must zfs create -V 256m -o compress=lz4 $vol
+
+write_compressible $BACKDIR ${megs}m 2
+md5_1=$(md5digest $data1)
+md5_2=$(md5digest $data2)
+
+log_must dd if=$data1 of=$voldev bs=1024k
+log_must zfs snapshot $vol@snap
+
+log_must eval "zfs send -c $vol@snap >$BACKDIR/full"
+log_must eval "zfs recv -d $POOL2 <$BACKDIR/full"
+
+verify_stream_size $BACKDIR/full $vol
+verify_stream_size $BACKDIR/full $vol2
+md5=$(dd if=$voldev2 bs=1024k count=$megs 2>/dev/null | md5digest)
+[[ $md5 = $md5_1 ]] || log_fail "md5 mismatch: $md5 != $md5_1"
+
+# Repeat, for an incremental send
+log_must dd seek=$megs if=$data2 of=$voldev bs=1024k
+log_must zfs snapshot $vol@snap2
+
+log_must eval "zfs send -c -i snap $vol@snap2 >$BACKDIR/inc"
+log_must eval "zfs recv -d $POOL2 <$BACKDIR/inc"
+
+verify_stream_size $BACKDIR/inc $vol 90 $vol@snap
+verify_stream_size $BACKDIR/inc $vol2 90 $vol2@snap
+md5=$(dd skip=$megs if=$voldev2 bs=1024k count=$megs 2>/dev/null | md5digest)
+[[ $md5 = $md5_2 ]] || log_fail "md5 mismatch: $md5 != $md5_2"
+
+log_pass "Verify compressed send works with volumes"
diff --git a/tests/zfs-tests/tests/functional/rsend/send-c_zstreamdump.ksh b/tests/zfs-tests/tests/functional/rsend/send-c_zstreamdump.ksh
new file mode 100755
index 000000000000..b4dc00cec4e7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-c_zstreamdump.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) 2015 by Delphix. All rights reserved.
+# Copyright (c) 2020 by Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/include/math.shlib
+
+#
+# Description:
+# Verify compression features show up in zstreamdump
+#
+# Strategy:
+# 1. Create a full compressed send stream
+# 2. Verify zstreamdump shows this stream has the relevant features
+# 3. Verify zstreamdump's accounting of logical and compressed size is correct
+# 4. Verify the toname from a resume token
+# 5. Verify it fails with corrupted resume token
+# 6. Verify it fails with missing resume token
+#
+
+verify_runnable "both"
+
+log_assert "Verify zstreamdump correctly interprets compressed send streams."
+log_onexit cleanup_pool $POOL2
+
+typeset sendfs=$POOL2/fs
+typeset streamfs=$POOL2/fs2
+typeset recvfs=$POOL2/fs3
+
+log_must zfs create -o compress=lz4 $sendfs
+log_must zfs create -o compress=lz4 $streamfs
+typeset dir=$(get_prop mountpoint $sendfs)
+write_compressible $dir 16m
+log_must zfs snapshot $sendfs@full
+
+log_must eval "zfs send -c $sendfs@full >$BACKDIR/full"
+log_must stream_has_features $BACKDIR/full lz4 compressed
+cat $BACKDIR/full | zstreamdump -v > $BACKDIR/dump.out
+
+lsize=$(awk '/^WRITE [^0]/ {lsize += $24} END {printf("%d", lsize)}' \
+ $BACKDIR/dump.out)
+lsize_prop=$(get_prop logicalused $sendfs)
+within_percent $lsize $lsize_prop 90 || log_fail \
+ "$lsize and $lsize_prop differed by too much"
+
+csize=$(awk '/^WRITE [^0]/ {csize += $27} END {printf("%d", csize)}' \
+ $BACKDIR/dump.out)
+csize_prop=$(get_prop used $sendfs)
+within_percent $csize $csize_prop 90 || log_fail \
+ "$csize and $csize_prop differed by too much"
+
+x=$(get_resume_token "zfs send -c $sendfs@full" $streamfs $recvfs)
+resume_token=$(cat /$streamfs/resume_token)
+to_name_fs=$sendfs
+log_must eval "zstream token $resume_token | grep $to_name_fs"
+
+bad_resume_token="1-1162e8285b-100789c6360"
+log_mustnot eval "zstream token $bad_resume_token 2>&1"
+log_mustnot eval "zstream token 2>&1"
+
+log_pass "zstreamdump correctly interprets compressed send streams."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-cpL_varied_recsize.ksh b/tests/zfs-tests/tests/functional/rsend/send-cpL_varied_recsize.ksh
new file mode 100755
index 000000000000..e1ac00c79c96
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-cpL_varied_recsize.ksh
@@ -0,0 +1,203 @@
+#!/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/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify compressed send works correctly with datasets of varying recsize.
+#
+# Strategy:
+# 1. Check the recv behavior (into pools with features enabled and disabled)
+# of all combinations of -c -p and -L. Verify the stream is compressed,
+# and that the recsize property and that of a received file is correct
+# according to this matrix:
+#
+# +---------+--------+------------+------------+-----------+-----------+
+# | send | send | received | received | received | received |
+# | stream | stream | file bs | prop | file bs | props |
+# | recsize | flags | (disabled) | (disabled) | (enabled) | (enabled) |
+# +---------+--------+------------+------------+-----------+-----------+
+# | 128k | | 128k | 128k | 128k | 128k |
+# | 128k | -c | Fails | Fails | 128k | 128k |
+# | 128k | -p | 128k | 128k | 128k | 128k |
+# | 128k | -L | 128k | 128k | 128k | 128k |
+# | 128k | -cp | Fails | Fails | 128k | 128k |
+# | 128k | -cL | Fails | Fails | 128k | 128k |
+# | 128k | -pL | 128k | 128k | 128k | 128k |
+# | 128k | -cpL | Fails | Fails | 128k | 128k |
+# | 1m | | Fails | Fails | 128k | 128k |
+# | 1m | -c | Fails | Fails | 128k | 128k |
+# | 1m | -p | 128k | 128k | 128k | 1m |
+# | 1m | -L | Fails | Fails | 1m | 128k |
+# | 1m | -cp | Fails | Fails | 128k | 1m |
+# | 1m | -cL | Fails | Fails | 1m | 128k |
+# | 1m | -pL | Fails | Fails | 1m | 1m |
+# | 1m | -cpL | Fails | Fails | 1m | 1m |
+# +---------+--------+------------+------------+-----------+-----------+
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/128k && log_must_busy zfs destroy $TESTPOOL/128k
+ datasetexists $TESTPOOL/1m && log_must_busy zfs destroy $TESTPOOL/1m
+ cleanup_pool $POOL2
+ destroy_pool $POOL3
+}
+
+# For a received stream, verify the recsize (prop and file) match expectations.
+function check_recsize
+{
+ typeset recv_ds=$1
+ typeset expected_file_bs=$2
+ typeset expected_recsize=$3
+ typeset file="$(get_prop mountpoint $recv_ds)/testfile"
+
+ [[ -f $file ]] || log_fail "file '$file' doesn't exist"
+
+ typeset read_recsize=$(get_prop recsize $recv_ds)
+ if is_freebsd; then
+ typeset read_file_bs=$(stat -f "%k" $file)
+ else
+ typeset read_file_bs=$(stat $file | sed -n \
+ 's/.*IO Block: \([0-9]*\).*/\1/p')
+ fi
+
+ [[ $read_recsize = $expected_recsize ]] || log_fail \
+ "read_recsize: $read_recsize expected_recsize: $expected_recsize"
+ [[ $read_file_bs = $expected_file_bs ]] || log_fail \
+ "read_file_bs: $read_file_bs expected_file_bs: $expected_file_bs"
+}
+
+#
+# This function does a zfs send and receive according to the parameters
+# below, and verifies the data shown in the strategy section.
+#
+# -[cpL] flags to pass through to 'zfs send'
+# -d Receive into a pool with all features disabled
+#
+# $1 The recordsize of the send dataset
+# $2 Whether or not the recv should work.
+# $3 The blocksize expected in a received file (default 128k)
+# $4 The recordsize property expected in a received dataset (default 128k)
+#
+function check
+{
+ typeset recv_pool=$POOL2
+ typeset flags='-'
+
+ while getopts "cdpL" opt; do
+ case $opt in
+ c)
+ flags+='c'
+ ;;
+ d)
+ recv_pool=$POOL3
+ ;;
+ p)
+ flags+='p'
+ ;;
+ L)
+ flags+='L'
+ ;;
+ esac
+ done
+ shift $(($OPTIND - 1))
+ [[ ${#flags} -eq 1 ]] && flags=''
+
+ typeset recsize=$1
+ typeset verify=$2
+ typeset expected_file_bs=${3-131072}
+ typeset expected_recsize=${4-131072}
+ typeset send_ds=$TESTPOOL/$recsize
+ typeset send_snap=$send_ds@snap
+ typeset recv_ds=$recv_pool/$recsize
+ typeset stream=$BACKDIR/stream.out
+
+ datasetexists $send_ds || log_fail "send ds: $send_ds doesn't exist"
+ [[ -f $stream ]] && log_must rm $stream
+ log_must eval "zfs send $flags $send_snap >$stream"
+ $verify eval "zfs recv $recv_ds <$stream"
+ typeset stream_size=$(cat $stream | zstreamdump | sed -n \
+ 's/ Total write size = \(.*\) (0x.*)/\1/p')
+
+ #
+ # Special case: For a send dataset with large blocks, don't try to
+ # verify the stream size is correct if the compress flag is present
+ # but the large blocks flag isn't. In these cases, the user data
+ # isn't compressed in the stream (though metadata is) so the
+ # verification would fail.
+ #
+ typeset do_size_test=true
+ [[ $recsize = $large && $flags =~ 'c' && ! $flags =~ 'L' ]] && \
+ do_size_test=false
+
+ $do_size_test && verify_stream_size $stream $send_ds
+
+ if [[ $verify = "log_mustnot" ]]; then
+ datasetnonexists $recv_ds || log_fail "$recv_ds shouldn't exist"
+ return
+ fi
+
+ check_recsize $recv_ds $expected_file_bs $expected_recsize
+ $do_size_test && verify_stream_size $stream $recv_ds
+ log_must_busy zfs destroy -r $recv_ds
+}
+
+log_assert "Verify compressed send works with datasets of varying recsize."
+log_onexit cleanup
+typeset recsize opts dir
+typeset small=$((128 * 1024))
+typeset large=$((1024 * 1024))
+
+# Create POOL3 with features disabled and datasets to create test send streams
+datasetexists $POOL3 && log_must zpool destroy $POOL3
+log_must zpool create -d $POOL3 $DISK3
+write_compressible $BACKDIR 32m
+for recsize in $small $large; do
+ log_must zfs create -o compress=gzip -o recsize=$recsize \
+ $TESTPOOL/$recsize
+ dir=$(get_prop mountpoint $TESTPOOL/$recsize)
+ log_must cp $BACKDIR/file.0 $dir/testfile
+ log_must zfs snapshot $TESTPOOL/$recsize@snap
+done
+
+# Run tests for send streams without large blocks
+for opts in '' -d -c -p -dp -L -dL -cp -cL -pL -dpL -cpL; do
+ check $opts $small log_must
+done
+for opts in -dc -dcp -dcL -dcpL; do
+ check $opts $small log_mustnot
+done
+
+# Run tests for send streams with large blocks
+for opts in '' -d -dp -c; do
+ check $opts $large log_must
+done
+for opts in -dc -dL -dcp -dcL -dpL -dcpL; do
+ check $opts $large log_mustnot
+done
+check -p $large log_must $small $large
+check -L $large log_must $large $small
+check -cp $large log_must $small $large
+check -cL $large log_must $large $small
+check -pL $large log_must $large $large
+check -cpL $large log_must $large $large
+
+log_pass "Compressed send works with datasets of varying recsize."
diff --git a/tests/zfs-tests/tests/functional/rsend/send-wR_encrypted_zvol.ksh b/tests/zfs-tests/tests/functional/rsend/send-wR_encrypted_zvol.ksh
new file mode 100755
index 000000000000..b95fc3da30c3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send-wR_encrypted_zvol.ksh
@@ -0,0 +1,108 @@
+#!/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) 2018 by Datto Inc. All rights reserved.
+# Copyright (c) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Verify that zvols with encryption=on can be sent and received with a raw
+# send stream.
+#
+# STRATEGY:
+# 1. Create a zvol with encryption on and put a filesystem on it
+# 2. Copy a file into the zvol a few times and take a snapshot
+# 3. Repeat step 2 a few times to create more snapshots
+# 4. Send all snapshots in a recursive, raw send stream
+# 5. Mount the received zvol and verify that all of the data there is correct
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ ismounted $recvmnt $fstype && log_must umount $recvmnt
+ ismounted $mntpnt $fstype && log_must umount $mntpnt
+ [[ -d $recvmnt ]] && log_must rm -rf $keyfile
+ [[ -d $mntpnt ]] && log_must rm -rf $keyfile
+ destroy_dataset $TESTPOOL/recv "-r"
+ destroy_dataset $TESTPOOL/$TESTVOL "-r"
+ [[ -f $keyfile ]] && log_must rm $keyfile
+ [[ -f $sendfile ]] && log_must rm $sendfile
+}
+log_onexit cleanup
+
+log_assert "Verify zfs can receive raw, recursive send streams"
+
+typeset keyfile=/$TESTPOOL/pkey
+typeset snap_count=5
+typeset zdev=$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL
+typeset mntpnt=$TESTDIR/$TESTVOL
+typeset recvdev=$ZVOL_DEVDIR/$TESTPOOL/recv
+typeset recvmnt=$TESTDIR/recvmnt
+typeset sendfile=$TESTDIR/sendfile
+typeset fstype=none
+
+log_must eval "echo 'password' > $keyfile"
+
+log_must zfs create -o dedup=on -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file://$keyfile -V 128M $TESTPOOL/$TESTVOL
+block_device_wait
+
+if is_linux; then
+ # ext4 only supported on Linux
+ log_must new_fs -t ext4 $zdev
+ fstype=ext4
+ typeset remount_ro="-o remount,ro"
+ typeset remount_rw="-o remount,rw"
+else
+ log_must new_fs $zdev
+ fstype=$NEWFS_DEFAULT_FS
+ typeset remount_ro="-ur"
+ typeset remount_rw="-uw"
+fi
+log_must mkdir -p $mntpnt
+log_must mkdir -p $recvmnt
+log_must mount $zdev $mntpnt
+
+for ((i = 1; i <= $snap_count; i++)); do
+ log_must dd if=/dev/urandom of=$mntpnt/file bs=1M count=1
+ for ((j = 0; j < 10; j++)); do
+ log_must cp $mntpnt/file $mntpnt/file$j
+ done
+
+ log_must sync
+ log_must mount $remount_ro $zdev $mntpnt
+ log_must zfs snap $TESTPOOL/$TESTVOL@snap$i
+ log_must mount $remount_rw $zdev $mntpnt
+done
+
+log_must eval "zfs send -wR $TESTPOOL/$TESTVOL@snap$snap_count > $sendfile"
+log_must eval "zfs recv $TESTPOOL/recv < $sendfile"
+log_must zfs load-key $TESTPOOL/recv
+block_device_wait
+
+log_must mount $recvdev $recvmnt
+
+md5_1=$(cat $mntpnt/* | md5digest)
+md5_2=$(cat $recvmnt/* | md5digest)
+[[ "$md5_1" == "$md5_2" ]] || log_fail "md5 mismatch: $md5_1 != $md5_2"
+
+log_pass "zfs can receive raw, recursive send streams"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_files.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_files.ksh
new file mode 100755
index 000000000000..f89cb3b31bee
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_files.ksh
@@ -0,0 +1,120 @@
+#!/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) 2018 by Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Verify that a raw zfs send and receive can deal with several different
+# types of file layouts.
+#
+# STRATEGY:
+# 1. Create a new encrypted filesystem
+# 2. Add an empty file to the filesystem
+# 3. Add a small 512 byte file to the filesystem
+# 4. Add a larger 32M file to the filesystem
+# 5. Add a large sparse file to the filesystem
+# 6. Add 1000 empty files to the filesystem
+# 7. Add a file with a large xattr value
+# 8. Use xattrtest to create files with random xattrs (with and without xattrs=on)
+# 9. Take a snapshot of the filesystem
+# 10. Remove the 1000 empty files to the filesystem
+# 11. Take another snapshot of the filesystem
+# 12. Send and receive both snapshots
+# 13. Mount the filesystem and check the contents
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+ datasetexists $TESTPOOL/recv && \
+ log_must zfs destroy -r $TESTPOOL/recv
+ [[ -f $keyfile ]] && log_must rm $keyfile
+ [[ -f $sendfile ]] && log_must rm $sendfile
+}
+log_onexit cleanup
+
+log_assert "Verify 'zfs send -w' works with many different file layouts"
+
+typeset keyfile=/$TESTPOOL/pkey
+typeset sendfile=/$TESTPOOL/sendfile
+typeset sendfile2=/$TESTPOOL/sendfile2
+
+# Create an encrypted dataset
+log_must eval "echo 'password' > $keyfile"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file://$keyfile $TESTPOOL/$TESTFS2
+
+# Create files with varied layouts on disk
+log_must touch /$TESTPOOL/$TESTFS2/empty
+log_must mkfile 512 /$TESTPOOL/$TESTFS2/small
+log_must mkfile 32M /$TESTPOOL/$TESTFS2/full
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS2/sparse \
+ bs=512 count=1 seek=1048576 >/dev/null 2>&1
+
+log_must mkdir -p /$TESTPOOL/$TESTFS2/dir
+for i in {1..1000}; do
+ log_must mkfile 512 /$TESTPOOL/$TESTFS2/dir/file-$i
+done
+
+log_must mkdir -p /$TESTPOOL/$TESTFS2/xattrondir
+log_must zfs set xattr=on $TESTPOOL/$TESTFS2
+log_must xattrtest -f 10 -x 3 -s 32768 -r -k -p /$TESTPOOL/$TESTFS2/xattrondir
+log_must mkdir -p /$TESTPOOL/$TESTFS2/xattrsadir
+log_must zfs set xattr=sa $TESTPOOL/$TESTFS2
+log_must xattrtest -f 10 -x 3 -s 32768 -r -k -p /$TESTPOOL/$TESTFS2/xattrsadir
+
+# ZoL issue #7432
+log_must zfs set compression=on xattr=sa $TESTPOOL/$TESTFS2
+log_must touch /$TESTPOOL/$TESTFS2/attrs
+log_must eval "python -c 'print \"a\" * 4096' | \
+ set_xattr_stdin bigval /$TESTPOOL/$TESTFS2/attrs"
+log_must zfs set compression=off xattr=on $TESTPOOL/$TESTFS2
+
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snap1
+
+# Remove the empty files created in the first snapshot
+for i in {1..1000}; do
+ log_must rm /$TESTPOOL/$TESTFS2/dir/file-$i
+done
+sync
+
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snap2
+expected_cksum=$(recursive_cksum /$TESTPOOL/$TESTFS2)
+
+log_must eval "zfs send -wp $TESTPOOL/$TESTFS2@snap1 > $sendfile"
+log_must eval "zfs send -wp -i @snap1 $TESTPOOL/$TESTFS2@snap2 > $sendfile2"
+
+log_must eval "zfs recv -F $TESTPOOL/recv < $sendfile"
+log_must eval "zfs recv -F $TESTPOOL/recv < $sendfile2"
+log_must zfs load-key $TESTPOOL/recv
+
+log_must zfs mount -a
+actual_cksum=$(recursive_cksum /$TESTPOOL/recv)
+[[ "$expected_cksum" != "$actual_cksum" ]] && \
+ log_fail "Recursive checksums differ ($expected_cksum != $actual_cksum)"
+
+log_must xattrtest -f 10 -o3 -y -p /$TESTPOOL/recv/xattrondir
+log_must xattrtest -f 10 -o3 -y -p /$TESTPOOL/recv/xattrsadir
+
+log_pass "Verified 'zfs send -w' works with many different file layouts"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_hierarchy.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_hierarchy.ksh
new file mode 100755
index 000000000000..8417afc88d33
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_hierarchy.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 by Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib
+
+#
+# DESCRIPTION:
+# Raw recursive sends preserve filesystem structure.
+#
+# STRATEGY:
+# 1. Create an encrypted filesystem with a clone and a child
+# 2. Snapshot and send the filesystem tree
+# 3. Verify that the filesystem structure was correctly received
+# 4. Change the child to an encryption root and promote the clone
+# 5. Snapshot and send the filesystem tree again
+# 6. Verify that the new structure is received correctly
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must cleanup_pool $POOL
+ log_must cleanup_pool $POOL2
+ log_must setup_test_model $POOL
+}
+
+log_assert "Raw recursive sends preserve filesystem structure."
+log_onexit cleanup
+
+# Create the filesystem hierarchy
+log_must cleanup_pool $POOL
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $POOL/$FS"
+log_must zfs snapshot $POOL/$FS@snap
+log_must zfs clone $POOL/$FS@snap $POOL/clone
+log_must zfs create $POOL/$FS/child
+
+# Back up the tree and verify the structure
+log_must zfs snapshot -r $POOL@before
+log_must eval "zfs send -wR $POOL@before > $BACKDIR/fs-before-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/fs-before-R"
+dstds=$(get_dst_ds $POOL/$FS $POOL2)
+log_must cmp_ds_subs $POOL/$FS $dstds
+
+log_must verify_encryption_root $POOL/$FS $POOL/$FS
+log_must verify_keylocation $POOL/$FS "prompt"
+log_must verify_origin $POOL/$FS "-"
+
+log_must verify_encryption_root $POOL/clone $POOL/$FS
+log_must verify_keylocation $POOL/clone "none"
+log_must verify_origin $POOL/clone "$POOL/$FS@snap"
+
+log_must verify_encryption_root $POOL/$FS/child $POOL/$FS
+log_must verify_keylocation $POOL/$FS/child "none"
+
+# Alter the hierarchy and re-send
+log_must eval "echo $PASSPHRASE1 | zfs change-key -o keyformat=passphrase" \
+ "$POOL/$FS/child"
+log_must zfs promote $POOL/clone
+log_must zfs snapshot -r $POOL@after
+log_must eval "zfs send -wR -i $POOL@before $POOL@after >" \
+ "$BACKDIR/fs-after-R"
+log_must eval "zfs receive -d -F $POOL2 < $BACKDIR/fs-after-R"
+log_must cmp_ds_subs $POOL/$FS $dstds
+
+log_must verify_encryption_root $POOL/$FS $POOL/clone
+log_must verify_keylocation $POOL/$FS "none"
+log_must verify_origin $POOL/$FS "$POOL/clone@snap"
+
+log_must verify_encryption_root $POOL/clone $POOL/clone
+log_must verify_keylocation $POOL/clone "prompt"
+log_must verify_origin $POOL/clone "-"
+
+log_must verify_encryption_root $POOL/$FS/child $POOL/$FS/child
+log_must verify_keylocation $POOL/$FS/child "prompt"
+
+log_pass "Raw recursive sends preserve filesystem structure."
diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh
new file mode 100755
index 000000000000..793904db91ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_props.ksh
@@ -0,0 +1,215 @@
+#!/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) 2018 by Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Verify that zfs properly handles encryption properties when receiving
+# send streams.
+#
+# STRATEGY:
+# 1. Create a few unencrypted and encrypted test datasets with some data
+# 2. Take snapshots of these datasets in preparation for sending
+# 3. Verify that 'zfs recv -o keylocation=prompt' fails
+# 4. Verify that 'zfs recv -x <encryption prop>' fails on a raw send stream
+# 5. Verify that encryption properties cannot be changed on incrementals
+# 6. Verify that a simple send can be received as an encryption root
+# 7. Verify that an unencrypted props send can be received as an
+# encryption root
+# 8. Verify that an unencrypted recursive send can be received as an
+# encryption root
+# 9. Verify that an unencrypted props send can be received as an
+# encryption child
+# 10. Verify that an unencrypted recursive send can be received as an
+# encryption child
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/recv "-r"
+ destroy_dataset $TESTPOOL/crypt "-r"
+ destroy_dataset $TESTPOOL/ds "-r"
+ [[ -f $sendfile ]] && log_must rm $sendfile
+ [[ -f $keyfile ]] && log_must rm $keyfile
+}
+log_onexit cleanup
+
+log_assert "'zfs recv' must properly handle encryption properties"
+
+typeset keyfile=/$TESTPOOL/pkey
+typeset sendfile=/$TESTPOOL/sendfile
+typeset snap=$TESTPOOL/ds@snap1
+typeset snap2=$TESTPOOL/ds@snap2
+typeset esnap=$TESTPOOL/crypt@snap1
+typeset esnap2=$TESTPOOL/crypt@snap2
+
+log_must eval "echo 'password' > $keyfile"
+
+log_must zfs create $TESTPOOL/ds
+log_must zfs create $TESTPOOL/ds/ds1
+
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file://$keyfile $TESTPOOL/crypt
+log_must zfs create $TESTPOOL/crypt/ds1
+log_must zfs create -o keyformat=passphrase -o keylocation=file://$keyfile \
+ $TESTPOOL/crypt/ds2
+
+log_must mkfile 1M /$TESTPOOL/ds/$TESTFILE0
+log_must cp /$TESTPOOL/ds/$TESTFILE0 /$TESTPOOL/crypt/$TESTFILE0
+typeset cksum=$(md5digest /$TESTPOOL/ds/$TESTFILE0)
+
+log_must zfs snap -r $snap
+log_must zfs snap -r $snap2
+log_must zfs snap -r $esnap
+log_must zfs snap -r $esnap2
+
+# Embedded data is incompatible with encrypted datasets, so we cannot
+# allow embedded streams to be received.
+log_note "Must not be able to receive an embedded stream as encrypted"
+log_mustnot eval "zfs send -e $TESTPOOL/crypt/ds1 | zfs recv $TESTPOOL/recv"
+
+# We currently don't have an elegant and secure way to pass the passphrase
+# in via prompt because the send stream itself is using stdin.
+log_note "Must not be able to use 'keylocation=prompt' on receive"
+log_must eval "zfs send $snap > $sendfile"
+log_mustnot eval "zfs recv -o encryption=on -o keyformat=passphrase" \
+ "$TESTPOOL/recv < $sendfile"
+log_mustnot eval "zfs recv -o encryption=on -o keyformat=passphrase" \
+ "-o keylocation=prompt $TESTPOOL/recv < $sendfile"
+
+# Raw sends do not have access to the decrypted data so we cannot override
+# the encryption settings without losing the data.
+log_note "Must not be able to disable encryption properties on raw send"
+log_must eval "zfs send -w $esnap > $sendfile"
+log_mustnot eval "zfs recv -x encryption $TESTPOOL/recv < $sendfile"
+log_mustnot eval "zfs recv -x keyformat $TESTPOOL/recv < $sendfile"
+log_mustnot eval "zfs recv -x pbkdf2iters $TESTPOOL/recv < $sendfile"
+
+# Encryption properties are set upon creating the dataset. Changing them
+# afterwards requires using 'zfs change-key' or an update from a raw send.
+log_note "Must not be able to change encryption properties on incrementals"
+log_must eval "zfs send $esnap | zfs recv -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=file://$keyfile $TESTPOOL/recv"
+log_mustnot eval "zfs send -i $esnap $esnap2 |" \
+ "zfs recv -o encryption=aes-128-ccm $TESTPOOL/recv"
+log_mustnot eval "zfs send -i $esnap $esnap2 |" \
+ "zfs recv -o keyformat=hex $TESTPOOL/recv"
+log_mustnot eval "zfs send -i $esnap $esnap2 |" \
+ "zfs recv -o pbkdf2iters=100k $TESTPOOL/recv"
+log_must zfs destroy -r $TESTPOOL/recv
+
+# Test that we can receive a simple stream as an encryption root.
+log_note "Must be able to receive stream as encryption root"
+ds=$TESTPOOL/recv
+log_must eval "zfs send $snap > $sendfile"
+log_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
+ "-o keylocation=file://$keyfile $ds < $sendfile"
+log_must test "$(get_prop 'encryption' $ds)" == "aes-256-gcm"
+log_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
+log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
+log_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
+log_must test "$(get_prop 'mounted' $ds)" == "yes"
+recv_cksum=$(md5digest /$ds/$TESTFILE0)
+log_must test "$recv_cksum" == "$cksum"
+log_must zfs destroy -r $ds
+
+# Test that we can override encryption properties on a properties stream
+# of an unencrypted dataset, turning it into an encryption root.
+log_note "Must be able to receive stream with props as encryption root"
+ds=$TESTPOOL/recv
+log_must eval "zfs send -p $snap > $sendfile"
+log_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
+ "-o keylocation=file://$keyfile $ds < $sendfile"
+log_must test "$(get_prop 'encryption' $ds)" == "aes-256-gcm"
+log_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
+log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
+log_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
+log_must test "$(get_prop 'mounted' $ds)" == "yes"
+recv_cksum=$(md5digest /$ds/$TESTFILE0)
+log_must test "$recv_cksum" == "$cksum"
+log_must zfs destroy -r $ds
+
+# Test that we can override encryption properties on a recursive stream
+# of an unencrypted dataset, turning it into an encryption root. The root
+# dataset of the stream should become an encryption root with all children
+# inheriting from it.
+log_note "Must be able to receive recursive stream as encryption root"
+ds=$TESTPOOL/recv
+log_must eval "zfs send -R $snap > $sendfile"
+log_must eval "zfs recv -o encryption=on -o keyformat=passphrase" \
+ "-o keylocation=file://$keyfile $ds < $sendfile"
+log_must test "$(get_prop 'encryption' $ds)" == "aes-256-gcm"
+log_must test "$(get_prop 'encryptionroot' $ds)" == "$ds"
+log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
+log_must test "$(get_prop 'keylocation' $ds)" == "file://$keyfile"
+log_must test "$(get_prop 'mounted' $ds)" == "yes"
+recv_cksum=$(md5digest /$ds/$TESTFILE0)
+log_must test "$recv_cksum" == "$cksum"
+log_must zfs destroy -r $ds
+
+# Test that we can override an unencrypted properties stream's encryption
+# settings, receiving it as an encrypted child.
+log_note "Must be able to receive stream with props to encrypted child"
+ds=$TESTPOOL/crypt/recv
+log_must eval "zfs send -p $snap > $sendfile"
+log_must eval "zfs recv -x encryption $ds < $sendfile"
+log_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
+log_must test "$(get_prop 'encryption' $ds)" == "aes-256-gcm"
+log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
+log_must test "$(get_prop 'mounted' $ds)" == "yes"
+recv_cksum=$(md5digest /$ds/$TESTFILE0)
+log_must test "$recv_cksum" == "$cksum"
+log_must zfs destroy -r $ds
+
+# Test that we can override an unencrypted recursive stream's encryption
+# settings, receiving all datasets as encrypted children.
+log_note "Must be able to receive recursive stream to encrypted child"
+ds=$TESTPOOL/crypt/recv
+log_must eval "zfs send -R $snap > $sendfile"
+log_must eval "zfs recv -x encryption $ds < $sendfile"
+log_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
+log_must test "$(get_prop 'encryption' $ds)" == "aes-256-gcm"
+log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
+log_must test "$(get_prop 'mounted' $ds)" == "yes"
+recv_cksum=$(md5digest /$ds/$TESTFILE0)
+log_must test "$recv_cksum" == "$cksum"
+log_must zfs destroy -r $ds
+
+# Test that we can override an unencrypted, incremental, recursive stream's
+# encryption settings, receiving all datasets as encrypted children.
+log_note "Must be able to receive recursive stream to encrypted child"
+ds=$TESTPOOL/crypt/recv
+log_must eval "zfs send -R $snap2 > $sendfile"
+log_must eval "zfs recv -x encryption $ds < $sendfile"
+log_must test "$(get_prop 'encryptionroot' $ds)" == "$TESTPOOL/crypt"
+log_must test "$(get_prop 'encryption' $ds)" == "aes-256-gcm"
+log_must test "$(get_prop 'keyformat' $ds)" == "passphrase"
+log_must test "$(get_prop 'mounted' $ds)" == "yes"
+recv_cksum=$(md5digest /$ds/$TESTFILE0)
+log_must test "$recv_cksum" == "$cksum"
+log_must zfs destroy -r $ds
+
+# Check that we haven't printed the key to the zpool history log
+log_mustnot eval "zpool history -i | grep -q 'wkeydata'"
+
+log_pass "'zfs recv' properly handles encryption properties"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_encrypted_truncated_files.ksh b/tests/zfs-tests/tests/functional/rsend/send_encrypted_truncated_files.ksh
new file mode 100755
index 000000000000..c710b3d911e7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_encrypted_truncated_files.ksh
@@ -0,0 +1,126 @@
+#!/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) 2018 by Datto Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+#
+#
+# STRATEGY:
+# 1. Create a new encrypted filesystem
+# 2. Add a 4 files that are to be truncated later
+# 3. Take a snapshot of the filesystem
+# 4. Truncate one of the files from 32M to 128k
+# 5. Truncate one of the files from 512k to 384k
+# 6. Truncate one of the files from 512k to 0 to 384k via reallocation
+# 7. Truncate one of the files from 1k to 0 to 512b via reallocation
+# 8. Take another snapshot of the filesystem
+# 9. Send and receive both snapshots
+# 10. Mount the filesystem and check the contents
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+ datasetexists $TESTPOOL/recv && \
+ log_must zfs destroy -r $TESTPOOL/recv
+ [[ -f $keyfile ]] && log_must rm $keyfile
+ [[ -f $sendfile ]] && log_must rm $sendfile
+}
+log_onexit cleanup
+
+function recursive_cksum
+{
+ case "$(uname)" in
+ FreeBSD)
+ find $1 -type f -exec sha256 -q {} \; | \
+ sort | sha256digest
+ ;;
+ *)
+ find $1 -type f -exec sha256sum {} \; | \
+ sort -k 2 | awk '{ print $1 }' | sha256digest
+ ;;
+ esac
+}
+
+log_assert "Verify 'zfs send -w' works with many different file layouts"
+
+typeset keyfile=/$TESTPOOL/pkey
+typeset sendfile=/$TESTPOOL/sendfile
+typeset sendfile2=/$TESTPOOL/sendfile2
+
+# Create an encrypted dataset
+log_must eval "echo 'password' > $keyfile"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file://$keyfile $TESTPOOL/$TESTFS2
+
+# Explicitly set the recordsize since the truncation sizes below depend on
+# this value being 128k. This is currently same as the default recordsize.
+log_must zfs set recordsize=128k $TESTPOOL/$TESTFS2
+
+# Create files with varied layouts on disk
+log_must mkfile 32M /$TESTPOOL/$TESTFS2/truncated
+log_must mkfile 524288 /$TESTPOOL/$TESTFS2/truncated2
+log_must mkfile 524288 /$TESTPOOL/$TESTFS2/truncated3
+log_must mkfile 1024 /$TESTPOOL/$TESTFS2/truncated4
+
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snap1
+
+#
+# Truncate files created in the first snapshot. The first tests
+# truncating a large file to a single block. The second tests
+# truncating one block off the end of a file without changing
+# the required nlevels to hold it. The third tests handling
+# of a maxblkid that is dropped and then raised again. The
+# fourth tests an object that is truncated from a single block
+# to a smaller single block.
+#
+log_must truncate -s 131072 /$TESTPOOL/$TESTFS2/truncated
+log_must truncate -s 393216 /$TESTPOOL/$TESTFS2/truncated2
+log_must rm -f /$TESTPOOL/$TESTFS2/truncated3
+log_must rm -f /$TESTPOOL/$TESTFS2/truncated4
+log_must zpool sync $TESTPOOL
+log_must zfs umount $TESTPOOL/$TESTFS2
+log_must zfs mount $TESTPOOL/$TESTFS2
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS2/truncated3 \
+ bs=128k count=3 iflag=fullblock
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS2/truncated4 \
+ bs=512 count=1 iflag=fullblock
+
+log_must zfs snapshot $TESTPOOL/$TESTFS2@snap2
+expected_cksum=$(recursive_cksum /$TESTPOOL/$TESTFS2)
+
+log_must eval "zfs send -wp $TESTPOOL/$TESTFS2@snap1 > $sendfile"
+log_must eval "zfs send -wp -i @snap1 $TESTPOOL/$TESTFS2@snap2 > $sendfile2"
+
+log_must eval "zfs recv -F $TESTPOOL/recv < $sendfile"
+log_must eval "zfs recv -F $TESTPOOL/recv < $sendfile2"
+log_must zfs load-key $TESTPOOL/recv
+
+log_must zfs mount -a
+actual_cksum=$(recursive_cksum /$TESTPOOL/recv)
+[[ "$expected_cksum" != "$actual_cksum" ]] && \
+ log_fail "Recursive checksums differ ($expected_cksum != $actual_cksum)"
+
+log_pass "Verified 'zfs send -w' works with many different file layouts"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_freeobjects.ksh b/tests/zfs-tests/tests/functional/rsend/send_freeobjects.ksh
new file mode 100755
index 000000000000..6533352a9a14
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_freeobjects.ksh
@@ -0,0 +1,81 @@
+#!/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
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify FREEOBJECTS record frees sequential objects (See
+# https://github.com/zfsonlinux/zfs/issues/6694)
+#
+# Strategy:
+# 1. Create three files with sequential object numbers, f1 f2 and f3
+# 2. Delete f2
+# 3. Take snapshot A
+# 4. Delete f3
+# 5. Take snapshot B
+# 6. Receive a full send of A
+# 7. Receive an incremental send of B
+# 8. Fail test if f3 exists on received snapshot B
+#
+
+verify_runnable "both"
+
+log_assert "Verify FREEOBJECTS record frees sequential objects"
+
+sendds=sendfo
+recvds=recvfo
+f1=/$POOL/$sendds/f1
+f2=/$POOL/$sendds/f2
+f3=/$POOL/$sendds/f3
+
+#
+# We need to set xattr=sa and dnodesize=legacy to guarantee sequential
+# object numbers for this test. Otherwise, if we used directory-based
+# xattrs, SELinux extended attributes might consume intervening object
+# numbers.
+#
+log_must zfs create -o xattr=sa -o dnodesize=legacy $POOL/$sendds
+
+tries=100
+for ((i=0; i<$tries; i++)); do
+ touch $f1 $f2 $f3
+ o1=$(ls -li $f1 | awk '{print $1}')
+ o2=$(ls -li $f2 | awk '{print $1}')
+ o3=$(ls -li $f3 | awk '{print $1}')
+
+ if [[ $o2 -ne $(( $o1 + 1 )) ]] || [[ $o3 -ne $(( $o2 + 1 )) ]]; then
+ rm -f $f1 $f2 $f3
+ else
+ break
+ fi
+done
+
+if [[ $i -eq $tries ]]; then
+ log_fail "Failed to create three sequential objects"
+fi
+
+log_must rm $f2
+log_must zfs snap $POOL/$sendds@A
+log_must rm $f3
+log_must zfs snap $POOL/$sendds@B
+log_must eval "zfs send $POOL/$sendds@A | zfs recv $POOL/$recvds"
+log_must eval "zfs send -i $POOL/$sendds@A $POOL/$sendds@B |" \
+ "zfs recv $POOL/$recvds"
+log_mustnot zdb $POOL/$recvds@B $o3
+log_pass "Verify FREEOBJECTS record frees sequential objects"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_holds.ksh b/tests/zfs-tests/tests/functional/rsend/send_holds.ksh
new file mode 100755
index 000000000000..5dcf0e2a0a7a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_holds.ksh
@@ -0,0 +1,177 @@
+#!/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.
+# Copyright (c) 2018 Datto, Inc. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+. $STF_SUITE/tests/functional/cli_root/cli_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs send' can send dataset holds.
+# Verify 'zfs receive' can receive dataset holds.
+#
+# STRATEGY:
+# 1. Create a snapshot.
+# 2. Create a full send stream with the fs, including holds.
+# 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, including holds.
+# 6. Receive the incremental send stream and verify the data integrity.
+# 7. Verify the holds have been received as expected.
+# 8. Create an incremental snap with no holds, and send that with -h.
+# 9. Confirm the snapshot was received as expected.
+# 10. Create an incremental snapshot and place a hold on it.
+# 11. Receive the incremental stream with -h and verify holds skipped.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ eval "zfs holds $init_snap |grep -q hold1-1" &&
+ log_must zfs release hold1-1 $init_snap
+ eval "zfs holds $init_snap |grep -q hold1-2" &&
+ log_must zfs release hold1-2 $init_snap
+ eval "zfs holds $recv_snap |grep -q hold1-1" &&
+ log_must zfs release hold1-1 $recv_snap
+ eval "zfs holds $recv_snap |grep -q hold1-2" &&
+ log_must zfs release hold1-2 $recv_snap
+ eval "zfs holds $inc_snap |grep -q hold2-1" &&
+ log_must zfs release hold2-1 $inc_snap
+ eval "zfs holds $recv_inc_snap |grep -q hold2-1" &&
+ log_must zfs release hold2-1 $recv_inc_snap
+ eval "zfs holds $inc_snap3 |grep -q hold3-1" &&
+ log_must zfs release hold3-1 $inc_snap3
+
+ # destroy datasets
+ datasetexists $recv_root/$TESTFS1 &&
+ log_must destroy_dataset "$recv_root/$TESTFS1" "-Rf"
+ datasetexists $recv_root && log_must destroy_dataset "$recv_root" "-Rf"
+ datasetexists $TESTPOOL/$TESTFS1 && log_must destroy_dataset "$TESTPOOL/$TESTFS1" "-Rf"
+
+ [[ -e $full_bkup ]] && log_must rm -f $full_bkup
+ [[ -e $inc_bkup ]] && log_must rm -f $inc_bkup
+ [[ -e $inc_data2 ]] && log_must rm -f $inc_data2
+ [[ -d $TESTDIR1 ]] && log_must rm -rf $TESTDIR1
+
+}
+
+#
+# Check if hold exists on the specified dataset.
+#
+function check_hold #<snapshot> <hold>
+{
+ typeset dataset=$1
+ typeset hold=$2
+
+ log_note "checking $dataset for $hold"
+ eval "zfs holds $dataset |grep -q $hold"
+}
+
+log_assert "Verify 'zfs send/recv' can send and receive dataset holds."
+log_onexit cleanup
+
+init_snap=$TESTPOOL/$TESTFS1@init_snap
+inc_snap=$TESTPOOL/$TESTFS1@inc_snap
+inc_snap2=$TESTPOOL/$TESTFS1@inc_snap2
+inc_snap3=$TESTPOOL/$TESTFS1@inc_snap3
+full_bkup=$TEST_BASE_DIR/fullbkup.$$
+inc_bkup=$TEST_BASE_DIR/incbkup.$$
+init_data=$TESTDIR/$TESTFILE1
+inc_data=$TESTDIR/$TESTFILE2
+inc_data2=$TESTDIR/testfile3
+recv_root=$TESTPOOL/rst_ctr
+recv_snap=$recv_root/$TESTFS1@init_snap
+recv_inc_snap=$recv_root/$TESTFS1@inc_snap
+recv_inc_snap2=$recv_root/$TESTFS1@inc_snap2
+recv_inc_snap3=$recv_root/$TESTFS1@inc_snap3
+recv_data=$TESTDIR1/$TESTFS1/$TESTFILE1
+recv_inc_data=$TESTDIR1/$TESTFS1/$TESTFILE2
+recv_inc_data2=$TESTDIR1/$TESTFS1/testfile3
+
+log_note "Verify 'zfs send' can create full send stream."
+
+# Preparation
+if ! datasetexists $TESTPOOL/$TESTFS1; then
+ log_must zfs create $TESTPOOL/$TESTFS1
+fi
+[[ -e $init_data ]] && log_must rm -f $init_data
+log_must zfs create $recv_root
+[[ ! -d $TESTDIR1 ]] && log_must mkdir -p $TESTDIR1
+[[ ! -d $TESTDIR ]] && log_must mkdir -p $TESTDIR
+log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS1
+log_must zfs set mountpoint=$TESTDIR1 $recv_root
+
+file_write -o create -f $init_data -b $BLOCK_SIZE -c $WRITE_COUNT
+
+log_must zfs snapshot $init_snap
+log_must zfs hold hold1-1 $init_snap
+log_must zfs hold hold1-2 $init_snap
+log_must eval "zfs send -h $init_snap > $full_bkup"
+
+log_note "Verify the send stream is valid to receive."
+
+log_must zfs recv -F $recv_snap <$full_bkup
+log_must datasetexists $recv_snap
+receive_check $recv_snap ${recv_snap%%@*}
+
+log_note "Verify the holds were received."
+log_must check_hold $recv_snap hold1-1
+log_must check_hold $recv_snap hold1-2
+compare_cksum $init_data $recv_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
+log_must zfs hold hold2-1 $inc_snap
+log_must eval "zfs send -h -i $init_snap $inc_snap > $inc_bkup"
+
+log_note "Verify the incremental send stream is valid to receive."
+
+log_must zfs recv -F $recv_inc_snap <$inc_bkup
+log_must datasetexists $recv_inc_snap
+log_note "Verify the hold was received from the incremental send."
+
+log_must check_hold $recv_inc_snap hold2-1
+
+compare_cksum $inc_data $recv_inc_data
+
+log_note "Verify send -h works when there are no holds."
+file_write -o create -f $inc_data2 -b $BLOCK_SIZE -c $WRITE_COUNT -d 0
+log_must zfs snapshot $inc_snap2
+log_must eval "zfs send -h -i $inc_snap $inc_snap2 > $inc_bkup"
+log_must zfs recv -F $recv_inc_snap2 <$inc_bkup
+log_must datasetexists $recv_inc_snap2
+compare_cksum $inc_data2 $recv_inc_data2
+
+log_note "Verify send -h fails properly when receive dataset already exists"
+log_must zfs recv -F $recv_inc_snap2 <$inc_bkup
+
+log_note "Verify recv -h skips the receive of holds"
+log_must zfs snapshot $inc_snap3
+log_must zfs hold hold3-1 $inc_snap3
+log_must eval "zfs send -h -i $inc_snap2 $inc_snap3 > $inc_bkup"
+log_must zfs recv -F -h $recv_inc_snap3 <$inc_bkup
+log_must datasetexists $recv_inc_snap3
+log_mustnot check_hold $recv_inc_snap3 hold3-1
+
+log_pass "'zfs send/recv' can send and receive dataset holds."
diff --git a/tests/zfs-tests/tests/functional/rsend/send_hole_birth.ksh b/tests/zfs-tests/tests/functional/rsend/send_hole_birth.ksh
new file mode 100755
index 000000000000..1dfa97e77358
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_hole_birth.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# DESCRIPTION:
+# Verify send streams which contain holes.
+#
+# STRATEGY:
+# 1. Create an initial file for the full send and snapshot.
+# 2. Permute the file with holes and snapshot.
+# 3. Send the full and incremental snapshots to a new pool.
+# 4. Verify the contents of the files match.
+#
+
+sendpool=$POOL
+sendfs=$sendpool/sendfs
+
+recvpool=$POOL2
+recvfs=$recvpool/recvfs
+
+verify_runnable "both"
+
+log_assert "Test hole_birth"
+log_onexit cleanup
+
+function cleanup
+{
+ cleanup_pool $sendpool
+ cleanup_pool $recvpool
+ set_tunable64 SEND_HOLES_WITHOUT_BIRTH_TIME 1
+}
+
+function send_and_verify
+{
+ log_must eval "zfs send $sendfs@snap1 > $BACKDIR/pool-snap1"
+ log_must eval "zfs receive -F $recvfs < $BACKDIR/pool-snap1"
+
+ log_must eval "zfs send -i $sendfs@snap1 $sendfs@snap2 " \
+ ">$BACKDIR/pool-snap1-snap2"
+ log_must eval "zfs receive $recvfs < $BACKDIR/pool-snap1-snap2"
+
+ log_must cmp_md5s /$sendfs/file1 /$recvfs/file1
+}
+
+# By default sending hole_birth times is disabled. This functionality needs
+# to be re-enabled for this test case to verify correctness. Once we're
+# comfortable that all hole_birth bugs has been resolved this behavior may
+# be re-enabled by default.
+log_must set_tunable64 SEND_HOLES_WITHOUT_BIRTH_TIME 0
+
+# Incremental send truncating the file and adding new data.
+log_must zfs create -o recordsize=4k $sendfs
+
+log_must truncate -s 1G /$sendfs/file1
+log_must dd if=/dev/urandom of=/$sendfs/file1 bs=4k count=11264 seek=1152
+log_must zfs snapshot $sendfs@snap1
+
+log_must truncate -s 4M /$sendfs/file1
+log_must dd if=/dev/urandom of=/$sendfs/file1 bs=4k count=152 seek=384 \
+ conv=notrunc
+log_must dd if=/dev/urandom of=/$sendfs/file1 bs=4k count=10 seek=1408 \
+ conv=notrunc
+log_must zfs snapshot $sendfs@snap2
+
+send_and_verify
+log_must cleanup_pool $sendpool
+log_must cleanup_pool $recvpool
+
+# Incremental send appending a hole and data.
+log_must zfs create -o recordsize=512 $sendfs
+
+log_must dd if=/dev/urandom of=/$sendfs/file1 bs=128k count=1 seek=1
+log_must zfs snapshot $sendfs@snap1
+
+log_must dd if=/dev/urandom of=/$sendfs/file1 bs=128k count=1
+log_must dd if=/dev/urandom of=/$sendfs/file1 bs=128k count=1 seek=3
+log_must zfs snapshot $sendfs@snap2
+
+send_and_verify
+log_must cleanup_pool $sendpool
+log_must cleanup_pool $recvpool
+
+# Incremental send truncating the file and adding new data.
+log_must zfs create -o recordsize=512 $sendfs
+
+log_must truncate -s 300M /$sendfs/file1
+log_must dd if=/dev/urandom of=/$sendfs/file1 bs=512 count=128k conv=notrunc
+log_must zfs snapshot $sendfs@snap1
+
+log_must truncate -s 10M /$sendfs/file1
+log_must dd if=/dev/urandom of=/$sendfs/file1 bs=512 count=1 seek=96k \
+ conv=notrunc
+log_must zfs snapshot $sendfs@snap2
+
+send_and_verify
+
+log_pass "Test hole_birth"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_mixed_raw.ksh b/tests/zfs-tests/tests/functional/rsend/send_mixed_raw.ksh
new file mode 100755
index 000000000000..eea535af1100
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_mixed_raw.ksh
@@ -0,0 +1,118 @@
+#!/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:
+# Verify that 'zfs receive' produces an error when mixing
+# raw and non-raw sends in a way that would break IV set
+# consistency.
+#
+# STRATEGY:
+# 1. Create an initial dataset with 3 snapshots.
+# 2. Perform a raw send of the first snapshot to 2 other datasets.
+# 3. Perform a non-raw send of the second snapshot to one of
+# the other datasets. Perform a raw send from this dataset to
+# the last one.
+# 4. Attempt to raw send the final snapshot of the first dataset
+# to the other 2 datasets, which should fail.
+# 5. Repeat steps 1-4, but using bookmarks for incremental sends.
+#
+#
+# A B C notes
+# ------------------------------------------------------------------------------
+# snap1 ---raw---> snap1 --raw--> snap1 # all snaps initialized via raw send
+# snap2 -non-raw-> snap2 --raw--> snap2 # A sends non-raw to B, B sends raw to C
+# snap3 ------------raw---------> snap3 # attempt send to C (should fail)
+#
+
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$TESTFS3 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS3
+ datasetexists $TESTPOOL/$TESTFS2 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS2
+ datasetexists $TESTPOOL/$TESTFS1 && \
+ log_must zfs destroy -r $TESTPOOL/$TESTFS1
+}
+log_onexit cleanup
+
+log_assert "Mixing raw and non-raw receives should fail"
+
+typeset passphrase="password"
+
+log_must eval "echo $passphrase | zfs create -o encryption=on" \
+ "-o keyformat=passphrase $TESTPOOL/$TESTFS1"
+
+log_must zfs snapshot $TESTPOOL/$TESTFS1@1
+log_must touch /$TESTPOOL/$TESTFS1/a
+log_must zfs snapshot $TESTPOOL/$TESTFS1@2
+log_must touch /$TESTPOOL/$TESTFS1/b
+log_must zfs snapshot $TESTPOOL/$TESTFS1@3
+
+# Testing with snapshots
+log_must eval "zfs send -w $TESTPOOL/$TESTFS1@1 |" \
+ "zfs receive $TESTPOOL/$TESTFS2"
+log_must eval "echo $passphrase | zfs load-key $TESTPOOL/$TESTFS2"
+log_must eval "zfs send -w $TESTPOOL/$TESTFS2@1 |" \
+ "zfs receive $TESTPOOL/$TESTFS3"
+log_must eval "echo $passphrase | zfs load-key $TESTPOOL/$TESTFS3"
+
+log_must eval "zfs send -i $TESTPOOL/$TESTFS1@1 $TESTPOOL/$TESTFS1@2 |" \
+ "zfs receive $TESTPOOL/$TESTFS2"
+log_must eval "zfs send -w -i $TESTPOOL/$TESTFS2@1 $TESTPOOL/$TESTFS2@2 |" \
+ "zfs receive $TESTPOOL/$TESTFS3"
+
+log_mustnot eval "zfs send -w -i $TESTPOOL/$TESTFS1@2 $TESTPOOL/$TESTFS1@3 |" \
+ "zfs receive $TESTPOOL/$TESTFS2"
+log_mustnot eval "zfs send -w -i $TESTPOOL/$TESTFS2@2 $TESTPOOL/$TESTFS2@3 |" \
+ "zfs receive $TESTPOOL/$TESTFS3"
+
+log_must zfs destroy -r $TESTPOOL/$TESTFS3
+log_must zfs destroy -r $TESTPOOL/$TESTFS2
+
+# Testing with bookmarks
+log_must zfs bookmark $TESTPOOL/$TESTFS1@1 $TESTPOOL/$TESTFS1#b1
+log_must zfs bookmark $TESTPOOL/$TESTFS1@2 $TESTPOOL/$TESTFS1#b2
+
+log_must eval "zfs send -w $TESTPOOL/$TESTFS1@1 |" \
+ "zfs receive $TESTPOOL/$TESTFS2"
+log_must eval "echo $passphrase | zfs load-key $TESTPOOL/$TESTFS2"
+
+log_must zfs bookmark $TESTPOOL/$TESTFS2@1 $TESTPOOL/$TESTFS2#b1
+
+log_must eval "zfs send -w $TESTPOOL/$TESTFS2@1 |" \
+ "zfs receive $TESTPOOL/$TESTFS3"
+log_must eval "echo $passphrase | zfs load-key $TESTPOOL/$TESTFS3"
+
+log_must eval "zfs send -i $TESTPOOL/$TESTFS1#b1 $TESTPOOL/$TESTFS1@2 |" \
+ "zfs receive $TESTPOOL/$TESTFS2"
+log_must eval "zfs send -w -i $TESTPOOL/$TESTFS2#b1 $TESTPOOL/$TESTFS2@2 |" \
+ "zfs receive $TESTPOOL/$TESTFS3"
+
+log_mustnot eval "zfs send -w -i $TESTPOOL/$TESTFS1#b2" \
+ "$TESTPOOL/$TESTFS1@3 | zfs receive $TESTPOOL/$TESTFS2"
+log_mustnot eval "zfs send -w -i $TESTPOOL/$TESTFS2#b2" \
+ "$TESTPOOL/$TESTFS2@3 | zfs receive $TESTPOOL/$TESTFS3"
+
+log_pass "Mixing raw and non-raw receives fail as expected"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_partial_dataset.ksh b/tests/zfs-tests/tests/functional/rsend/send_partial_dataset.ksh
new file mode 100755
index 000000000000..d5eb9a0edc11
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_partial_dataset.ksh
@@ -0,0 +1,110 @@
+#!/bin/ksh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version a.0.
+# You may only use this file in accordance with the terms of version
+# a.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 Datto Inc.
+# Copyright (c) 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify that a partially received dataset can be sent with
+# 'zfs send --saved'.
+#
+# Strategy:
+# 1. Setup a pool with partially received filesystem
+# 2. Perform saved send without incremental
+# 3. Perform saved send with incremental
+# 4. Perform saved send with incremental, resuming from a token
+# 5. Perform negative tests for invalid command inputs
+#
+
+verify_runnable "both"
+
+log_assert "Verify that a partially received dataset can be sent with " \
+ "'zfs send --saved'."
+
+function cleanup
+{
+ destroy_dataset $POOL/testfs2 "-r"
+ destroy_dataset $POOL/stream "-r"
+ destroy_dataset $POOL/recvfs "-r"
+ destroy_dataset $POOL/partialfs "-r"
+}
+log_onexit cleanup
+
+log_must zfs create $POOL/testfs2
+log_must zfs create $POOL/stream
+mntpnt=$(get_prop mountpoint $POOL/testfs2)
+
+# Setup a pool with partially received filesystems
+log_must mkfile 1m $mntpnt/filea
+log_must zfs snap $POOL/testfs2@a
+log_must mkfile 1m $mntpnt/fileb
+log_must zfs snap $POOL/testfs2@b
+log_must eval "zfs send $POOL/testfs2@a | zfs recv $POOL/recvfs"
+log_must eval "zfs send -i $POOL/testfs2@a $POOL/testfs2@b > " \
+ "/$POOL/stream/inc.send"
+log_must eval "zfs send $POOL/testfs2@b > /$POOL/stream/full.send"
+mess_send_file /$POOL/stream/full.send
+mess_send_file /$POOL/stream/inc.send
+log_mustnot zfs recv -s $POOL/recvfullfs < /$POOL/stream/full.send
+log_mustnot zfs recv -s $POOL/recvfs < /$POOL/stream/inc.send
+
+# Perform saved send without incremental
+log_mustnot eval "zfs send --saved $POOL/recvfullfs | zfs recv -s " \
+ "$POOL/partialfs"
+token=$(zfs get -Hp -o value receive_resume_token $POOL/partialfs)
+log_must eval "zfs send -t $token | zfs recv -s $POOL/partialfs"
+file_check $POOL/recvfullfs $POOL/partialfs
+log_must zfs destroy -r $POOL/partialfs
+
+# Perform saved send with incremental
+log_must eval "zfs send $POOL/recvfs@a | zfs recv $POOL/partialfs"
+log_mustnot eval "zfs send --saved $POOL/recvfs | " \
+ "zfs recv -s $POOL/partialfs"
+token=$(zfs get -Hp -o value receive_resume_token $POOL/partialfs)
+log_must eval "zfs send -t $token | zfs recv -s $POOL/partialfs"
+file_check $POOL/recvfs $POOL/partialfs
+log_must zfs destroy -r $POOL/partialfs
+
+# Perform saved send with incremental, resuming from token
+log_must eval "zfs send $POOL/recvfs@a | zfs recv $POOL/partialfs"
+log_must eval "zfs send --saved $POOL/recvfs > " \
+ "/$POOL/stream/partial.send"
+mess_send_file /$POOL/stream/partial.send
+log_mustnot zfs recv -s $POOL/partialfs < /$POOL/stream/partial.send
+token=$(zfs get -Hp -o value receive_resume_token $POOL/partialfs)
+log_must eval "zfs send -t $token | zfs recv -s $POOL/partialfs"
+file_check $POOL/recvfs $POOL/partialfs
+
+# Perform negative tests for invalid command inputs
+set -A badargs \
+ "" \
+ "$POOL/recvfs@a" \
+ "-i $POOL/recvfs@a $POOL/recvfs@b" \
+ "-R $POOL/recvfs" \
+ "-p $POOL/recvfs" \
+ "-I $POOL/recvfs" \
+ "-h $POOL/recvfs"
+
+while (( i < ${#badargs[*]} ))
+do
+ log_mustnot eval "zfs send --saved ${badargs[i]} >/dev/null"
+ (( i = i + 1 ))
+done
+
+log_pass "A partially received dataset can be sent with 'zfs send --saved'."
diff --git a/tests/zfs-tests/tests/functional/rsend/send_realloc_dnode_size.ksh b/tests/zfs-tests/tests/functional/rsend/send_realloc_dnode_size.ksh
new file mode 100755
index 000000000000..394fe95bb9b7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_realloc_dnode_size.ksh
@@ -0,0 +1,112 @@
+#!/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) 2018 Datto Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify incremental receive properly handles objects with changed
+# dnode slot count.
+#
+# Strategy:
+# 1. Populate a dataset with 1k byte dnodes and snapshot
+# 2. Remove objects, set dnodesize=legacy, and remount dataset so new objects
+# get recycled numbers and formerly "interior" dnode slots get assigned
+# to new objects
+# 3. Remove objects, set dnodesize=2k, and remount dataset so new objects
+# overlap with recently recycled and formerly "normal" dnode slots get
+# assigned to new objects
+# 4. Create an empty file and add xattrs to it to exercise reclaiming a
+# dnode that requires more than 1 slot for its bonus buffer (Zol #7433)
+# 5. Generate initial and incremental streams
+# 6. Verify initial and incremental streams can be received
+#
+
+verify_runnable "both"
+
+log_assert "Verify incremental receive handles objects with changed dnode size"
+
+function cleanup
+{
+ rm -f $BACKDIR/fs-dn-legacy
+ rm -f $BACKDIR/fs-dn-1k
+ rm -f $BACKDIR/fs-dn-2k
+ rm -f $BACKDIR/fs-attr
+
+ if datasetexists $POOL/fs ; then
+ log_must zfs destroy -rR $POOL/fs
+ fi
+
+ if datasetexists $POOL/newfs ; then
+ log_must zfs destroy -rR $POOL/newfs
+ fi
+}
+
+log_onexit cleanup
+
+# 1. Populate a dataset with 1k byte dnodes and snapshot
+log_must zfs create -o dnodesize=1k $POOL/fs
+log_must mk_files 200 262144 0 $POOL/fs
+log_must zfs snapshot $POOL/fs@a
+
+# 2. Remove objects, set dnodesize=legacy, and remount dataset so new objects
+# get recycled numbers and formerly "interior" dnode slots get assigned
+# to new objects
+rm /$POOL/fs/*
+
+log_must zfs unmount $POOL/fs
+log_must zfs set dnodesize=legacy $POOL/fs
+log_must zfs mount $POOL/fs
+
+log_must mk_files 200 262144 0 $POOL/fs
+log_must zfs snapshot $POOL/fs@b
+
+# 3. Remove objects, set dnodesize=2k, and remount dataset so new objects
+# overlap with recently recycled and formerly "normal" dnode slots get
+# assigned to new objects
+rm /$POOL/fs/*
+
+log_must zfs unmount $POOL/fs
+log_must zfs set dnodesize=2k $POOL/fs
+log_must zfs mount $POOL/fs
+
+log_must touch /$POOL/fs/attrs
+mk_files 200 262144 0 $POOL/fs
+log_must zfs snapshot $POOL/fs@c
+
+# 4. Create an empty file and add xattrs to it to exercise reclaiming a
+# dnode that requires more than 1 slot for its bonus buffer (Zol #7433)
+log_must zfs set compression=on xattr=sa $POOL/fs
+log_must eval "python -c 'print \"a\" * 512' |
+ set_xattr_stdin bigval /$POOL/fs/attrs"
+log_must zfs snapshot $POOL/fs@d
+
+# 5. Generate initial and incremental streams
+log_must eval "zfs send $POOL/fs@a > $BACKDIR/fs-dn-1k"
+log_must eval "zfs send -i $POOL/fs@a $POOL/fs@b > $BACKDIR/fs-dn-legacy"
+log_must eval "zfs send -i $POOL/fs@b $POOL/fs@c > $BACKDIR/fs-dn-2k"
+log_must eval "zfs send -i $POOL/fs@c $POOL/fs@d > $BACKDIR/fs-attr"
+
+# 6. Verify initial and incremental streams can be received
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs-dn-1k"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs-dn-legacy"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs-dn-2k"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs-attr"
+
+log_pass "Verify incremental receive handles objects with changed dnode size"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_realloc_encrypted_files.ksh b/tests/zfs-tests/tests/functional/rsend/send_realloc_encrypted_files.ksh
new file mode 100755
index 000000000000..a653f8b3f15e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_realloc_encrypted_files.ksh
@@ -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) 2019, Lawrence Livermore National Security LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify encrypted raw incremental receives handle dnode reallocation.
+
+# Strategy:
+# 1. Create a pool containing an encrypted filesystem.
+# 2. Use 'zfs send -wp' to perform a raw send of the initial filesystem.
+# 3. Repeat the following steps N times to verify raw incremental receives.
+# a) Randomly change several key dataset properties.
+# b) Modify the contents of the filesystem such that dnode reallocation
+# is likely during the 'zfs receive', and receive_object() exercises
+# as much of its functionality as possible.
+# c) Create a new snapshot and generate an raw incremental stream.
+# d) Receive the raw incremental stream and verify the received contents.
+# e) Destroy the incremental stream and old snapshot.
+#
+
+verify_runnable "both"
+
+log_assert "Verify encrypted raw incremental receive handles reallocation"
+
+function cleanup
+{
+ rm -f $BACKDIR/fs@*
+ rm -f $keyfile
+ destroy_dataset $POOL/fs "-rR"
+ destroy_dataset $POOL/newfs "-rR"
+}
+
+log_onexit cleanup
+
+typeset keyfile=/$TESTPOOL/pkey
+
+# Create an encrypted dataset
+log_must eval "echo 'password' > $keyfile"
+log_must zfs create -o encryption=on -o keyformat=passphrase \
+ -o keylocation=file://$keyfile $POOL/fs
+
+last_snap=1
+log_must zfs snapshot $POOL/fs@snap${last_snap}
+log_must eval "zfs send -wp $POOL/fs@snap${last_snap} \
+ >$BACKDIR/fs@snap${last_snap}"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap${last_snap}"
+
+# Set atime=off to prevent the recursive_cksum from modifying newfs.
+log_must zfs set atime=off $POOL/newfs
+
+if is_kmemleak; then
+ # Use fewer files and passes on debug kernels
+ # to avoid timeout due to reduced performance.
+ nr_files=100
+ passes=2
+elif is_freebsd; then
+ # Use fewer files and passes on FreeBSD to avoid timeout.
+ nr_files=500
+ passes=2
+else
+ nr_files=1000
+ passes=3
+fi
+
+for i in {1..$passes}; do
+ # Randomly modify several dataset properties in order to generate
+ # more interesting incremental send streams.
+ rand_set_prop $POOL/fs checksum "off" "fletcher4" "sha256"
+ rand_set_prop $POOL/fs compression "${compress_prop_vals[@]}"
+ rand_set_prop $POOL/fs recordsize "32K" "128K"
+ rand_set_prop $POOL/fs dnodesize "legacy" "auto" "4k"
+ rand_set_prop $POOL/fs xattr "on" "sa"
+
+ # Churn the filesystem in such a way that we're likely to be both
+ # allocating and reallocating objects in the incremental stream.
+ log_must churn_files $nr_files 524288 $POOL/fs
+ expected_cksum=$(recursive_cksum /$POOL/fs)
+
+ # Create a snapshot and use it to send an incremental stream.
+ this_snap=$((last_snap + 1))
+ log_must zfs snapshot $POOL/fs@snap${this_snap}
+ log_must eval "zfs send -wp -i $POOL/fs@snap${last_snap} \
+ $POOL/fs@snap${this_snap} > $BACKDIR/fs@snap${this_snap}"
+
+ # Receive the incremental stream and verify the received contents.
+ log_must eval "zfs recv -Fu $POOL/newfs < $BACKDIR/fs@snap${this_snap}"
+
+ log_must zfs load-key $POOL/newfs
+ log_must zfs mount $POOL/newfs
+ actual_cksum=$(recursive_cksum /$POOL/newfs)
+ log_must zfs umount $POOL/newfs
+ log_must zfs unload-key $POOL/newfs
+
+ if [[ "$expected_cksum" != "$actual_cksum" ]]; then
+ log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
+ fi
+
+ # Destroy the incremental stream and old snapshot.
+ rm -f $BACKDIR/fs@snap${last_snap}
+ log_must zfs destroy $POOL/fs@snap${last_snap}
+ log_must zfs destroy $POOL/newfs@snap${last_snap}
+ last_snap=$this_snap
+done
+
+log_pass "Verify encrypted raw incremental receive handles reallocation"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_realloc_files.ksh b/tests/zfs-tests/tests/functional/rsend/send_realloc_files.ksh
new file mode 100755
index 000000000000..083a2bec9daa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_realloc_files.ksh
@@ -0,0 +1,111 @@
+#!/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 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/properties.shlib
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify incremental receive properly handles reallocation.
+#
+# Strategy:
+# 1. Create a pool containing an encrypted filesystem.
+# 2. Use 'zfs send -wp' to perform a raw send of the initial filesystem.
+# 3. Repeat the following steps N times to verify raw incremental receives.
+# a) Randomly change several key dataset properties.
+# b) Modify the contents of the filesystem such that dnode reallocation
+# is likely during the 'zfs receive', and receive_object() exercises
+# as much of its functionality as possible.
+# c) Create a new snapshot and generate an raw incremental stream.
+# d) Receive the raw incremental stream and verify the received contents.
+# e) Destroy the incremental stream and old snapshot.
+#
+
+verify_runnable "both"
+
+log_assert "Verify incremental receive handles reallocation"
+
+function cleanup
+{
+ rm -f $BACKDIR/fs@*
+ destroy_dataset $POOL/fs "-rR"
+ destroy_dataset $POOL/newfs "-rR"
+}
+
+log_onexit cleanup
+
+log_must zfs create $POOL/fs
+
+last_snap=1
+log_must zfs snapshot $POOL/fs@snap${last_snap}
+log_must eval "zfs send $POOL/fs@snap${last_snap} >$BACKDIR/fs@snap${last_snap}"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap${last_snap}"
+
+# Set atime=off to prevent the recursive_cksum from modifying newfs.
+log_must zfs set atime=off $POOL/newfs
+
+if is_kmemleak; then
+ # Use fewer files and passes on debug kernels
+ # to avoid timeout due to reduced performance.
+ nr_files=100
+ passes=2
+elif is_freebsd; then
+ # Use fewer passes and files on FreeBSD to avoid timeout.
+ nr_files=500
+ passes=2
+else
+ nr_files=1000
+ passes=3
+fi
+
+for i in {1..$passes}; do
+ # Randomly modify several dataset properties in order to generate
+ # more interesting incremental send streams.
+ rand_set_prop $POOL/fs checksum "off" "fletcher4" "sha256"
+ rand_set_prop $POOL/fs compression "${compress_prop_vals[@]}"
+ rand_set_prop $POOL/fs recordsize "32K" "128K"
+ rand_set_prop $POOL/fs dnodesize "legacy" "auto" "4k"
+ rand_set_prop $POOL/fs xattr "on" "sa"
+
+ # Churn the filesystem in such a way that we're likely to be both
+ # allocating and reallocating objects in the incremental stream.
+ log_must churn_files $nr_files 524288 $POOL/fs
+ expected_cksum=$(recursive_cksum /$POOL/fs)
+
+ # Create a snapshot and use it to send an incremental stream.
+ this_snap=$((last_snap + 1))
+ log_must zfs snapshot $POOL/fs@snap${this_snap}
+ log_must eval "zfs send -i $POOL/fs@snap${last_snap} \
+ $POOL/fs@snap${this_snap} > $BACKDIR/fs@snap${this_snap}"
+
+ # Receive the incremental stream and verify the received contents.
+ log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap${this_snap}"
+ actual_cksum=$(recursive_cksum /$POOL/newfs)
+
+ if [[ "$expected_cksum" != "$actual_cksum" ]]; then
+ log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
+ fi
+
+ # Destroy the incremental stream and old snapshot.
+ rm -f $BACKDIR/fs@snap${last_snap}
+ log_must zfs destroy $POOL/fs@snap${last_snap}
+ log_must zfs destroy $POOL/newfs@snap${last_snap}
+ last_snap=$this_snap
+done
+
+log_pass "Verify incremental receive handles dnode reallocation"
diff --git a/tests/zfs-tests/tests/functional/rsend/send_spill_block.ksh b/tests/zfs-tests/tests/functional/rsend/send_spill_block.ksh
new file mode 100755
index 000000000000..73f164852f91
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/send_spill_block.ksh
@@ -0,0 +1,155 @@
+#!/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 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+#
+# Description:
+# Verify spill blocks are correctly preserved.
+#
+# Strategy:
+# 1) Create a set of files each containing some file data.
+# 2) Add enough xattrs to the file to require a spill block.
+# 3) Snapshot and send these files to a new dataset.
+# 4) Modify the files and spill blocks in a variety of ways.
+# 5) Send the changes using an incremental send stream.
+# 6) Verify that all the xattrs (and thus the spill block) were
+# preserved when receiving the incremental stream.
+#
+
+verify_runnable "both"
+
+log_assert "Verify spill blocks are correctly preserved"
+
+function cleanup
+{
+ rm -f $BACKDIR/fs@*
+ destroy_dataset $POOL/fs "-rR"
+ destroy_dataset $POOL/newfs "-rR"
+}
+
+attrvalue="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
+
+log_onexit cleanup
+
+log_must zfs create $POOL/fs
+log_must zfs set xattr=sa $POOL/fs
+log_must zfs set dnodesize=legacy $POOL/fs
+log_must zfs set recordsize=128k $POOL/fs
+
+# Create 40 files each with a spill block containing xattrs. Each file
+# will be modified in a different way to validate the incremental receive.
+for i in {1..40}; do
+ file="/$POOL/fs/file$i"
+
+ log_must mkfile 16384 $file
+ for j in {1..20}; do
+ log_must set_xattr "testattr$j" "$attrvalue" $file
+ done
+done
+
+# Snapshot the pool and send it to the new dataset.
+log_must zfs snapshot $POOL/fs@snap1
+log_must eval "zfs send -e $POOL/fs@snap1 >$BACKDIR/fs@snap1"
+log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap1"
+
+#
+# Modify file[1-6]'s contents but not the spill blocks.
+#
+# file1 - Increase record size; single block
+# file2 - Increase record size; multiple blocks
+# file3 - Truncate file to zero size; single block
+# file4 - Truncate file to smaller size; single block
+# file5 - Truncate file to much larger size; add holes
+# file6 - Truncate file to embedded size; embedded data
+#
+log_must mkfile 32768 /$POOL/fs/file1
+log_must mkfile 1048576 /$POOL/fs/file2
+log_must truncate -s 0 /$POOL/fs/file3
+log_must truncate -s 8192 /$POOL/fs/file4
+log_must truncate -s 1073741824 /$POOL/fs/file5
+log_must truncate -s 50 /$POOL/fs/file6
+
+#
+# Modify file[11-16]'s contents and their spill blocks.
+#
+# file11 - Increase record size; single block
+# file12 - Increase record size; multiple blocks
+# file13 - Truncate file to zero size; single block
+# file14 - Truncate file to smaller size; single block
+# file15 - Truncate file to much larger size; add holes
+# file16 - Truncate file to embedded size; embedded data
+#
+log_must mkfile 32768 /$POOL/fs/file11
+log_must mkfile 1048576 /$POOL/fs/file12
+log_must truncate -s 0 /$POOL/fs/file13
+log_must truncate -s 8192 /$POOL/fs/file14
+log_must truncate -s 1073741824 /$POOL/fs/file15
+log_must truncate -s 50 /$POOL/fs/file16
+
+for i in {11..20}; do
+ log_must rm_xattr testattr1 /$POOL/fs/file$i
+done
+
+#
+# Modify file[21-26]'s contents and remove their spill blocks.
+#
+# file21 - Increase record size; single block
+# file22 - Increase record size; multiple blocks
+# file23 - Truncate file to zero size; single block
+# file24 - Truncate file to smaller size; single block
+# file25 - Truncate file to much larger size; add holes
+# file26 - Truncate file to embedded size; embedded data
+#
+log_must mkfile 32768 /$POOL/fs/file21
+log_must mkfile 1048576 /$POOL/fs/file22
+log_must truncate -s 0 /$POOL/fs/file23
+log_must truncate -s 8192 /$POOL/fs/file24
+log_must truncate -s 1073741824 /$POOL/fs/file25
+log_must truncate -s 50 /$POOL/fs/file26
+
+for i in {21..30}; do
+ for j in {1..20}; do
+ log_must rm_xattr testattr$j /$POOL/fs/file$i
+ done
+done
+
+#
+# Modify file[31-40]'s spill blocks but not the file contents.
+#
+for i in {31..40}; do
+ file="/$POOL/fs/file$i"
+ log_must rm_xattr testattr$(((RANDOM % 20) + 1)) $file
+ log_must set_xattr testattr$(((RANDOM % 20) + 1)) "$attrvalue" $file
+done
+
+# Calculate the expected recursive checksum for the source.
+expected_cksum=$(recursive_cksum /$POOL/fs)
+
+# Snapshot the pool and send the incremental snapshot.
+log_must zfs snapshot $POOL/fs@snap2
+log_must eval "zfs send -e -i $POOL/fs@snap1 $POOL/fs@snap2 >$BACKDIR/fs@snap2"
+log_must eval "zfs recv -F $POOL/newfs < $BACKDIR/fs@snap2"
+
+# Validate the received copy using the received recursive checksum.
+actual_cksum=$(recursive_cksum /$POOL/newfs)
+if [[ "$expected_cksum" != "$actual_cksum" ]]; then
+ log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
+fi
+
+log_pass "Verify spill blocks are correctly preserved"
diff --git a/tests/zfs-tests/tests/functional/rsend/setup.ksh b/tests/zfs-tests/tests/functional/rsend/setup.ksh
new file mode 100755
index 000000000000..dbf4eecede88
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/rsend/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.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/rsend/rsend.kshlib
+
+verify_runnable "both"
+verify_disk_count "$DISKS" 2
+
+if is_global_zone ; then
+ log_must zpool create $POOL $DISK1
+ log_must zpool create $POOL2 $DISK2
+ log_must zpool create $POOL3 $DISK3
+fi
+log_must mkdir $BACKDIR $TESTDIR
+
+log_must setup_test_model $POOL
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/Makefile.am b/tests/zfs-tests/tests/functional/scrub_mirror/Makefile.am
new file mode 100644
index 000000000000..bc657fbf2ad9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/scrub_mirror
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ scrub_mirror_001_pos.ksh \
+ scrub_mirror_002_pos.ksh \
+ scrub_mirror_003_pos.ksh \
+ scrub_mirror_004_pos.ksh
+
+dist_pkgdata_DATA = \
+ default.cfg \
+ scrub_mirror_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/cleanup.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/cleanup.ksh
new file mode 100755
index 000000000000..92e58996ab62
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/cleanup.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.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/scrub_mirror/default.cfg
+
+
+verify_runnable "global"
+
+destroy_pool $TESTPOOL
+log_must rm -f $SIDE_PRIMARY $SIDE_SECONDARY
+log_must rmdir $SIDE_DIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/default.cfg b/tests/zfs-tests/tests/functional/scrub_mirror/default.cfg
new file mode 100644
index 000000000000..01c90e58f51b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/default.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+export SIDE_DIR="${TEST_BASE_DIR}/scrub_mirror"
+export SIDE_PRIMARY="${SIDE_DIR}/dev1"
+export SIDE_SECONDARY="${SIDE_DIR}/dev2"
+export FILE_COUNT=10
+export FILE_SIZE=$(( 1024 * 1024 ))
+export DD_BLOCK=$(( 64 * 1024 ))
+export DD_COUNT=$(( MINVDEVSIZE / DD_BLOCK ))
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_pos.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_pos.ksh
new file mode 100755
index 000000000000..cce59737255c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_001_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
+
+#
+# DESCRIPTION:
+# The primary side of a zpool mirror can be zeroed without causing damage
+# to the data in the pool
+#
+# STRATEGY:
+# 1) Write several files to the ZFS filesystem mirror
+# 2) dd from /dev/zero over the primary side of the mirror
+# 3) verify that all the file contents are unchanged on the file system
+#
+
+verify_runnable "global"
+
+log_assert "The primary side of a zpool mirror may be completely wiped" \
+ "without affecting the content of the pool"
+
+overwrite_verify_mirror $SIDE_PRIMARY /dev/zero
+
+log_pass "The overwrite had no effect on the data"
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_002_pos.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_002_pos.ksh
new file mode 100755
index 000000000000..d1fb9d2f174c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
+
+#
+# DESCRIPTION:
+# The secondary side of a zpool mirror can be zeroed without causing damage
+# to the data in the pool
+#
+# STRATEGY:
+# 1) Write several files to the ZFS filesystem in the mirrored pool
+# 2) dd from /dev/zero over the secondary side of the mirror
+# 3) verify that all the file contents are unchanged on the file system
+#
+
+verify_runnable "global"
+
+log_assert "The primary side of a zpool mirror may be completely wiped" \
+ "without affecting the content of the pool"
+
+overwrite_verify_mirror $SIDE_SECONDARY /dev/zero
+
+log_pass "The overwrite had no effect on the data"
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_pos.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_pos.ksh
new file mode 100755
index 000000000000..fa6c3c2f575f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_003_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
+
+#
+# DESCRIPTION:
+# The primary side of a zpool mirror can be mangled causing without damage
+# to the data in the pool
+#
+# STRATEGY:
+# 1) Write several files to the ZFS filesystem mirror
+# 2) dd from /dev/urandom over the primary side of the mirror
+# 3) verify that all the file contents are unchanged on the file system
+#
+
+verify_runnable "global"
+
+log_assert "The primary side of a zpool mirror may be completely mangled" \
+ "without affecting the content of the pool"
+
+overwrite_verify_mirror $SIDE_PRIMARY /dev/urandom
+
+log_pass "The overwrite did not have any effect on the data"
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_pos.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_pos.ksh
new file mode 100755
index 000000000000..3139b047bb6f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_004_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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
+
+#
+# DESCRIPTION:
+# The secondary side of a zpool mirror can be mangled causing without damage
+# to the data in the pool
+#
+# STRATEGY:
+# 1) Write several files to the ZFS filesystem in the mirrored pool
+# 2) dd from /dev/urandom over the secondary side of the mirror
+# 3) verify that all the file contents are unchanged on the file system
+#
+
+verify_runnable "global"
+
+log_assert "The primary side of a zpool mirror may be completely mangled" \
+ "without affecting the content of the pool"
+
+overwrite_verify_mirror $SIDE_SECONDARY /dev/urandom
+
+log_pass "The overwrite had no effect on the data"
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
new file mode 100644
index 000000000000..4e434ae0b600
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/scrub_mirror_common.kshlib
@@ -0,0 +1,76 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/scrub_mirror/default.cfg
+
+function overwrite_verify_mirror
+{
+ typeset AFFECTED_DEVICE=$1
+ typeset OVERWRITING_DEVICE=$2
+
+ typeset atfile=0
+ set -A files
+ set -A cksums
+ set -A newcksums
+
+ while (( atfile < FILE_COUNT )); do
+ files[$atfile]=$TESTDIR/file.$atfile
+ log_must file_write -o create -f $TESTDIR/file.$atfile \
+ -b $FILE_SIZE -c 1
+ cksums[$atfile]=$(cksum ${files[$atfile]})
+ (( atfile = atfile + 1 ))
+ done
+
+ # dd the affected side of the mirror
+ log_must dd if=$OVERWRITING_DEVICE of=$AFFECTED_DEVICE \
+ seek=8 bs=$DD_BLOCK count=$(( DD_COUNT - 128 )) conv=notrunc
+
+ log_must zpool scrub $TESTPOOL
+ log_must wait_scrubbed $TESTPOOL
+
+ atfile=0
+
+ typeset -i failedcount=0
+ while (( atfile < FILE_COUNT )); do
+ files[$atfile]=$TESTDIR/file.$atfile
+ newcksum=$(cksum ${files[$atfile]})
+ if [[ $newcksum != ${cksums[$atfile]} ]]; then
+ (( failedcount = failedcount + 1 ))
+ fi
+ rm -f ${files[$atfile]}
+ (( atfile = atfile + 1 ))
+ done
+
+ if (( $failedcount > 0 )); then
+ log_fail "of the $FILE_COUNT files $failedcount did not " \
+ "have the same checksum before and after."
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/scrub_mirror/setup.ksh b/tests/zfs-tests/tests/functional/scrub_mirror/setup.ksh
new file mode 100755
index 000000000000..94b995db53ed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/scrub_mirror/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/scrub_mirror/default.cfg
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+log_must mkdir -p $SIDE_DIR
+log_must truncate -s $MINVDEVSIZE $SIDE_PRIMARY $SIDE_SECONDARY
+
+default_mirror_setup $SIDE_PRIMARY $SIDE_SECONDARY
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/slog/Makefile.am b/tests/zfs-tests/tests/functional/slog/Makefile.am
new file mode 100644
index 000000000000..33e3a6d3a496
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/Makefile.am
@@ -0,0 +1,26 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/slog
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ slog_001_pos.ksh \
+ slog_002_pos.ksh \
+ slog_003_pos.ksh \
+ slog_004_pos.ksh \
+ slog_005_pos.ksh \
+ slog_006_pos.ksh \
+ slog_007_pos.ksh \
+ slog_008_neg.ksh \
+ slog_009_neg.ksh \
+ slog_010_neg.ksh \
+ slog_011_neg.ksh \
+ slog_012_neg.ksh \
+ slog_013_pos.ksh \
+ slog_014_pos.ksh \
+ slog_015_neg.ksh \
+ slog_replay_fs_001.ksh \
+ slog_replay_fs_002.ksh \
+ slog_replay_volume.ksh
+
+dist_pkgdata_DATA = \
+ slog.cfg \
+ slog.kshlib
diff --git a/tests/zfs-tests/tests/functional/slog/cleanup.ksh b/tests/zfs-tests/tests/functional/slog/cleanup.ksh
new file mode 100755
index 000000000000..ac301f386f76
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/cleanup.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/slog/slog.cfg
+
+verify_runnable "global"
+
+if ! verify_slog_support ; then
+ log_unsupported "This system doesn't support separate intent logs"
+fi
+
+if datasetexists $TESTPOOL ; then
+ log_must zpool destroy -f $TESTPOOL
+fi
+if datasetexists $TESTPOOL2 ; then
+ log_must zpool destroy -f $TESTPOOL2
+fi
+if [[ -d $VDIR ]]; then
+ log_must rm -rf $VDIR
+fi
+if [[ -d $VDIR2 ]]; then
+ log_must rm -rf $VDIR2
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/slog/setup.ksh b/tests/zfs-tests/tests/functional/slog/setup.ksh
new file mode 100755
index 000000000000..8e8d214d823c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/setup.ksh
@@ -0,0 +1,41 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/slog/slog.cfg
+
+verify_runnable "global"
+
+if ! verify_slog_support ; then
+ log_unsupported "This system doesn't support separate intent logs"
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/slog/slog.cfg b/tests/zfs-tests/tests/functional/slog/slog.cfg
new file mode 100644
index 000000000000..d0d25fde151e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog.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) 2013, 2015 by Delphix. All rights reserved.
+#
+
+export VDIR=$TEST_BASE_DIR/disk-slog
+export VDIR2=$TEST_BASE_DIR/disk2-slog
+
+export VDEV="$VDIR/a $VDIR/b $VDIR/c"
+export SDEV="$VDIR/d"
+export LDEV="$VDIR/e $VDIR/f"
+export VDEV2="$VDIR2/a $VDIR2/b $VDIR2/c"
+export SDEV2="$VDIR2/d"
+export LDEV2="$VDIR2/e $VDIR2/f"
diff --git a/tests/zfs-tests/tests/functional/slog/slog.kshlib b/tests/zfs-tests/tests/functional/slog/slog.kshlib
new file mode 100644
index 000000000000..75cfec2d832d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog.kshlib
@@ -0,0 +1,157 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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/slog/slog.cfg
+
+function setup
+{
+ log_must rm -rf $VDIR $VDIR2
+ log_must mkdir -p $VDIR $VDIR2
+ log_must truncate -s $MINVDEVSIZE $VDEV $SDEV $LDEV $VDEV2 $SDEV2 $LDEV2
+
+ return 0
+}
+
+function cleanup
+{
+ poolexists $TESTPOOL && destroy_pool $TESTPOOL
+ poolexists $TESTPOOL2 && destroy_pool $TESTPOOL2
+ rm -rf $TESTDIR $VDIR $VDIR2
+}
+
+#
+# Try zpool status/iostat for given pool
+#
+# $1 pool
+#
+function display_status
+{
+ typeset pool=$1
+
+ typeset -i ret=0
+ zpool status -xv $pool > /dev/null 2>&1
+ ret=$?
+
+ zpool iostat > /dev/null 2>&1
+ ((ret |= $?))
+
+ typeset mntpnt=$(get_prop mountpoint $pool)
+ dd if=/dev/urandom of=$mntpnt/testfile.$$ &
+ typeset pid=$!
+
+ zpool iostat -v 1 3 > /dev/null
+ ((ret |= $?))
+
+ kill -9 $pid
+ wait
+
+ return $ret
+}
+
+#
+# Verify the give slog device have correct type and status
+#
+# $1 pool name
+# $2 device name
+# $3 device status
+# $4 device type
+#
+function verify_slog_device
+{
+ typeset pool=$1
+ typeset device=$2
+ typeset status=$3
+ typeset type=$4
+
+ if [[ -z $pool || -z $device || -z $status ]]; then
+ log_fail "Usage: verify_slog_device <pool> <device> " \
+ "<status> [type]"
+ fi
+
+ #
+ # Get all the slog devices and status table like below
+ #
+ # mirror:/disks/d ONLINE mirror:/disks/e ONLINE stripe:/disks/f ONLINE
+ #
+ set -A dev_stat_tab $(zpool status -v $pool | nawk 'BEGIN {start=0} \
+ /\tlogs/ {start=1}
+ /\tmirror/ || /\tspares/ || /^$/ {start=0}
+ (start==1) && /\t (\/|[a-zA-Z])/ \
+ {print "stripe:" $1 " " $2}
+ (start==1) && /\t (\/|[a-zA-Z])/ \
+ {print "mirror:" $1 " " $2}
+ # When hotspare is replacing
+ (start==1) && /\t (\/|[a-zA-Z])/ \
+ {print "mirror:" $1 " " $2}'
+ )
+
+ typeset -i i=0
+ typeset find=0
+ while (( i < ${#dev_stat_tab[@]} )); do
+ typeset dev=${dev_stat_tab[$i]}
+ typeset stat=${dev_stat_tab[((i+1))]}
+
+ case $dev in
+ stripe:$device)
+ if [[ "$type" == 'mirror' ]]; then
+ log_note "Unexpected type: mirror"
+ return 1
+ else
+ if [[ $stat != $status ]]; then
+ log_note "Status($stat) " \
+ "!= Expected stat($status)"
+ return 1
+ fi
+ return 0
+ fi
+ ;;
+ mirror:$device)
+ if [[ -z "$type" || $type == 'stripe' ]]; then
+ log_note "Unexpected type: stripe"
+ return 1
+ else
+ if [[ $stat != $status ]]; then
+ log_note "Status($stat) " \
+ "!= Expected stat($status)"
+ return 1
+ fi
+ return 0
+ fi
+ ;;
+ esac
+
+ ((i += 2))
+ done
+
+ log_note "Can not find device: $device"
+
+ return 1
+}
diff --git a/tests/zfs-tests/tests/functional/slog/slog_001_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_001_pos.ksh
new file mode 100755
index 000000000000..a4c35ed9e98e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Creating a pool with a log device succeeds.
+#
+# STRATEGY:
+# 1. Create pool with separated log devices.
+# 2. Display pool status
+# 3. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Creating a pool with a log device succeeds."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ for logtype in "" "mirror"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ $spare $SDEV log $logtype $LDEV
+ log_must display_status $TESTPOOL
+
+ ldev=$(random_get $LDEV)
+ log_must verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' $logtype
+
+ log_must zpool destroy -f $TESTPOOL
+ done
+ done
+done
+
+log_pass "Creating a pool with a log device succeeds."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_002_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_002_pos.ksh
new file mode 100755
index 000000000000..91904aa612d1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Adding a log device to normal pool works.
+#
+# STRATEGY:
+# 1. Create pool
+# 2. Add log devices with different configuration
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Adding a log device to normal pool works."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ for logtype in "" "mirror"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV $spare $SDEV
+ log_must zpool add $TESTPOOL log $logtype $LDEV
+ log_must display_status $TESTPOOL
+ typeset ldev=$(random_get $LDEV)
+ log_must verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' $logtype
+ log_must zpool destroy -f $TESTPOOL
+ done
+ done
+done
+
+log_pass "Adding a log device to normal pool works."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_003_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_003_pos.ksh
new file mode 100755
index 000000000000..0b4d6ede3e13
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_003_pos.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Adding an extra log device works
+#
+# STRATEGY:
+# 1. Create pool with separated log devices.
+# 2. Add an extra log devices
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Adding an extra log device works."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ for logtype in "" "mirror"
+ do
+ for newtype in "" "mirror"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ $spare $SDEV log $logtype $LDEV
+ log_must zpool add $TESTPOOL \
+ log $newtype $LDEV2
+
+ log_must display_status $TESTPOOL
+ ldev=$(random_get $LDEV2)
+ log_must verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' $newtype
+
+ log_must zpool destroy -f $TESTPOOL
+ done
+ done
+ done
+done
+
+log_pass "Adding an extra log device works."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_004_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_004_pos.ksh
new file mode 100755
index 000000000000..10f28dcc000b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_004_pos.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Attaching a log device passes.
+#
+# STRATEGY:
+# 1. Create pool with separated log devices.
+# 2. Attaching a log device for existing log device
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Attaching a log device passes."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ for logtype in "" "mirror"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ $spare $SDEV log $logtype $LDEV
+
+ ldev=$(random_get $LDEV)
+ typeset ldev2=$(random_get $LDEV2)
+ log_must zpool attach $TESTPOOL $ldev $ldev2
+ log_must display_status $TESTPOOL
+ log_must verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' 'mirror'
+ log_must verify_slog_device \
+ $TESTPOOL $ldev2 'ONLINE' 'mirror'
+
+ log_must zpool destroy -f $TESTPOOL
+ done
+ done
+done
+
+log_pass "Attaching a log device passes."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_005_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_005_pos.ksh
new file mode 100755
index 000000000000..4836f6f27937
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Detaching a log device passes.
+#
+# STRATEGY:
+# 1. Create pool with mirror log devices.
+# 2. Detaching a log device
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Detaching a log device passes."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV $spare $SDEV \
+ log mirror $LDEV mirror $LDEV2
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must zpool detach $TESTPOOL $ldev
+ log_must display_status $TESTPOOL
+ log_mustnot verify_slog_device $TESTPOOL $ldev 'ONLINE' 'mirror'
+
+ log_must zpool destroy -f $TESTPOOL
+ done
+done
+
+log_pass "Detaching a log device passes."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_006_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_006_pos.ksh
new file mode 100755
index 000000000000..24143196fd2e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_006_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Replacing a log device passes.
+#
+# STRATEGY:
+# 1. Create pool with log devices.
+# 2. Replacing one log device
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Replacing a log device passes."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ for logtype in "" "mirror"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV \
+ $spare $SDEV log $logtype $LDEV
+ sdev=$(random_get $LDEV)
+ tdev=$(random_get $LDEV2)
+ log_must zpool replace $TESTPOOL $sdev $tdev
+ log_must display_status $TESTPOOL
+ # sleep 15 to make sure replacement completely.
+ log_must sleep 15
+ log_must verify_slog_device \
+ $TESTPOOL $tdev 'ONLINE' $logtype
+
+ log_must zpool destroy -f $TESTPOOL
+ done
+ done
+done
+
+log_pass "Replacing a log device passes."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_007_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_007_pos.ksh
new file mode 100755
index 000000000000..27ac38606c29
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_007_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Exporting and importing pool with log devices passes.
+#
+# STRATEGY:
+# 1. Create pool with log devices.
+# 2. Export and import the pool
+# 3. Display pool status
+# 4. Destroy and import the pool again
+# 5. Display pool status
+# 6. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Exporting and importing pool with log devices passes."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ for logtype in "" "mirror"
+ do
+ #
+ # Create pool which devices resider in different
+ # directory
+ #
+ log_must zpool create $TESTPOOL $type $VDEV \
+ $spare $SDEV log $logtype $LDEV $LDEV2
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' $logtype
+
+ #
+ # Nomal export/import operating
+ #
+ log_must zpool export $TESTPOOL
+ log_must zpool import -d $VDIR -d $VDIR2 $TESTPOOL
+ log_must display_status $TESTPOOL
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' $logtype
+
+ #
+ # Destroy the pool and import again
+ #
+ log_must zpool destroy $TESTPOOL
+ log_must zpool import -Df -d $VDIR -d $VDIR2 $TESTPOOL
+ log_must display_status $TESTPOOL
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' $logtype
+
+ log_must zpool destroy -f $TESTPOOL
+ done
+ done
+done
+
+log_pass "Exporting and importing pool with log devices passes."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_008_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_008_neg.ksh
new file mode 100755
index 000000000000..54587a0c61a7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_008_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# A raidz/raidz2 log is not supported.
+#
+# STRATEGY:
+# 1. Try to create pool with unsupported type
+# 2. Verify failed to create pool.
+#
+
+verify_runnable "global"
+
+log_assert "A raidz/raidz2 log is not supported."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ for logtype in "raidz" "raidz1" "raidz2"
+ do
+ log_mustnot zpool create $TESTPOOL $type $VDEV \
+ $spare $SDEV log $logtype $LDEV $LDEV2
+ ldev=$(random_get $LDEV $LDEV2)
+ log_mustnot verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' $logtype
+ log_must datasetnonexists $TESTPOOL
+ done
+ done
+done
+
+log_pass "A raidz/raidz2 log is not supported."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_009_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_009_neg.ksh
new file mode 100755
index 000000000000..222f71a99928
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_009_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# A raidz/raidz2 log can not be added to existed pool.
+#
+# STRATEGY:
+# 1. Create pool with or without log.
+# 2. Add a raidz/raidz2 log to this pool.
+# 3. Verify failed to add.
+#
+
+verify_runnable "global"
+
+log_assert "A raidz/raidz2 log can not be added to existed pool."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ for logtype in "raidz" "raidz1" "raidz2"
+ do
+ log=$(random_get_with_non "log")
+ log_must zpool create $TESTPOOL $type $VDEV \
+ $spare $SDEV $log $LDEV
+
+ log_mustnot zpool add $TESTPOOL log $logtype $LDEV2
+ ldev=$(random_get $LDEV2)
+ log_mustnot verify_slog_device \
+ $TESTPOOL $ldev 'ONLINE' $logtype
+
+ log_must zpool destroy $TESTPOOL
+ done
+ done
+done
+
+log_pass "A raidz/raidz2 log can not be added to existed pool."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_010_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_010_neg.ksh
new file mode 100755
index 000000000000..edd9abea0930
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_010_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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Slog device can not be replaced with spare device
+#
+# STRATEGY:
+# 1. Create a pool with hotspare and log devices.
+# 2. Verify slog device can not be replaced with hotspare device.
+# 3. Create pool2 with hotspare
+# 4. Verify slog device can not be replaced with hotspare device in pool2.
+#
+
+verify_runnable "global"
+
+log_assert "Slog device can not be replaced with spare device."
+log_onexit cleanup
+log_must setup
+
+log_must zpool create $TESTPOOL $VDEV spare $SDEV log $LDEV
+sdev=$(random_get $SDEV)
+ldev=$(random_get $LDEV)
+log_mustnot zpool replace $TESTPOOL $ldev $sdev
+log_mustnot verify_slog_device $TESTPOOL $sdev 'ONLINE'
+log_must verify_slog_device $TESTPOOL $ldev 'ONLINE'
+
+log_must zpool create $TESTPOOL2 $VDEV2 spare $SDEV2
+sdev2=$(random_get $SDEV2)
+log_mustnot zpool replace $TESTPOOL $ldev $sdev2
+log_mustnot zpool replace -f $TESTPOOL $ldev $sdev2
+log_mustnot verify_slog_device $TESTPOOL $sdev2 'ONLINE'
+log_must verify_slog_device $TESTPOOL $ldev 'ONLINE'
+
+log_pass "Slog device can not be replaced with spare device."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_011_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_011_neg.ksh
new file mode 100755
index 000000000000..3bebc8201713
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_011_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Offline and online a log device passes.
+#
+# STRATEGY:
+# 1. Create pool with mirror log devices.
+# 2. Offine and online a log device
+# 3. Display pool status
+# 4. Destroy and loop to create pool with different configuration.
+#
+
+verify_runnable "global"
+
+log_assert "Offline and online a log device passes."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV $spare $SDEV \
+ log mirror $LDEV mirror $LDEV2
+
+ ldev=$(random_get $LDEV $LDEV2)
+ log_must zpool offline $TESTPOOL $ldev
+ log_must display_status $TESTPOOL
+ log_must verify_slog_device $TESTPOOL $ldev 'OFFLINE' 'mirror'
+
+ log_must zpool online $TESTPOOL $ldev
+ log_must display_status $TESTPOOL
+ log_must verify_slog_device $TESTPOOL $ldev 'ONLINE' 'mirror'
+
+ log_must zpool destroy -f $TESTPOOL
+ done
+done
+
+log_pass "Offline and online a log device passes."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_012_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_012_neg.ksh
new file mode 100755
index 000000000000..8d6fb2bffb7f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_012_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Pool can survive when one of mirror log device get corrupted
+#
+# STRATEGY:
+# 1. Create pool with mirror slog devices
+# 2. Make corrupted on one disk
+# 3. Verify the pool is fine
+#
+
+verify_runnable "global"
+
+log_assert "Pool can survive when one of mirror log device get corrupted."
+log_onexit cleanup
+log_must setup
+
+for type in "" "mirror" "raidz" "raidz2"
+do
+ for spare in "" "spare"
+ do
+ log_must zpool create $TESTPOOL $type $VDEV $spare $SDEV \
+ log mirror $LDEV
+
+ mntpnt=$(get_prop mountpoint $TESTPOOL)
+ #
+ # Create file in pool to trigger writing in slog devices
+ #
+ log_must dd if=/dev/urandom of=$mntpnt/testfile.$$ count=100
+
+ ldev=$(random_get $LDEV)
+ log_must mkfile $MINVDEVSIZE $ldev
+ log_must zpool scrub $TESTPOOL
+
+ log_must display_status $TESTPOOL
+ log_must verify_slog_device $TESTPOOL $ldev 'UNAVAIL' 'mirror'
+
+ log_must zpool destroy -f $TESTPOOL
+ done
+done
+
+log_pass "Pool can survive when one of mirror log device get corrupted."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_013_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_013_pos.ksh
new file mode 100755
index 000000000000..89b3aeb4034c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_013_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Verify slog device can be disk, file, lofi device or any device that
+# presents a block interface.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Loop to add different object as slog
+# 3. Verify it passes
+#
+
+verify_runnable "global"
+
+function cleanup_testenv
+{
+ cleanup
+ if [[ -n $lofidev ]]; then
+ if is_linux; then
+ losetup -d $lofidev
+ elif is_freebsd; then
+ mdconfig -du ${lofidev#md}
+ else
+ lofiadm -d $lofidev
+ fi
+ fi
+}
+
+log_assert "Verify slog device can be disk, file, lofi device or any device " \
+ "that presents a block interface."
+verify_disk_count "$DISKS" 2
+log_onexit cleanup_testenv
+log_must setup
+
+dsk1=${DISKS%% *}
+log_must zpool create $TESTPOOL ${DISKS#$dsk1}
+
+# Add provided disk
+log_must zpool add $TESTPOOL log $dsk1
+log_must verify_slog_device $TESTPOOL $dsk1 'ONLINE'
+# Add normal file
+log_must zpool add $TESTPOOL log $LDEV
+ldev=$(random_get $LDEV)
+log_must verify_slog_device $TESTPOOL $ldev 'ONLINE'
+
+# Add loop back device
+if is_linux; then
+ lofidev=$(losetup -f)
+ log_must losetup $lofidev ${LDEV2%% *}
+ lofidev=${lofidev##*/}
+elif is_freebsd; then
+ lofidev=$(mdconfig -a ${LDEV2%% *})
+else
+ lofidev=${LDEV2%% *}
+ log_must lofiadm -a $lofidev
+ lofidev=$(lofiadm $lofidev)
+fi
+log_must zpool add $TESTPOOL log $lofidev
+log_must verify_slog_device $TESTPOOL $lofidev 'ONLINE'
+
+log_pass "Verify slog device can be disk, file, lofi device or any device " \
+ "that presents a block interface."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_014_pos.ksh b/tests/zfs-tests/tests/functional/slog/slog_014_pos.ksh
new file mode 100755
index 000000000000..f8530a623d47
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_014_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) 2013, 2018 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# log device can survive when one of pool device get corrupted
+#
+# STRATEGY:
+# 1. Create pool with slog devices
+# 2. Corrupt the data on one disk.
+# 3. Verify the log is fine
+#
+
+verify_runnable "global"
+
+log_assert "log device can survive when one of the pool device get corrupted."
+log_must setup
+
+for type in "mirror" "raidz" "raidz2"; do
+ for spare in "" "spare"; do
+ log_must zpool create $TESTPOOL $type $VDEV $spare $SDEV \
+ log $LDEV
+
+ # Create a file to be corrupted
+ dd if=/dev/urandom of=/$TESTPOOL/filler bs=1024k count=50
+
+ #
+ # Ensure the file has been synced out before attempting to
+ # corrupt its contents.
+ #
+ sync
+
+ #
+ # Corrupt a pool device to make the pool DEGRADED
+ # The oseek value below is to skip past the vdev label.
+ #
+ if is_linux || is_freebsd; then
+ log_must dd if=/dev/urandom of=$VDIR/a bs=1024k \
+ seek=4 conv=notrunc count=50
+ else
+ log_must dd if=/dev/urandom of=$VDIR/a bs=1024k \
+ oseek=4 conv=notrunc count=50
+ fi
+ log_must zpool scrub $TESTPOOL
+ log_must display_status $TESTPOOL
+ log_must zpool offline $TESTPOOL $VDIR/a
+ log_must wait_for_degraded $TESTPOOL
+
+ zpool status -v $TESTPOOL | grep logs | \
+ grep "DEGRADED" 2>&1 >/dev/null
+ if (( $? == 0 )); then
+ log_fail "log device should display correct status"
+ fi
+
+ log_must zpool online $TESTPOOL $VDIR/a
+ log_must zpool destroy -f $TESTPOOL
+ done
+done
+
+log_pass "log device can survive when one of the pool device get corrupted."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_015_neg.ksh b/tests/zfs-tests/tests/functional/slog/slog_015_neg.ksh
new file mode 100755
index 000000000000..04fb225ed4ae
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_015_neg.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 (c) 2017 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Concurrent sync writes with log offline/online works.
+#
+# STRATEGY:
+# 1. Configure "zfs_commit_timeout_pct"
+# 2. Create pool with a log device.
+# 3. Concurrently do the following:
+# 3.1. Perform 8K sync writes
+# 3.2. Perform log offline/online commands
+# 4. Loop to test with growing "zfs_commit_timeout_pct" values.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ #
+ # Wait for any of the writes and/or zpool commands that were
+ # kicked off in the background to complete. On failure, we may
+ # enter this function without previously waiting for them.
+ #
+ wait
+
+ set_tunable64 COMMIT_TIMEOUT_PCT $ORIG_TIMEOUT
+
+ poolexists $TESTPOOL && zpool destroy -f $TESTPOOL
+}
+
+typeset ORIG_TIMEOUT=$(get_tunable COMMIT_TIMEOUT_PCT)
+log_onexit cleanup
+log_must setup
+
+for PCT in 0 1 2 4 8 16 32 64 128 256 512 1024; do
+ log_must set_tunable64 COMMIT_TIMEOUT_PCT $PCT
+
+ log_must zpool create $TESTPOOL $VDEV log $SDEV
+
+ for i in {1..10}; do
+ log_must fio --rw write --sync 1 --directory "/$TESTPOOL" \
+ --bs 8K --size 8K --name slog-test
+ done &
+
+ for i in {1..10}; do
+ log_must zpool offline $TESTPOOL $SDEV
+ log_must verify_slog_device $TESTPOOL $SDEV 'OFFLINE'
+ log_must zpool online $TESTPOOL $SDEV
+ log_must verify_slog_device $TESTPOOL $SDEV 'ONLINE'
+ done &
+
+ wait
+
+ log_must zpool destroy -f $TESTPOOL
+done
+
+log_pass "Concurrent writes with slog offline/online works."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh b/tests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh
new file mode 100755
index 000000000000..0b78a099f0b9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_replay_fs_001.ksh
@@ -0,0 +1,223 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Verify slogs are replayed correctly. This test is a direct
+# adaptation of the ziltest.sh script for the ZFS Test Suite.
+#
+# The general idea is to build up an intent log from a bunch of
+# diverse user commands without actually committing them to the
+# file system. Then copy the file system, replay the intent
+# log and compare the file system and the copy.
+#
+# To enable this automated testing of the intent log some minimal
+# support is required of the file system. In particular, a
+# "freeze" command is required to flush the in-flight transactions;
+# to stop the actual committing of transactions; and to ensure no
+# deltas are discarded. All deltas past a freeze point are kept
+# for replay and comparison later. Here is the flow:
+#
+# STRATEGY:
+# 1. Create an empty file system (TESTFS)
+# 2. Freeze TESTFS
+# 3. Run various user commands that create files, directories and ACLs
+# 4. Copy TESTFS to temporary location (TESTDIR/copy)
+# 5. Unmount filesystem
+# <at this stage TESTFS is empty again and unfrozen, and the
+# intent log contains a complete set of deltas to replay it>
+# 6. Remount TESTFS <which replays the intent log>
+# 7. Compare TESTFS against the TESTDIR/copy
+#
+
+verify_runnable "global"
+
+log_assert "Replay of intent log succeeds."
+log_onexit cleanup
+log_must setup
+
+#
+# 1. Create an empty file system (TESTFS)
+#
+log_must zpool create $TESTPOOL $VDEV log mirror $LDEV
+log_must zfs set compression=on $TESTPOOL
+log_must zfs create $TESTPOOL/$TESTFS
+
+#
+# This dd command works around an issue where ZIL records aren't created
+# after freezing the pool unless a ZIL header already exists. Create a file
+# synchronously to force ZFS to write one out.
+#
+log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/sync \
+ conv=fdatasync,fsync bs=1 count=1
+
+#
+# 2. Freeze TESTFS
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 3. Run various user commands that create files, directories and ACLs
+#
+
+# TX_CREATE
+log_must touch /$TESTPOOL/$TESTFS/a
+
+# TX_RENAME
+log_must mv /$TESTPOOL/$TESTFS/a /$TESTPOOL/$TESTFS/b
+
+# TX_SYMLINK
+log_must touch /$TESTPOOL/$TESTFS/c
+log_must ln -s /$TESTPOOL/$TESTFS/c /$TESTPOOL/$TESTFS/d
+
+# TX_LINK
+log_must touch /$TESTPOOL/$TESTFS/e
+log_must ln /$TESTPOOL/$TESTFS/e /$TESTPOOL/$TESTFS/f
+
+# TX_MKDIR
+log_must mkdir /$TESTPOOL/$TESTFS/dir_to_delete
+
+# TX_RMDIR
+log_must rmdir /$TESTPOOL/$TESTFS/dir_to_delete
+
+# Create a simple validation payload
+log_must mkdir -p $TESTDIR
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/payload \
+ oflag=sync bs=1k count=8
+typeset checksum=$(sha256digest /$TESTPOOL/$TESTFS/payload)
+
+# TX_WRITE (small file with ordering)
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/small_file \
+ oflag=sync bs=1k count=1
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/small_file \
+ oflag=sync bs=512 count=1
+
+# TX_CREATE, TX_MKDIR, TX_REMOVE, TX_RMDIR
+log_must cp -R /usr/share/dict /$TESTPOOL/$TESTFS
+log_must rm -rf /$TESTPOOL/$TESTFS/dict
+
+# TX_SETATTR
+log_must touch /$TESTPOOL/$TESTFS/setattr
+log_must chmod 567 /$TESTPOOL/$TESTFS/setattr
+if is_freebsd; then
+ log_must chgrp wheel /$TESTPOOL/$TESTFS/setattr
+else
+ log_must chgrp root /$TESTPOOL/$TESTFS/setattr
+fi
+log_must touch -cm -t 201311271200 /$TESTPOOL/$TESTFS/setattr
+
+# TX_TRUNCATE (to zero)
+log_must mkfile 4k /$TESTPOOL/$TESTFS/truncated_file
+log_must truncate -s 0 /$TESTPOOL/$TESTFS/truncated_file
+
+# TX_WRITE (large file)
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/large \
+ oflag=sync bs=128k count=64
+
+# Write zeros, which compress to holes, in the middle of a file
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.1 \
+ oflag=sync bs=128k count=8
+log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.1 \
+ oflag=sync bs=128k count=2
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.2 \
+ oflag=sync bs=128k count=8
+log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.2 \
+ oflag=sync bs=128k count=2 seek=2
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.3 \
+ oflag=sync bs=128k count=8
+log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.3 \
+ oflag=sync bs=128k count=2 seek=2 conv=notrunc
+
+# TX_MKXATTR
+log_must mkdir /$TESTPOOL/$TESTFS/xattr.dir
+log_must touch /$TESTPOOL/$TESTFS/xattr.file
+log_must set_xattr fileattr HelloWorld /$TESTPOOL/$TESTFS/xattr.dir
+log_must set_xattr tmpattr HelloWorld /$TESTPOOL/$TESTFS/xattr.dir
+log_must rm_xattr fileattr /$TESTPOOL/$TESTFS/xattr.dir
+
+log_must set_xattr fileattr HelloWorld /$TESTPOOL/$TESTFS/xattr.file
+log_must set_xattr tmpattr HelloWorld /$TESTPOOL/$TESTFS/xattr.file
+log_must rm_xattr tmpattr /$TESTPOOL/$TESTFS/xattr.file
+
+# TX_WRITE, TX_LINK, TX_REMOVE
+# Make sure TX_REMOVE won't affect TX_WRITE if file is not destroyed
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/link_and_unlink \
+ oflag=sync bs=128k count=8
+log_must ln /$TESTPOOL/$TESTFS/link_and_unlink \
+ /$TESTPOOL/$TESTFS/link_and_unlink.link
+log_must rm /$TESTPOOL/$TESTFS/link_and_unlink.link
+
+#
+# 4. Copy TESTFS to temporary location (TESTDIR/copy)
+#
+log_must mkdir -p $TESTDIR/copy
+log_must cp -a /$TESTPOOL/$TESTFS/* $TESTDIR/copy/
+
+#
+# 5. Unmount filesystem and export the pool
+#
+# At this stage TESTFS is empty again and frozen, the intent log contains
+# a complete set of deltas to replay.
+#
+log_must zfs unmount /$TESTPOOL/$TESTFS
+
+log_note "Verify transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTFS
+
+log_must zpool export $TESTPOOL
+
+#
+# 6. Remount TESTFS <which replays the intent log>
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must zpool import -f -d $VDIR $TESTPOOL
+
+#
+# 7. Compare TESTFS against the TESTDIR/copy
+#
+log_note "Verify current block usage:"
+log_must zdb -bcv $TESTPOOL
+
+log_note "Verify copy of xattrs:"
+log_must ls_xattr /$TESTPOOL/$TESTFS/xattr.dir
+log_must ls_xattr /$TESTPOOL/$TESTFS/xattr.file
+
+log_note "Verify working set diff:"
+log_must diff -r /$TESTPOOL/$TESTFS $TESTDIR/copy
+
+log_note "Verify file checksum:"
+typeset checksum1=$(sha256digest /$TESTPOOL/$TESTFS/payload)
+[[ "$checksum1" == "$checksum" ]] || \
+ log_fail "checksum mismatch ($checksum1 != $checksum)"
+
+log_pass "Replay of intent log succeeds."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_replay_fs_002.ksh b/tests/zfs-tests/tests/functional/slog/slog_replay_fs_002.ksh
new file mode 100755
index 000000000000..3c3ccdf4ad23
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_replay_fs_002.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 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Verify slog replay correctly when TX_REMOVEs are followed by
+# TX_CREATEs.
+#
+# STRATEGY:
+# 1. Create a file system (TESTFS) with a lot of files
+# 2. Freeze TESTFS
+# 3. Remove all files then create a lot of files
+# 4. Copy TESTFS to temporary location (TESTDIR/copy)
+# 5. Unmount filesystem
+# <at this stage TESTFS is empty again and unfrozen, and the
+# intent log contains a complete set of deltas to replay it>
+# 6. Remount TESTFS <which replays the intent log>
+# 7. Compare TESTFS against the TESTDIR/copy
+#
+
+verify_runnable "global"
+
+function cleanup_fs
+{
+ cleanup
+}
+
+log_assert "Replay of intent log succeeds."
+log_onexit cleanup_fs
+log_must setup
+
+#
+# 1. Create a file system (TESTFS) with a lot of files
+#
+log_must zpool create $TESTPOOL $VDEV log mirror $LDEV
+log_must zfs set compression=on $TESTPOOL
+log_must zfs create $TESTPOOL/$TESTFS
+
+# Prep for the test of TX_REMOVE followed by TX_CREATE
+dnsize=(legacy auto 1k 2k 4k 8k 16k)
+NFILES=200
+log_must mkdir /$TESTPOOL/$TESTFS/dir0
+log_must eval 'for i in $(seq $NFILES); do zfs set dnodesize=${dnsize[$RANDOM % ${#dnsize[@]}]} $TESTPOOL/$TESTFS; touch /$TESTPOOL/$TESTFS/dir0/file.$i; done'
+
+#
+# Reimport to reset dnode allocation pointer.
+# This is to make sure we will have TX_REMOVE and TX_CREATE on same id
+#
+log_must zpool export $TESTPOOL
+log_must zpool import -f -d $VDIR $TESTPOOL
+
+#
+# This dd command works around an issue where ZIL records aren't created
+# after freezing the pool unless a ZIL header already exists. Create a file
+# synchronously to force ZFS to write one out.
+#
+log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/sync \
+ conv=fdatasync,fsync bs=1 count=1
+
+#
+# 2. Freeze TESTFS
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 3. Remove all files then create a lot of files
+#
+# TX_REMOVE followed by TX_CREATE
+log_must eval 'rm -f /$TESTPOOL/$TESTFS/dir0/*'
+log_must eval 'for i in $(seq $NFILES); do zfs set dnodesize=${dnsize[$RANDOM % ${#dnsize[@]}]} $TESTPOOL/$TESTFS; touch /$TESTPOOL/$TESTFS/dir0/file.$i; done'
+
+#
+# 4. Copy TESTFS to temporary location (TESTDIR/copy)
+#
+log_must mkdir -p $TESTDIR/copy
+log_must cp -a /$TESTPOOL/$TESTFS/* $TESTDIR/copy/
+
+#
+# 5. Unmount filesystem and export the pool
+#
+# At this stage TESTFS is empty again and frozen, the intent log contains
+# a complete set of deltas to replay.
+#
+log_must zfs unmount /$TESTPOOL/$TESTFS
+
+log_note "Verify transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTFS
+
+log_must zpool export $TESTPOOL
+
+#
+# 6. Remount TESTFS <which replays the intent log>
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must zpool import -f -d $VDIR $TESTPOOL
+
+#
+# 7. Compare TESTFS against the TESTDIR/copy
+#
+log_note "Verify current block usage:"
+log_must zdb -bcv $TESTPOOL
+
+log_note "Verify number of files"
+log_must test "$(ls /$TESTPOOL/$TESTFS/dir0 | wc -l)" -eq $NFILES
+
+log_note "Verify working set diff:"
+log_must diff -r /$TESTPOOL/$TESTFS $TESTDIR/copy
+
+log_pass "Replay of intent log succeeds."
diff --git a/tests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh b/tests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh
new file mode 100755
index 000000000000..d39c6ded557a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/slog/slog_replay_volume.ksh
@@ -0,0 +1,179 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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.
+# Copyright (c) 2017 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+. $STF_SUITE/tests/functional/slog/slog.kshlib
+
+#
+# DESCRIPTION:
+# Verify slogs are replayed correctly for a volume.
+#
+# The general idea is to build up an intent log from a bunch of
+# diverse user commands without actually committing them to the
+# file system. Then generate checksums for files and volume,
+# replay the intent log and verify the checksums.
+#
+# To enable this automated testing of the intent log some minimal
+# support is required of the file system. In particular, a
+# "freeze" command is required to flush the in-flight transactions;
+# to stop the actual committing of transactions; and to ensure no
+# deltas are discarded. All deltas past a freeze point are kept
+# for replay and comparison later. Here is the flow:
+#
+# STRATEGY:
+# 1. Create an empty volume (TESTVOL), set sync=always, and format
+# it with an ext4 filesystem and mount it.
+# 2. Freeze TESTVOL.
+# 3. Create log records of various types to verify replay.
+# 4. Generate checksums for all ext4 files.
+# 5. Unmount filesystem and export the pool
+# <at this stage TESTVOL is empty again and unfrozen, and the
+# intent log contains a complete set of deltas to replay it>
+# 6. Import TESTVOL <which replays the intent log> and mount it.
+# 7. Verify the stored checksums
+#
+
+verify_runnable "global"
+
+VOLUME=$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL
+MNTPNT=$TESTDIR/$TESTVOL
+FSTYPE=none
+
+function cleanup_volume
+{
+ if ismounted $MNTPNT $FSTYPE; then
+ log_must umount $MNTPNT
+ rmdir $MNTPNT
+ fi
+
+ rm -f $TESTDIR/checksum.files
+
+ cleanup
+}
+
+log_assert "Replay of intent log succeeds."
+log_onexit cleanup_volume
+log_must setup
+
+#
+# 1. Create an empty volume (TESTVOL), set sync=always, and format
+# it with an ext4 filesystem and mount it.
+#
+log_must zpool create $TESTPOOL ${DISKS%% *}
+log_must zfs create -V 128M $TESTPOOL/$TESTVOL
+log_must zfs set compression=on $TESTPOOL/$TESTVOL
+log_must zfs set sync=always $TESTPOOL/$TESTVOL
+log_must mkdir -p $TESTDIR
+block_device_wait
+if is_linux; then
+ # ext4 only on Linux
+ log_must new_fs -t ext4 -v $VOLUME
+ log_must mkdir -p $MNTPNT
+ log_must mount -o discard $VOLUME $MNTPNT
+ FSTYPE=ext4
+ log_must rmdir $MNTPNT/lost+found
+else
+ log_must new_fs $VOLUME
+ log_must mkdir -p $MNTPNT
+ log_must mount $VOLUME $MNTPNT
+ FSTYPE=$NEWFS_DEFAULT_FS
+fi
+log_must zpool sync
+
+#
+# 2. Freeze TESTVOL
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 3. Create log records of various types to verify replay.
+#
+
+# TX_WRITE
+log_must dd if=/dev/urandom of=$MNTPNT/latency-8k bs=8k count=1 oflag=sync
+log_must dd if=/dev/urandom of=$MNTPNT/latency-128k bs=128k count=1 oflag=sync
+
+# TX_WRITE (WR_INDIRECT)
+log_must zfs set logbias=throughput $TESTPOOL/$TESTVOL
+log_must dd if=/dev/urandom of=$MNTPNT/throughput-8k bs=8k count=1
+log_must dd if=/dev/urandom of=$MNTPNT/throughput-128k bs=128k count=1
+
+# TX_WRITE (holes)
+log_must dd if=/dev/urandom of=$MNTPNT/holes bs=128k count=8
+log_must dd if=/dev/zero of=$MNTPNT/holes bs=128k count=2 seek=2 conv=notrunc
+
+if is_linux; then
+ # TX_TRUNCATE
+ if fallocate --punch-hole 2>&1 | grep -q "unrecognized option"; then
+ log_note "fallocate(1) does not support --punch-hole"
+ else
+ log_must dd if=/dev/urandom of=$MNTPNT/discard bs=128k count=16
+ log_must fallocate --punch-hole -l 128K -o 512K $MNTPNT/discard
+ log_must fallocate --punch-hole -l 512K -o 1M $MNTPNT/discard
+ fi
+fi
+
+#
+# 4. Generate checksums for all ext4 files.
+#
+typeset checksum=$(cat $MNTPNT/* | sha256digest)
+
+#
+# 5. Unmount filesystem and export the pool
+#
+# At this stage TESTVOL is initialized with the random data and frozen,
+# the intent log contains a complete set of deltas to replay.
+#
+log_must umount $MNTPNT
+
+log_note "Verify transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTVOL
+
+log_must zpool export $TESTPOOL
+
+#
+# 6. Import TESTPOOL, the intent log is replayed during minor creation.
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must zpool import -f $TESTPOOL
+block_device_wait
+log_must mount $VOLUME $MNTPNT
+
+#
+# 7. Verify the stored checksums
+#
+log_note "Verify current block usage:"
+log_must zdb -bcv $TESTPOOL
+
+log_note "Verify checksums"
+typeset checksum1=$(cat $MNTPNT/* | sha256digest)
+[[ "$checksum1" == "$checksum" ]] || \
+ log_fail "checksum mismatch ($checksum1 != $checksum)"
+
+log_pass "Replay of intent log succeeds."
diff --git a/tests/zfs-tests/tests/functional/snapshot/Makefile.am b/tests/zfs-tests/tests/functional/snapshot/Makefile.am
new file mode 100644
index 000000000000..783133a643a1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/Makefile.am
@@ -0,0 +1,28 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/snapshot
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ clone_001_pos.ksh \
+ rollback_001_pos.ksh \
+ rollback_002_pos.ksh \
+ rollback_003_pos.ksh \
+ snapshot_001_pos.ksh \
+ snapshot_002_pos.ksh \
+ snapshot_003_pos.ksh \
+ snapshot_004_pos.ksh \
+ snapshot_005_pos.ksh \
+ snapshot_006_pos.ksh \
+ snapshot_007_pos.ksh \
+ snapshot_008_pos.ksh \
+ snapshot_009_pos.ksh \
+ snapshot_010_pos.ksh \
+ snapshot_011_pos.ksh \
+ snapshot_012_pos.ksh \
+ snapshot_013_pos.ksh \
+ snapshot_014_pos.ksh \
+ snapshot_015_pos.ksh \
+ snapshot_016_pos.ksh \
+ snapshot_017_pos.ksh
+
+dist_pkgdata_DATA = \
+ snapshot.cfg
diff --git a/tests/zfs-tests/tests/functional/snapshot/cleanup.ksh b/tests/zfs-tests/tests/functional/snapshot/cleanup.ksh
new file mode 100755
index 000000000000..530a785330dc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/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.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+if is_linux; then
+ log_must set_tunable64 ADMIN_SNAPSHOT 0
+fi
+
+default_container_cleanup
diff --git a/tests/zfs-tests/tests/functional/snapshot/clone_001_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/clone_001_pos.ksh
new file mode 100755
index 000000000000..3abdff8c3bc7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/clone_001_pos.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 2009 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/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Create a snapshot from regular filesystem, volume,
+# or filesystem upon volume, Build a clone file system
+# from the snapshot and verify new files can be written.
+#
+# STRATEGY:
+# 1. Create snapshot use 3 combination:
+# - Regular filesystem
+# - Regular volume
+# - Filesystem upon volume
+# 2. Clone a new file system from the snapshot
+# 3. Verify the cloned file system is writable
+#
+
+verify_runnable "both"
+
+# Setup array, 4 elements as a group, refer to:
+# i+0: name of a snapshot
+# i+1: mountpoint of the snapshot
+# i+2: clone created from the snapshot
+# i+3: mountpoint of the clone
+
+set -A args "$SNAPFS" "$SNAPDIR" "$TESTPOOL/$TESTCLONE" "$TESTDIR.0" \
+ "$SNAPFS1" "$SNAPDIR3" "$TESTPOOL/$TESTCLONE1" "" \
+ "$SNAPFS2" "$SNAPDIR2" "$TESTPOOL1/$TESTCLONE2" "$TESTDIR.2"
+
+function setup_all
+{
+ if is_freebsd; then
+ # Pool creation on zvols is forbidden by default.
+ # Save and the current setting.
+ typeset _saved=$(get_tunable VOL_RECURSIVE)
+ log_must set_tunable64 VOL_RECURSIVE 1
+ fi
+ create_pool $TESTPOOL1 ${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+ if is_freebsd; then
+ # Restore the previous setting.
+ log_must set_tunable64 VOL_RECURSIVE $_saved
+ fi
+ log_must zfs create $TESTPOOL1/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR2 $TESTPOOL1/$TESTFS
+
+ return 0
+}
+
+function cleanup_all
+{
+ typeset -i i=0
+
+ i=0
+ while (( i < ${#args[*]} )); do
+ snapexists ${args[i]} && \
+ destroy_dataset "${args[i]}" "-Rf"
+
+ [[ -d ${args[i+3]} ]] && \
+ log_must rm -rf ${args[i+3]}
+
+ [[ -d ${args[i+1]} ]] && \
+ log_must rm -rf ${args[i+1]}
+
+ (( i = i + 4 ))
+ done
+
+ datasetexists $TESTPOOL1/$TESTFS && \
+ log_must zfs destroy -f $TESTPOOL1/$TESTFS
+
+ destroy_pool $TESTPOOL1
+
+ [[ -d $TESTDIR2 ]] && \
+ log_must rm -rf $TESTDIR2
+
+ return 0
+}
+
+log_assert "Verify a cloned file system is writable."
+
+log_onexit cleanup_all
+
+setup_all
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+typeset -i COUNT=10
+typeset -i i=0
+
+for mtpt in $TESTDIR $TESTDIR2 ; do
+ log_note "Populate the $mtpt directory (prior to snapshot)"
+ typeset -i j=1
+ while [[ $j -le $COUNT ]]; do
+ log_must file_write -o create -f $mtpt/before_file$j \
+ -b $BLOCKSZ -c $NUM_WRITES -d $j
+
+ (( j = j + 1 ))
+ done
+done
+
+while (( i < ${#args[*]} )); do
+ #
+ # Take a snapshot of the test file system.
+ #
+ log_must zfs snapshot ${args[i]}
+
+ #
+ # Clone a new file system from the snapshot
+ #
+ log_must zfs clone ${args[i]} ${args[i+2]}
+ if [[ -n ${args[i+3]} ]] ; then
+ log_must zfs set mountpoint=${args[i+3]} ${args[i+2]}
+
+ FILE_COUNT=`ls -Al ${args[i+3]} | grep -v "total" \
+ | grep -v "\.zfs" | wc -l`
+ if [[ $FILE_COUNT -ne $COUNT ]]; then
+ ls -Al ${args[i+3]}
+ log_fail "AFTER: ${args[i+3]} contains $FILE_COUNT files(s)."
+ fi
+
+ log_note "Verify the ${args[i+3]} directory is writable"
+ j=1
+ while [[ $j -le $COUNT ]]; do
+ log_must file_write -o create -f ${args[i+3]}/after_file$j \
+ -b $BLOCKSZ -c $NUM_WRITES -d $j
+ (( j = j + 1 ))
+ done
+
+ FILE_COUNT=`ls -Al ${args[i+3]}/after* | grep -v "total" | wc -l`
+ if [[ $FILE_COUNT -ne $COUNT ]]; then
+ ls -Al ${args[i+3]}
+ log_fail "${args[i+3]} contains $FILE_COUNT after* files(s)."
+ fi
+ fi
+
+ (( i = i + 4 ))
+done
+
+log_pass "The clone file system is writable."
diff --git a/tests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh
new file mode 100755
index 000000000000..8894c3a65287
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/rollback_001_pos.ksh
@@ -0,0 +1,115 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Populate a file system and take a snapshot. Add some more files to the
+# file system and rollback to the last snapshot. Verify no post snapshot
+# file exist.
+#
+# STRATEGY:
+# 1. Empty a file system
+# 2. Populate the file system
+# 3. Take a snapshot of the file system
+# 4. Add new files to the file system
+# 5. Perform a rollback
+# 6. Verify the snapshot and file system agree
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $SNAPFS
+ [[ $? -eq 0 ]] && \
+ log_must zfs destroy $SNAPFS
+
+ [[ -e $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+}
+
+log_assert "Verify that a rollback to a previous snapshot succeeds."
+
+log_onexit cleanup
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+typeset -i COUNT=10
+
+log_note "Populate the $TESTDIR directory (prior to snapshot)"
+typeset -i i=1
+while [[ $i -le $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR/before_file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+log_must zfs snapshot $SNAPFS
+
+FILE_COUNT=`ls -Al $SNAPDIR | grep -v "total" | wc -l`
+if [[ $FILE_COUNT -ne $COUNT ]]; then
+ ls -Al $SNAPDIR
+ log_fail "AFTER: $SNAPFS contains $FILE_COUNT files(s)."
+fi
+
+log_note "Populate the $TESTDIR directory (post snapshot)"
+typeset -i i=1
+while [[ $i -le $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR/after_file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+#
+# Now rollback to latest snapshot
+#
+log_must zfs rollback $SNAPFS
+
+FILE_COUNT=`ls -Al $TESTDIR/after* 2> /dev/null | grep -v "total" | wc -l`
+if [[ $FILE_COUNT -ne 0 ]]; then
+ ls -Al $TESTDIR
+ log_fail "$TESTDIR contains $FILE_COUNT after* files(s)."
+fi
+
+FILE_COUNT=`ls -Al $TESTDIR/before* 2> /dev/null \
+ | grep -v "total" | wc -l`
+if [[ $FILE_COUNT -ne $COUNT ]]; then
+ ls -Al $TESTDIR
+ log_fail "$TESTDIR contains $FILE_COUNT before* files(s)."
+fi
+
+log_pass "The rollback operation succeeded."
diff --git a/tests/zfs-tests/tests/functional/snapshot/rollback_002_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/rollback_002_pos.ksh
new file mode 100755
index 000000000000..c424a69f0a7e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/rollback_002_pos.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 2007 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/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify that rollbacks are with respect to the latest snapshot.
+#
+# STRATEGY:
+# 1. Empty a file system
+# 2. Populate the file system
+# 3. Take a snapshot of the file system
+# 4. Add new files to the file system
+# 5. Take a snapshot
+# 6. Remove the original files
+# 7. Perform a rollback
+# 8. Verify the latest snapshot and file system agree
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $SNAPFS.1
+ [[ $? -eq 0 ]] && \
+ log_must zfs destroy $SNAPFS.1
+
+ snapexists $SNAPFS
+ [[ $? -eq 0 ]] && \
+ log_must zfs destroy $SNAPFS
+
+ [[ -e $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+}
+
+log_assert "Verify rollback is with respect to latest snapshot."
+
+log_onexit cleanup
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+typeset -i COUNT=10
+
+log_note "Populate the $TESTDIR directory (prior to first snapshot)"
+typeset -i i=1
+while [[ $i -le $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR/original_file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+log_must zfs snapshot $SNAPFS
+
+FILE_COUNT=`ls -Al $SNAPDIR | grep -v "total" | wc -l`
+if [[ $FILE_COUNT -ne $COUNT ]]; then
+ ls -Al $SNAPDIR
+ log_fail "AFTER: $SNAPFS contains $FILE_COUNT files(s)."
+fi
+
+log_note "Populate the $TESTDIR directory (prior to second snapshot)"
+typeset -i i=1
+while [[ $i -le $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR/afterfirst_file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+log_must zfs snapshot $SNAPFS.1
+
+log_note "Populate the $TESTDIR directory (Post second snapshot)"
+typeset -i i=1
+while [[ $i -le $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR/aftersecond_file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/original_file* > /dev/null 2>&1
+
+#
+# Now rollback to latest snapshot
+#
+log_must zfs rollback $SNAPFS.1
+
+FILE_COUNT=`ls -Al $TESTDIR/aftersecond* 2> /dev/null \
+ | grep -v "total" | wc -l`
+if [[ $FILE_COUNT -ne 0 ]]; then
+ ls -Al $TESTDIR
+ log_fail "$TESTDIR contains $FILE_COUNT aftersecond* files(s)."
+fi
+
+FILE_COUNT=`ls -Al $TESTDIR/original* $TESTDIR/afterfirst*| grep -v "total" | wc -l`
+if [[ $FILE_COUNT -ne 20 ]]; then
+ ls -Al $TESTDIR
+ log_fail "$TESTDIR contains $FILE_COUNT original* files(s)."
+fi
+
+log_pass "The rollback to the latest snapshot succeeded."
diff --git a/tests/zfs-tests/tests/functional/snapshot/rollback_003_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/rollback_003_pos.ksh
new file mode 100755
index 000000000000..59e7c110ddd7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/rollback_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+
+#
+# DESCRIPTION:
+# Verify that rollbacks succeed when there are nested file systems.
+#
+# STRATEGY:
+# 1) Snapshot an empty file system and rollback
+# 2) Create a file in the file system
+# 3) Rollback the file system to empty
+# 4) Create a nested file system with the same name as the file created in (2)
+# 5) Verify a rollback succeeds
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset snap=""
+ typeset fs=""
+
+ export __ZFS_POOL_RESTRICT="$TESTPOOL"
+ log_must zfs mount -a
+ unset __ZFS_POOL_RESTRICT
+
+ for snap in "$SNAPPOOL.1" "$SNAPPOOL"; do
+ if snapexists $snap; then
+ destroy_snapshot $snap
+ fi
+ done
+
+ for fs in "$TESTPOOL/$TESTFILE/$TESTFILE.1" "$TESTPOOL/$TESTFILE"; do
+ if datasetexists $fs; then
+ destroy_dataset $fs -r
+ fi
+ done
+
+ [[ -e /$TESTPOOL ]] && \
+ log_must rm -rf $TESTPOOL/*
+}
+
+log_assert "Verify rollback succeeds when there are nested file systems."
+
+log_onexit cleanup
+
+log_must zfs snapshot $SNAPPOOL
+log_must zfs rollback $SNAPPOOL
+log_mustnot zfs snapshot $SNAPPOOL
+
+log_must touch /$TESTPOOL/$TESTFILE
+
+log_must zfs rollback $SNAPPOOL
+log_must zfs create $TESTPOOL/$TESTFILE
+
+log_must zfs rollback $SNAPPOOL
+
+log_note "Verify rollback of multiple nested file systems succeeds."
+log_must zfs snapshot $TESTPOOL/$TESTFILE@$TESTSNAP
+log_must zfs snapshot $SNAPPOOL.1
+
+export __ZFS_POOL_RESTRICT="$TESTPOOL"
+log_must zfs unmount -a
+log_must zfs mount -a
+unset __ZFS_POOL_RESTRICT
+
+log_must touch /$TESTPOOL/$TESTFILE/$TESTFILE.1
+
+log_must zfs rollback $SNAPPOOL.1
+
+#
+# Workaround for issue #6143. Issuing a `df` seems to properly force any
+# negative dcache entries to be invalidated preventing subsequent failures
+# when accessing the mount point. Additional investigation required.
+#
+log_must df
+
+log_pass "Rollbacks succeed when nested file systems are present."
diff --git a/tests/zfs-tests/tests/functional/snapshot/setup.ksh b/tests/zfs-tests/tests/functional/snapshot/setup.ksh
new file mode 100755
index 000000000000..a73d1aff3c53
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/setup.ksh
@@ -0,0 +1,40 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+if is_linux; then
+ log_must set_tunable64 ADMIN_SNAPSHOT 1
+fi
+
+default_container_volume_setup ${DISK}
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot.cfg b/tests/zfs-tests/tests/functional/snapshot/snapshot.cfg
new file mode 100644
index 000000000000..265903fe1469
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot.cfg
@@ -0,0 +1,53 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export TESTFILE=testfile-snapshot
+export SNAPROOT=".zfs/snapshot"
+
+export SNAPPOOL="$TESTPOOL@$TESTSNAP"
+export SNAPFS="$TESTPOOL/$TESTFS@$TESTSNAP"
+export SNAPFS1="$TESTPOOL/$TESTVOL@$TESTSNAP"
+export SNAPFS2="$TESTPOOL1/$TESTFS@$TESTSNAP"
+export SNAPCTR="$TESTPOOL/$TESTCTR/$TESTFS1@$TESTSNAP"
+export SNAPDIR="$TESTDIR/$SNAPROOT/$TESTSNAP"
+export SNAPDIR1="$TESTDIR1/$SNAPROOT/$TESTSNAP"
+export SNAPDIR2="$TESTDIR2/$SNAPROOT/$TESTSNAP"
+export SNAPDIR3="/$SNAPFS1"
+
+export VOLSIZE=1gb
+export BLOCKSZ=8192
+export NUM_WRITES=20
+export DATA=0
+export LIMIT=2097152 # tolerance measured in bytes, 2M
+export FSQUOTA=500m
+export FILESIZE=400m
+export FILESIZE1=200m
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_001_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_001_pos.ksh
new file mode 100755
index 000000000000..8b8c118d9dfb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# A zfs file system snapshot is identical to
+# the originally snapshot'd file system, after the file
+# system has been changed. Uses 'sum -r'.
+#
+# STRATEGY:
+# 1. Create a file in the zfs file system
+# 2. Checksum the file for later comparison
+# 3. Create a snapshot of the dataset
+# 4. Append to the original file
+# 5. Verify the snapshot and file agree
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $SNAPFS
+ if [[ $? -eq 0 ]]; then
+ log_must zfs destroy $SNAPFS
+ fi
+
+ if [[ -e $SNAPDIR ]]; then
+ log_must rm -rf $SNAPDIR > /dev/null 2>&1
+ fi
+
+ if [[ -e $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+ fi
+}
+
+log_assert "Verify a file system snapshot is identical to original."
+
+log_onexit cleanup
+
+log_note "Create a file in the zfs filesystem..."
+log_must file_write -o create -f $TESTDIR/$TESTFILE -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+
+log_note "Sum the file, save for later comparison..."
+FILE_SUM=`sum -r $TESTDIR/$TESTFILE | awk '{ print $1 }'`
+log_note "FILE_SUM = $FILE_SUM"
+
+log_note "Create a snapshot and mount it..."
+log_must zfs snapshot $SNAPFS
+
+log_note "Append to the original file..."
+log_must file_write -o append -f $TESTDIR/$TESTFILE -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+
+SNAP_FILE_SUM=`sum -r $SNAPDIR/$TESTFILE | awk '{ print $1 }'`
+if [[ $SNAP_FILE_SUM -ne $FILE_SUM ]]; then
+ log_fail "Sums do not match, aborting!! ($SNAP_FILE_SUM != $FILE_SUM)"
+fi
+
+log_pass "Both Sums match. ($SNAP_FILE_SUM == $FILE_SUM)"
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh
new file mode 100755
index 000000000000..124a7db9c6e6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_002_pos.ksh
@@ -0,0 +1,129 @@
+#! /bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# An archive of a zfs file system and an archive of its snapshot
+# is identical even though the original file system has
+# changed since the snapshot was taken.
+#
+# STRATEGY:
+# 1) Create files in all of the zfs file systems
+# 2) Create a tarball of the file system
+# 3) Create a snapshot of the dataset
+# 4) Remove all the files in the original file system
+# 5) Create a tarball of the snapshot
+# 6) Extract each tarball and compare directory structures
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if [[ -d $CWD ]]; then
+ cd $CWD || log_fail "Could not cd $CWD"
+ fi
+
+ snapexists $SNAPFS
+ if [[ $? -eq 0 ]]; then
+ log_must zfs destroy $SNAPFS
+ fi
+
+ if [[ -e $SNAPDIR ]]; then
+ log_must rm -rf $SNAPDIR > /dev/null 2>&1
+ fi
+
+ if [[ -e $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+ fi
+
+}
+
+log_assert "Verify an archive of a file system is identical to " \
+ "an archive of its snapshot."
+
+log_onexit cleanup
+
+typeset -i COUNT=21
+typeset OP=create
+
+[[ -n $TESTDIR ]] && \
+ rm -rf $TESTDIR/* > /dev/null 2>&1
+
+log_note "Create files in the zfs filesystem..."
+
+typeset i=1
+while [ $i -lt $COUNT ]; do
+ log_must file_write -o $OP -f $TESTDIR/file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $DATA
+
+ (( i = i + 1 ))
+done
+
+log_note "Create a tarball from $TESTDIR contents..."
+CWD=$PWD
+cd $TESTDIR || log_fail "Could not cd $TESTDIR"
+log_must tar cf $TESTDIR/tarball.original.tar file*
+cd $CWD || log_fail "Could not cd $CWD"
+
+log_note "Create a snapshot and mount it..."
+log_must zfs snapshot $SNAPFS
+
+log_note "Remove all of the original files..."
+log_must rm -f $TESTDIR/file* > /dev/null 2>&1
+
+log_note "Create tarball of snapshot..."
+CWD=$PWD
+cd $SNAPDIR || log_fail "Could not cd $SNAPDIR"
+log_must tar cf $TESTDIR/tarball.snapshot.tar file*
+cd $CWD || log_fail "Could not cd $CWD"
+
+log_must mkdir $TESTDIR/original
+log_must mkdir $TESTDIR/snapshot
+
+CWD=$PWD
+cd $TESTDIR/original || log_fail "Could not cd $TESTDIR/original"
+log_must tar xf $TESTDIR/tarball.original.tar
+
+cd $TESTDIR/snapshot || log_fail "Could not cd $TESTDIR/snapshot"
+log_must tar xf $TESTDIR/tarball.snapshot.tar
+
+cd $CWD || log_fail "Could not cd $CWD"
+
+diff -q -r $TESTDIR/original $TESTDIR/snapshot > /dev/null 2>&1
+if [[ $? -eq 1 ]]; then
+ log_fail "Directory structures differ."
+fi
+
+log_pass "Directory structures match."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_003_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_003_pos.ksh
new file mode 100755
index 000000000000..054b58cd5590
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_003_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 2007 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/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify that many snapshots can be made on a zfs file system.
+#
+# STRATEGY:
+# 1) Create a files in the zfs file system
+# 2) Create a snapshot of the dataset
+# 3) Remove all the files from the original file system
+# 4) Verify consistency of each snapshot directory
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset -i i=1
+ while [ $i -lt $COUNT ]; do
+ snapexists $SNAPFS.$i
+ if [[ $? -eq 0 ]]; then
+ log_must zfs destroy $SNAPFS.$i
+ fi
+
+ if [[ -e $SNAPDIR.$i ]]; then
+ log_must rm -rf $SNAPDIR.$i > /dev/null 2>&1
+ fi
+
+ (( i = i + 1 ))
+ done
+
+ if [[ -e $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+ fi
+}
+
+log_assert "Verify many snapshots of a file system can be taken."
+
+log_onexit cleanup
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+typeset -i COUNT=10
+
+log_note "Create some files in the $TESTDIR directory..."
+typeset -i i=1
+while [[ $i -lt $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR/file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+ log_must zfs snapshot $SNAPFS.$i
+
+ (( i = i + 1 ))
+done
+
+log_note "Remove all of the original files"
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/file* > /dev/null 2>&1
+
+i=1
+while [[ $i -lt $COUNT ]]; do
+ FILECOUNT=`ls $SNAPDIR.$i/file* | wc -l`
+ typeset j=1
+ while [ $j -lt $FILECOUNT ]; do
+ log_must file_check $SNAPDIR.$i/file$j $j
+ (( j = j + 1 ))
+ done
+ (( i = i + 1 ))
+done
+
+log_pass "All files are consistent"
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_004_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_004_pos.ksh
new file mode 100755
index 000000000000..9d3b3de1adc0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_004_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Create a null snapshot i.e. a snapshot created before file system
+# activity is empty.
+#
+# STRATEGY:
+# 1. Empty a file system
+# 2. Take a snapshot of the empty file system.
+# 3. Populate the file system
+# 4. Verify the snapshot is still empty
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $SNAPFS
+ [[ $? -eq 0 ]] && \
+ log_must zfs destroy $SNAPFS
+
+ [[ -e $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+}
+
+log_assert "Verify that a snapshot of an empty file system remains empty."
+
+log_onexit cleanup
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+log_must zfs snapshot $SNAPFS
+FILE_COUNT=`ls -Al $SNAPDIR | grep -v "total 0" | wc -l`
+if [[ $FILE_COUNT -ne 0 ]]; then
+ ls $SNAPDIR
+ log_fail "BEFORE: $SNAPDIR contains $FILE_COUNT files(s)."
+fi
+
+typeset -i COUNT=10
+
+log_note "Populate the $TESTDIR directory"
+typeset -i i=1
+while [[ $i -lt $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR/file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+FILE_COUNT=`ls -Al $SNAPDIR | grep -v "total 0" | wc -l`
+if [[ $FILE_COUNT -ne 0 ]]; then
+ ls $SNAPDIR
+ log_fail "AFTER: $SNAPDIR contains $FILE_COUNT files(s)."
+fi
+
+log_pass "The NULL snapshot remains empty."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_005_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_005_pos.ksh
new file mode 100755
index 000000000000..c1917dff1299
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_005_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# to the originally snapshot'd file system, after the file
+# system has been changed. Uses 'sum -r'.
+#
+# STRATEGY:
+# 1) Create a file in the zfs dataset
+# 2) Sum the file for later comparison
+# 3) Create a snapshot of the dataset
+# 4) Append to the original file
+# 5) Verify both checksums match
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $SNAPCTR
+ if [[ $? -eq 0 ]]; then
+ log_must zfs destroy $SNAPCTR
+ fi
+
+ if [[ -e $SNAPDIR1 ]]; then
+ log_must rm -rf $SNAPDIR1 > /dev/null 2>&1
+ fi
+
+ if [[ -e $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+ fi
+}
+
+log_assert "Verify that a snapshot of a dataset is identical to " \
+ "the original dataset."
+log_onexit cleanup
+
+log_note "Create a file in the zfs filesystem..."
+log_must file_write -o create -f $TESTDIR1/$TESTFILE -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+
+log_note "Sum the file, save for later comparison..."
+FILE_SUM=`sum -r $TESTDIR1/$TESTFILE | awk '{ print $1 }'`
+log_note "FILE_SUM = $FILE_SUM"
+
+log_note "Create a snapshot and mount it..."
+log_must zfs snapshot $SNAPCTR
+
+log_note "Append to the original file..."
+log_must file_write -o append -f $TESTDIR1/$TESTFILE -b $BLOCKSZ \
+ -c $NUM_WRITES -d $DATA
+
+SNAP_FILE_SUM=`sum -r $SNAPDIR1/$TESTFILE | awk '{ print $1 }'`
+if [[ $SNAP_FILE_SUM -ne $FILE_SUM ]]; then
+ log_fail "Sums do not match, aborting!! ($SNAP_FILE_SUM != $FILE_SUM)"
+fi
+
+log_pass "Both Sums match. ($SNAP_FILE_SUM == $FILE_SUM)"
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_006_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_006_pos.ksh
new file mode 100755
index 000000000000..68a616c02a6c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_006_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# An archive of a zfs dataset and an archive of its snapshot
+# changed since the snapshot was taken.
+#
+# STRATEGY:
+# 1) Create some files in a ZFS dataset
+# 2) Create a tarball of the dataset
+# 3) Create a snapshot of the dataset
+# 4) Remove all the files in the original dataset
+# 5) Create a tarball of the snapshot
+# 6) Extract each tarball and compare directory structures
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if [[ -d $CWD ]]; then
+ cd $CWD || log_fail "Could not cd $CWD"
+ fi
+
+ snapexists $SNAPCTR
+ if [[ $? -eq 0 ]]; then
+ log_must zfs destroy $SNAPCTR
+ fi
+
+ if [[ -e $SNAPDIR1 ]]; then
+ log_must rm -rf $SNAPDIR1 > /dev/null 2>&1
+ fi
+
+ if [[ -e $TESTDIR1 ]]; then
+ log_must rm -rf $TESTDIR1/* > /dev/null 2>&1
+ fi
+
+}
+
+log_assert "Verify that an archive of a dataset is identical to " \
+ "an archive of the dataset's snapshot."
+
+log_onexit cleanup
+
+typeset -i COUNT=21
+typeset OP=create
+
+[[ -n $TESTDIR1 ]] && rm -rf $TESTDIR1/* > /dev/null 2>&1
+
+log_note "Create files in the zfs dataset ..."
+
+typeset i=1
+while [ $i -lt $COUNT ]; do
+ log_must file_write -o $OP -f $TESTDIR1/file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $DATA
+
+ (( i = i + 1 ))
+done
+
+log_note "Create a tarball from $TESTDIR1 contents..."
+CWD=$PWD
+cd $TESTDIR1 || log_fail "Could not cd $TESTDIR1"
+log_must tar cf $TESTDIR1/tarball.original.tar file*
+cd $CWD || log_fail "Could not cd $CWD"
+
+log_note "Create a snapshot and mount it..."
+log_must zfs snapshot $SNAPCTR
+
+log_note "Remove all of the original files..."
+log_must rm -f $TESTDIR1/file* > /dev/null 2>&1
+
+log_note "Create tarball of snapshot..."
+CWD=$PWD
+cd $SNAPDIR1 || log_fail "Could not cd $SNAPDIR1"
+log_must tar cf $TESTDIR1/tarball.snapshot.tar file*
+cd $CWD || log_fail "Could not cd $CWD"
+
+log_must mkdir $TESTDIR1/original
+log_must mkdir $TESTDIR1/snapshot
+
+CWD=$PWD
+cd $TESTDIR1/original || log_fail "Could not cd $TESTDIR1/original"
+log_must tar xf $TESTDIR1/tarball.original.tar
+
+cd $TESTDIR1/snapshot || log_fail "Could not cd $TESTDIR1/snapshot"
+log_must tar xf $TESTDIR1/tarball.snapshot.tar
+
+cd $CWD || log_fail "Could not cd $CWD"
+
+diff -q -r $TESTDIR1/original $TESTDIR1/snapshot > /dev/null 2>&1
+if [[ $? -eq 1 ]]; then
+ log_fail "Directory structures differ."
+fi
+
+log_pass "Directory structures match."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.ksh
new file mode 100755
index 000000000000..7ed1fdb6e7ad
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_007_pos.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 2007 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/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify that many snapshots can be made on a zfs dataset.
+#
+# STRATEGY:
+# 1) Create a file in the zfs dataset
+# 2) Create a snapshot of the dataset
+# 3) Remove all the files from the original dataset
+# 4) For each snapshot directory verify consistency
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset -i i=1
+ while [ $i -lt $COUNT ]; do
+ snapexists $SNAPCTR.$i
+ if [[ $? -eq 0 ]]; then
+ log_must zfs destroy $SNAPCTR.$i
+ fi
+
+ if [[ -e $SNAPDIR.$i ]]; then
+ log_must rm -rf $SNAPDIR1.$i > /dev/null 2>&1
+ fi
+
+ (( i = i + 1 ))
+ done
+
+ if [[ -e $SNAPDIR1 ]]; then
+ log_must rm -rf $SNAPDIR1 > /dev/null 2>&1
+ fi
+
+ if [[ -e $TESTDIR ]]; then
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+ fi
+}
+
+log_assert "Verify that many snapshots can be made on a zfs dataset."
+
+log_onexit cleanup
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+typeset -i COUNT=10
+
+log_note "Create some files in the $TESTDIR directory..."
+typeset -i i=1
+while [[ $i -lt $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR1/file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+ log_must zfs snapshot $SNAPCTR.$i
+
+ (( i = i + 1 ))
+done
+
+log_note "Remove all of the original files"
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR1/file* > /dev/null 2>&1
+
+i=1
+while [[ $i -lt $COUNT ]]; do
+ FILECOUNT=`ls $SNAPDIR1.$i/file* | wc -l`
+ typeset j=1
+ while [ $j -lt $FILECOUNT ]; do
+ log_must file_check $SNAPDIR1.$i/file$j $j
+ (( j = j + 1 ))
+ done
+ (( i = i + 1 ))
+done
+
+log_pass "All files are consistent"
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_008_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_008_pos.ksh
new file mode 100755
index 000000000000..d0ecb77fe0a0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_008_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 2007 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/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify that destroying snapshots returns space to the pool.
+#
+# STRATEGY:
+# 1. Create a file system and populate it while snapshotting.
+# 2. Destroy the snapshots and remove the files.
+# 3. Verify the space returns to the pool.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset -i i=1
+ while [[ $i -lt $COUNT ]]; do
+ snapexists $SNAPFS.$i
+ [[ $? -eq 0 ]] && \
+ log_must zfs destroy $SNAPFS.$i
+
+ (( i = i + 1 ))
+ done
+
+ [[ -e $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+}
+
+log_assert "Verify that destroying snapshots returns space to the pool."
+
+log_onexit cleanup
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+typeset -i COUNT=10
+
+orig_size=`get_prop available $TESTPOOL`
+
+log_note "Populate the $TESTDIR directory"
+typeset -i i=1
+while [[ $i -lt $COUNT ]]; do
+ log_must file_write -o create -f $TESTDIR/file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ log_must zfs snapshot $SNAPFS.$i
+ (( i = i + 1 ))
+done
+
+typeset -i i=1
+while [[ $i -lt $COUNT ]]; do
+ log_must rm -rf $TESTDIR/file$i > /dev/null 2>&1
+ log_must zfs destroy $SNAPFS.$i
+
+ (( i = i + 1 ))
+done
+
+wait_freeing $TESTPOOL
+sync_pool
+
+new_size=`get_prop available $TESTPOOL`
+
+typeset -i tolerance=0
+
+(( tolerance = new_size - orig_size))
+if (( tolerance > LIMIT )); then
+ log_fail "Space not freed. ($orig_size != $new_size)"
+fi
+
+log_pass "After destroying snapshots, the space is returned to the pool."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_009_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_009_pos.ksh
new file mode 100755
index 000000000000..1ee7e33c2ac2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_009_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify 'snapshot -r' and 'destroy -r' can correctly create and destroy
+# snapshot tree respectively.
+#
+# STRATEGY:
+# 1. Use the snapshot -r to create snapshot for top level pool
+# 2. Verify the children snapshots are created correctly.
+# 3. Use destroy -r to destroy the top level snapshot
+# 4. Verify that all children snapshots are destroyed too.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset ds
+ typeset snap
+
+ for ds in $ctr/$TESTVOL1 $ctr/$TESTCLONE; do
+ destroy_dataset $ds "-rf"
+ done
+
+ for snap in $ctr/$TESTFS1@$TESTSNAP1 \
+ $snappool $snapvol $snapctr $snapctrvol \
+ $snapctrclone $snapctrfs
+ do
+ snapexists $snap && destroy_dataset $snap "-rf"
+ done
+}
+
+log_assert "Verify snapshot -r can correctly create a snapshot tree."
+log_onexit cleanup
+
+ctr=$TESTPOOL/$TESTCTR
+ctrfs=$ctr/$TESTFS1
+ctrclone=$ctr/$TESTCLONE
+ctrvol=$ctr/$TESTVOL1
+snappool=$SNAPPOOL
+snapfs=$SNAPFS
+snapctr=$ctr@$TESTSNAP
+snapvol=$SNAPFS1
+snapctrvol=$ctrvol@$TESTSNAP
+snapctrclone=$ctrclone@$TESTSNAP
+snapctrfs=$SNAPCTR
+
+#preparation for testing
+log_must zfs snapshot $ctrfs@$TESTSNAP1
+log_must zfs clone $ctrfs@$TESTSNAP1 $ctrclone
+if is_global_zone; then
+ log_must zfs create -V $VOLSIZE $ctrvol
+else
+ log_must zfs create $ctrvol
+fi
+
+log_must zfs snapshot -r $snappool
+block_device_wait
+
+#verify the snapshot -r results
+for snap in $snappool $snapfs $snapvol $snapctr $snapctrvol \
+ $snapctrclone $snapctrfs
+do
+ ! snapexists $snap && \
+ log_fail "The snapshot $snap is not created via -r option."
+done
+
+log_note "Verify that destroy -r can destroy the snapshot tree."
+
+log_must zfs destroy -r $snappool
+for snap in $snappool $snapfs $snapvol $snapctr $snapctrvol \
+ $snapctrclone $snapctrfs
+do
+ snapexists $snap && \
+ log_fail "The snapshot $snap is not destroyed correctly."
+done
+
+log_note "Verify that the snapshot with different name should \
+ be not destroyed."
+! snapexists $ctrfs@$TESTSNAP1 && \
+ log_fail "destroy -r incorrectly destroys the snapshot \
+ $ctrfs@$TESTSNAP1."
+
+log_pass "snapshot|destroy -r with snapshot tree works as expected."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_010_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_010_pos.ksh
new file mode 100755
index 000000000000..128b443c6fc9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_010_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify 'destroy -r' can correctly destroy a snapshot tree at any point.
+#
+# STRATEGY:
+# 1. Use the snapshot -r to create snapshot for top level pool
+# 2. Select a middle point of the snapshot tree, use destroy -r to destroy all
+# snapshots beneath the point.
+# 3. Verify the destroy results.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset snap
+
+ destroy_dataset $ctrvol "-rf"
+
+ for snap in $ctrfs@$TESTSNAP1 \
+ $snappool $snapvol $snapctr $snapctrvol \
+ $snapctrclone $snapctrfs
+ do
+ snapexists $snap && destroy_dataset $snap "-rf"
+ done
+
+}
+
+log_assert "Verify 'destroy -r' can correctly destroy a snapshot subtree at any point."
+log_onexit cleanup
+
+ctr=$TESTPOOL/$TESTCTR
+ctrfs=$ctr/$TESTFS1
+ctrvol=$ctr/$TESTVOL1
+snappool=$SNAPPOOL
+snapfs=$SNAPFS
+snapctr=$ctr@$TESTSNAP
+snapvol=$SNAPFS1
+snapctrvol=$ctr/$TESTVOL1@$TESTSNAP
+snapctrclone=$ctr/$TESTCLONE@$TESTSNAP
+snapctrfs=$SNAPCTR
+
+#preparation for testing
+log_must zfs snapshot $ctrfs@$TESTSNAP1
+if is_global_zone; then
+ log_must zfs create -V $VOLSIZE $ctrvol
+else
+ log_must zfs create $ctrvol
+fi
+
+log_must zfs snapshot -r $snappool
+block_device_wait
+
+#select the $TESTCTR as destroy point, $TESTCTR is a child of $TESTPOOL
+log_must zfs destroy -r $snapctr
+for snap in $snapctr $snapctrvol $snapctrclone $snapctrfs; do
+ snapexists $snap && \
+ log_fail "The snapshot $snap is not destroyed correctly."
+done
+
+for snap in $snappool $snapfs $snapvol $ctrfs@$TESTSNAP1; do
+ ! snapexists $snap && \
+ log_fail "The snapshot $snap should be not destroyed."
+done
+
+log_pass "'destroy -r' destroys snapshot subtree as expected."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.ksh
new file mode 100755
index 000000000000..44e5943bcd2f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_011_pos.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# use 'snapshot -r' to create a snapshot tree, add some files to one child
+# filesystem, rollback the child filesystem snapshot, verify that the child
+# filesystem gets back to the status while taking the snapshot.
+#
+# STRATEGY:
+# 1. Add some files to a target child filesystem
+# 2. snapshot -r the parent filesystem
+# 3. Add some other files to the target child filesystem
+# 4. rollback the child filesystem snapshot
+# 5. verify that the child filesystem get back to the status while being
+# snapshot'd
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ snapexists $SNAPPOOL && \
+ log_must zfs destroy -r $SNAPPOOL
+
+ [[ -e $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+}
+
+log_assert "Verify that rollback to a snapshot created by snapshot -r succeeds."
+log_onexit cleanup
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+typeset -i COUNT=10
+
+log_note "Populate the $TESTDIR directory (prior to snapshot)"
+typeset -i i=0
+while (( i < COUNT )); do
+ log_must file_write -o create -f $TESTDIR/before_file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+log_must zfs snapshot -r $SNAPPOOL
+
+FILE_COUNT=`ls -Al $SNAPDIR | grep -v "total" | wc -l`
+if (( FILE_COUNT != COUNT )); then
+ ls -Al $SNAPDIR
+ log_fail "AFTER: $SNAPFS contains $FILE_COUNT files(s)."
+fi
+
+log_note "Populate the $TESTDIR directory (post snapshot)"
+typeset -i i=0
+while (( i < COUNT )); do
+ log_must file_write -o create -f $TESTDIR/after_file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+#
+# Now rollback to latest snapshot
+#
+log_must zfs rollback $SNAPFS
+
+FILE_COUNT=`ls -Al $TESTDIR/after* 2> /dev/null | grep -v "total" | wc -l`
+if (( FILE_COUNT != 0 )); then
+ ls -Al $TESTDIR
+ log_fail "$TESTDIR contains $FILE_COUNT after* files(s)."
+fi
+
+FILE_COUNT=`ls -Al $TESTDIR/before* 2> /dev/null \
+ | grep -v "total" | wc -l`
+if (( FILE_COUNT != $COUNT )); then
+ ls -Al $TESTDIR
+ log_fail "$TESTDIR contains $FILE_COUNT before* files(s)."
+fi
+
+log_pass "Rollback with child snapshot works as expected."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_012_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_012_pos.ksh
new file mode 100755
index 000000000000..c5717e452686
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_012_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify 'snapshot -r' can create snapshot for promoted clone, and vice
+# versa, a clone filesystem from the snapshot created by 'snapshot -r'
+# can be correctly promoted.
+#
+# STRATEGY:
+# 1. Create a dataset tree
+# 2. snapshot a filesystem and clone the snapshot
+# 3. promote the clone
+# 4. snapshot -r the dataset tree
+# 5. verify that the snapshot of cloned filesystem is created correctly
+# 6. clone a snapshot from the snapshot tree
+# 7. promote the clone
+# 8. verify that the clone is promoted correctly.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ if datasetexists $clone1; then
+ log_must zfs promote $ctrfs
+ log_must zfs destroy $clone1
+ fi
+
+ snapexists $snapctr && \
+ log_must zfs destroy -r $snapctr
+
+ if snapexists $clone@$TESTSNAP1; then
+ log_must zfs promote $ctrfs
+ log_must zfs destroy -rR $ctrfs@$TESTSNAP1
+ fi
+}
+
+log_assert "Verify that 'snapshot -r' can work with 'zfs promote'."
+log_onexit cleanup
+
+ctr=$TESTPOOL/$TESTCTR
+ctrfs=$ctr/$TESTFS1
+clone=$ctr/$TESTCLONE
+clone1=$ctr/$TESTCLONE1
+snappool=$SNAPPOOL
+snapfs=$SNAPFS
+snapctr=$ctr@$TESTSNAP
+snapctrclone=$clone@$TESTSNAP
+snapctrclone1=$clone1@$TESTSNAP
+snapctrfs=$SNAPCTR
+
+#preparation for testing
+log_must zfs snapshot $ctrfs@$TESTSNAP1
+log_must zfs clone $ctrfs@$TESTSNAP1 $clone
+log_must zfs promote $clone
+
+log_must zfs snapshot -r $snapctr
+
+! snapexists $snapctrclone && \
+ log_fail "'snapshot -r' fails to create $snapctrclone for $ctr/$TESTCLONE."
+
+log_must zfs clone $snapctrfs $clone1
+log_must zfs promote $clone1
+
+#verify the origin value is correct.
+orig_value=$(get_prop origin $ctrfs)
+if ! snapexists $snapctrclone1 || [[ "$orig_value" != "$snapctrclone1" ]]; then
+ log_fail "'zfs promote' fails to promote $clone which is cloned from \
+ $snapctrfs."
+fi
+
+log_pass "'snapshot -r' can work with 'zfs promote' as expected."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_013_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_013_pos.ksh
new file mode 100755
index 000000000000..31aedb224515
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_013_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# verify that the snapshots created by 'snapshot -r' can be used for
+# zfs send/recv
+#
+# STRATEGY:
+# 1. create a dataset tree and populate a filesystem
+# 2. snapshot -r the dataset tree
+# 3. select one snapshot used for zfs send/recv
+# 4. verify the data integrity after zfs send/recv
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $ctrfs && \
+ zfs destroy -r $ctrfs
+
+ snapexists $snappool && \
+ log_must zfs destroy -r $snappool
+
+ [[ -e $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+}
+
+log_assert "Verify snapshots from 'snapshot -r' can be used for zfs send/recv"
+log_onexit cleanup
+
+ctr=$TESTPOOL/$TESTCTR
+ctrfs=$ctr/$TESTFS
+snappool=$SNAPPOOL
+snapfs=$SNAPFS
+snapctr=$ctr@$TESTSNAP
+snapctrfs=$ctrfs@$TESTSNAP
+fsdir=/$ctrfs
+snapdir=$fsdir/.zfs/snapshot/$TESTSNAP
+
+[[ -n $TESTDIR ]] && \
+ log_must rm -rf $TESTDIR/* > /dev/null 2>&1
+
+typeset -i COUNT=10
+
+log_note "Populate the $TESTDIR directory (prior to snapshot)"
+typeset -i i=0
+while (( i < COUNT )); do
+ log_must file_write -o create -f $TESTDIR/file$i \
+ -b $BLOCKSZ -c $NUM_WRITES -d $i
+
+ (( i = i + 1 ))
+done
+
+log_must zfs snapshot -r $snappool
+
+zfs send $snapfs | zfs receive $ctrfs >/dev/null 2>&1
+if ! datasetexists $ctrfs || ! snapexists $snapctrfs; then
+ log_fail "zfs send/receive fails with snapshot $snapfs."
+fi
+
+for dir in $fsdir $snapdir; do
+ FILE_COUNT=`ls -Al $dir | grep -v "total" | wc -l`
+ (( FILE_COUNT != COUNT )) && log_fail "Got $FILE_COUNT expected $COUNT"
+done
+
+log_pass "'zfs send/receive' works as expected with snapshots from 'snapshot -r'"
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_014_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_014_pos.ksh
new file mode 100755
index 000000000000..3579fbebb4b8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_014_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# verify that creating/destroying snapshots do things clean
+#
+# STRATEGY:
+# 1. create a dataset and set a quota with 500m
+# 2. create file of size 400m on the dataset
+# 3. take a snapshot and destroy it
+# 4. then create file to use all spaces in the dataset
+# 5. verify removing the first file should succeed
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ [[ -e $TESTDIR1 ]] && \
+ log_must rm -rf $TESTDIR1/* > /dev/null 2>&1
+
+ snapexists $SNAPCTR && \
+ log_must zfs destroy $SNAPCTR
+
+ datasetexists $TESTPOOL/$TESTCTR/$TESTFS1 && \
+ log_must zfs set quota=none $TESTPOOL/$TESTCTR/$TESTFS1
+
+}
+
+log_assert "Verify creating/destroying snapshots do things clean"
+log_onexit cleanup
+
+log_must zfs set quota=$FSQUOTA $TESTPOOL/$TESTCTR/$TESTFS1
+log_must mkfile $FILESIZE $TESTDIR1/$TESTFILE
+
+log_must zfs snapshot $SNAPCTR
+log_must zfs destroy $SNAPCTR
+
+log_note "Make the quota of filesystem is reached"
+log_mustnot mkfile $FILESIZE1 $TESTDIR1/$TESTFILE1
+
+log_note "Verify removing the first file should succeed after the snapshot is \
+ removed"
+log_must rm $TESTDIR1/$TESTFILE
+
+log_pass "Verify creating/destroying snapshots do things clean"
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh
new file mode 100755
index 000000000000..1091bcb13ea7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_015_pos.ksh
@@ -0,0 +1,121 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapshot/snapshot.cfg
+. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify snapshot can be created or destroy via mkdir or rm
+# in .zfs/snapshot.
+#
+# STRATEGY:
+# 1. Verify make directories only successfully in .zfs/snapshot.
+# 2. Verify snapshot can be created and destroy via mkdir and remove
+# directories in .zfs/snapshot.
+# 3. Verify rollback to previous snapshot can succeed.
+# 4. Verify remove directory in snapdir can destroy snapshot.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ typeset -i i=0
+ while ((i < snap_cnt)); do
+ typeset snap=$fs@snap.$i
+ datasetexists $snap && log_must zfs destroy -f $snap
+
+ ((i += 1))
+ done
+}
+
+zfs 2>&1 | grep "allow" > /dev/null
+(($? != 0)) && log_unsupported
+
+log_assert "Verify snapshot can be created via mkdir in .zfs/snapshot."
+log_onexit cleanup
+
+fs=$TESTPOOL/$TESTFS
+# Verify all the other directories are readonly.
+mntpnt=$(get_prop mountpoint $fs)
+snapdir=$mntpnt/.zfs
+set -A ro_dirs "$snapdir" "$snapdir/snap" "$snapdir/snapshot"
+for dir in ${ro_dirs[@]}; do
+ if [[ -d $dir ]]; then
+ log_mustnot rm -rf $dir
+ log_mustnot touch $dir/testfile
+ else
+ log_mustnot mkdir $dir
+ fi
+done
+
+# Verify snapshot can be created via mkdir in .zfs/snapshot
+typeset -i snap_cnt=5
+typeset -i cnt=0
+while ((cnt < snap_cnt)); do
+ testfile=$mntpnt/testfile.$cnt
+ log_must mkfile 1M $testfile
+ log_must mkdir $snapdir/snapshot/snap.$cnt
+ if ! datasetexists $fs@snap.$cnt ; then
+ log_fail "ERROR: $fs@snap.$cnt should exists."
+ fi
+
+ ((cnt += 1))
+done
+
+# Verify rollback to previous snapshot succeed.
+((cnt = RANDOM % snap_cnt))
+log_must zfs rollback -r $fs@snap.$cnt
+
+typeset -i i=0
+while ((i < snap_cnt)); do
+ testfile=$mntpnt/testfile.$i
+ if ((i <= cnt)); then
+ if [[ ! -f $testfile ]]; then
+ log_fail "ERROR: $testfile should exists."
+ fi
+ else
+ if [[ -f $testfile ]]; then
+ log_fail "ERROR: $testfile should not exists."
+ fi
+ fi
+
+ ((i += 1))
+done
+
+# Verify remove directory in snapdir can destroy snapshot.
+log_must rmdir $snapdir/snapshot/snap.$cnt
+log_mustnot datasetexists $fs@snap.$cnt
+
+log_pass "Verify snapshot can be created via mkdir in .zfs/snapshot passed."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_016_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_016_pos.ksh
new file mode 100755
index 000000000000..b460c2b0c5dc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_016_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 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/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+# Verify renamed snapshots via mv can be destroyed
+#
+# STRATEGY:
+# 1. Create snapshot
+# 2. Rename the snapshot via mv command
+# 2. Verify destroying the renamed snapshot via 'zfs destroy' succeeds
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ datasetexists $SNAPFS && \
+ log_must zfs destroy -Rf $SNAPFS
+ datasetexists $TESTPOOL/$TESTFS@snap_a && \
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS@snap_a
+ datasetexists $TESTPOOL/$TESTFS@snap_b && \
+ log_must zfs destroy -Rf $TESTPOOL/$TESTFS@snap_b
+ datasetexists $TESTPOOL/$TESTCLONE@snap_a && \
+ log_must zfs destroy -Rf $TESTPOOL/$TESTCLONE@snap_a
+
+ datasetexists $TESTPOOL/$TESTCLONE && \
+ log_must zfs destroy $TESTPOOL/$TESTCLONE
+ datasetexists $TESTPOOL/$TESTFS && \
+ log_must zfs destroy $TESTPOOL/$TESTFS
+
+ log_must zfs create $TESTPOOL/$TESTFS
+ log_must zfs set mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+log_assert "Verify renamed snapshots via mv can be destroyed."
+log_onexit cleanup
+
+# scenario 1
+
+log_must zfs snapshot $SNAPFS
+log_must mv $TESTDIR/$SNAPROOT/$TESTSNAP $TESTDIR/$SNAPROOT/snap_a
+
+datasetexists $TESTPOOL/$TESTFS@snap_a || \
+ log_fail "rename snapshot via mv in .zfs/snapshot fails."
+log_must zfs destroy $TESTPOOL/$TESTFS@snap_a
+
+# scenario 2
+
+log_must zfs snapshot $SNAPFS
+log_must zfs clone $SNAPFS $TESTPOOL/$TESTCLONE
+log_must mv $TESTDIR/$SNAPROOT/$TESTSNAP $TESTDIR/$SNAPROOT/snap_b
+
+datasetexists $TESTPOOL/$TESTFS@snap_b || \
+ log_fail "rename snapshot via mv in .zfs/snapshot fails."
+log_must zfs promote $TESTPOOL/$TESTCLONE
+# promote back to $TESTPOOL/$TESTFS for scenario 3
+log_must zfs promote $TESTPOOL/$TESTFS
+log_must zfs destroy $TESTPOOL/$TESTCLONE
+log_must zfs destroy $TESTPOOL/$TESTFS@snap_b
+
+# scenario 3
+
+log_must zfs snapshot $SNAPFS
+log_must zfs clone $SNAPFS $TESTPOOL/$TESTCLONE
+log_must zfs rename $SNAPFS $TESTPOOL/$TESTFS@snap_a
+log_must zfs promote $TESTPOOL/$TESTCLONE
+log_must zfs destroy $TESTPOOL/$TESTFS
+log_must zfs destroy $TESTPOOL/$TESTCLONE@snap_a
+
+log_pass "Verify renamed snapshots via mv can be destroyed."
diff --git a/tests/zfs-tests/tests/functional/snapshot/snapshot_017_pos.ksh b/tests/zfs-tests/tests/functional/snapshot/snapshot_017_pos.ksh
new file mode 100755
index 000000000000..a21f8750d697
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapshot/snapshot_017_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 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/snapshot/snapshot.cfg
+
+#
+# DESCRIPTION:
+#
+# Directory structure of snapshots reflects filesystem structure.
+#
+# STRATEGY:
+#
+# This test makes sure that the directory structure of snapshots is
+# a proper reflection of the filesystem the snapshot was taken of.
+#
+# 1. Create a simple directory structure of files and directories
+# 2. Take a snapshot of the filesystem
+# 3. Modify original filesystem
+# 4. Walk down the snapshot directory structure verifying it
+# checking with both absolute and relative paths
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ cd $SAVED_DIR
+
+ 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
+}
+
+function verify_structure {
+
+ # check absolute paths
+ DIR=$PWD
+ verify_file $DIR/file1
+ verify_file $DIR/file2
+ verify_file $DIR/dir1/file3
+ verify_file $DIR/dir1/file4
+ verify_file $DIR/dir1/dir2/file5
+ verify_file $DIR/dir1/dir2/file6
+
+ verify_no_file $DIR/file99
+
+ # check relative paths
+ verify_file ./file1
+ verify_file ./file2
+ verify_file ./dir1/file3
+ verify_file ./dir1/file4
+ verify_file ./dir1/dir2/file5
+ verify_file ./dir1/dir2/file6
+
+ cd dir1
+ verify_file ../file1
+ verify_file ../file2
+ verify_file ./file3
+ verify_file ./file4
+
+ verify_no_file ../file99
+
+ cd dir2
+ verify_file ./file5
+ verify_file ./file6
+ verify_file ../file3
+ verify_file ../file4
+ verify_no_file ../file99
+
+ verify_file ../../file1
+ verify_file ../../file2
+ verify_no_file ../../file99
+}
+
+function verify_file {
+ if [ ! -e $1 ]
+ then
+ log_note "Working dir is $PWD"
+ log_fail "File $1 does not exist!"
+ fi
+}
+
+function verify_no_file {
+ if [ -e $1 ]
+ then
+ log_note "Working dir is $PWD"
+ log_fail "File $1 exists when it should not!"
+ fi
+}
+
+function verify_dir {
+ if [ ! -d $1 ]
+ then
+ log_note "Working dir is $PWD"
+ log_fail "Directory $1 does not exist!"
+ fi
+}
+
+log_assert "Directory structure of snapshots reflects filesystem structure."
+log_onexit cleanup
+
+SAVED_DIR=$PWD
+
+#
+# Create a directory structure with the following files
+#
+# ./file1
+# ./file2
+# ./dir1/file3
+# ./dir1/file4
+# ./dir1/dir2/file5
+# ./dir1/dir2/file6
+
+cd $TESTDIR
+mkfile 10m file1
+mkfile 20m file2
+mkdir dir1
+cd dir1
+mkfile 10m file3
+mkfile 20m file4
+mkdir dir2
+cd dir2
+mkfile 10m file5
+mkfile 20m file6
+
+# Now walk the directory structure verifying it
+cd $TESTDIR
+verify_structure
+
+# Take snapshots
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap_a
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap_b
+
+# Change the filesystem structure by renaming files in the original structure
+# The snapshot file structure should not change
+cd $TESTDIR
+log_must mv file2 file99
+cd dir1
+log_must mv file4 file99
+cd dir2
+log_must mv file6 file99
+
+# verify the top level snapshot directories
+verify_dir $TESTDIR/.zfs
+verify_dir $TESTDIR/.zfs/snapshot
+verify_dir $TESTDIR/.zfs/snapshot/snap_a
+verify_dir $TESTDIR/.zfs/snapshot/snap_b
+
+cd $TESTDIR/.zfs/snapshot/snap_a
+verify_structure
+
+cd $TESTDIR/.zfs/snapshot/snap_b
+verify_structure
+
+cd $TESTDIR/.zfs
+verify_dir snapshot
+cd $TESTDIR/.zfs/snapshot
+verify_dir snap_a
+verify_dir snap_b
+
+cd snap_a
+verify_dir ../snap_a
+verify_dir ../snap_b
+
+cd ..
+verify_dir snap_a
+verify_dir snap_b
+
+log_pass "Directory structure of snapshots reflects filesystem structure."
diff --git a/tests/zfs-tests/tests/functional/snapused/Makefile.am b/tests/zfs-tests/tests/functional/snapused/Makefile.am
new file mode 100644
index 000000000000..d6551b7c41b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/snapused
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ snapused_001_pos.ksh \
+ snapused_002_pos.ksh \
+ snapused_003_pos.ksh \
+ snapused_004_pos.ksh \
+ snapused_005_pos.ksh
+
+dist_pkgdata_DATA = \
+ snapused.kshlib
diff --git a/tests/zfs-tests/tests/functional/snapused/cleanup.ksh b/tests/zfs-tests/tests/functional/snapused/cleanup.ksh
new file mode 100755
index 000000000000..2f536ca588ed
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/snapused/setup.ksh b/tests/zfs-tests/tests/functional/snapused/setup.ksh
new file mode 100755
index 000000000000..dfe8696add67
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused.kshlib b/tests/zfs-tests/tests/functional/snapused/snapused.kshlib
new file mode 100644
index 000000000000..d7d05bfeef1f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/snapused.kshlib
@@ -0,0 +1,185 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export USEDTEST=$TESTPOOL/$TESTFS/usedtest-snapused
+
+function _check_used # dataset
+{
+ typeset dataset=$1
+
+ if [[ "$(get_prop type $dataset)" == "snapshot" ]]; then
+ return
+ fi
+
+ used=$(get_prop used $dataset)
+ usedbychildren=$(get_prop usedbychildren $dataset)
+ usedbydataset=$(get_prop usedbydataset $dataset)
+ usedbyrefreservation=$(get_prop usedbyrefreservation $dataset)
+ usedbysnapshots=$(get_prop usedbysnapshots $dataset)
+ ((used_sum = usedbychildren + usedbydataset + \
+ usedbyrefreservation + usedbysnapshots))
+ if ((used != used_sum)); then
+ log_fail "$dataset: used($used) is not the sum($used_sum) of usedby*"
+ fi
+}
+
+function check_used # dataset
+{
+ typeset dataset=$1
+ for child in $(zfs list -rH -t filesystem,volume -o name $dataset)
+ do
+ _check_used $child
+ done
+}
+
+function check_usedbychildren # dataset
+{
+ typeset dataset=$1
+ typeset -i usedbychildren_sum=0
+ typeset -i parent_usedbychildren=0
+ for child in $(zfs list -rH -t filesystem,volume -o name $dataset)
+ do
+ if [[ "$(get_prop type $child)" == "snapshot" ]]; then
+ continue
+ fi
+
+ # parent
+ if [[ "$child" == "$dataset" ]]; then
+ parent_usedbychildren=$(get_prop usedbychildren $child)
+ else #child
+ reservation=$(get_prop reservation $child)
+ used=$(get_prop used $child)
+ if ((reservation > used)); then
+ ((usedbychildren_sum += reservation))
+ else
+ ((usedbychildren_sum += used))
+ fi
+ fi
+ done
+
+ if ((parent_usedbychildren != usedbychildren_sum)); then
+ log_fail "$dataset: usedbychildren($parent_usedbychildren) is not the sum($usedbychildren_sum) of used by children"
+ fi
+}
+
+function _check_usedbydataset # dataset
+{
+ typeset dataset=$1
+ if [[ "$(get_prop type $dataset)" == "snapshot" ]]; then
+ return
+ fi
+
+ usedbydataset=$(get_prop usedbydataset $dataset)
+ referenced=$(get_prop referenced $dataset)
+
+ is_cloned=$(get_prop is:cloned $dataset)
+
+ if [[ "$is_cloned" == "yes" ]]; then
+ if ((usedbydataset > referenced)); then
+ log_fail "$dataset(cloned): usedbydataset($usedbydataset) is more than referenced($referenced)"
+ fi
+ else
+ #
+ # if non-clones, should usedbydataset == referenced
+ #
+ if ((usedbydataset != referenced)); then
+ log_fail "$dataset: usedbydataset($usedbydataset) is not equal to referenced($referenced)"
+ fi
+ fi
+}
+
+function check_usedbydataset # dataset
+{
+ typeset dataset=$1
+ for child in $(zfs list -rH -t filesystem,volume -o name $dataset)
+ do
+ _check_usedbydataset $child
+ done
+}
+
+function _check_usedbyrefreservation # dataset
+{
+ typeset dataset=$1
+ if [[ "$(get_prop type $dataset)" == "snapshot" ]]; then
+ return
+ fi
+
+ usedbyrefreservation=$(get_prop usedbyrefreservation $dataset)
+ referenced=$(get_prop referenced $dataset)
+ refreservation=$(get_prop refreservation $dataset)
+ ((diff_ref = refreservation - referenced))
+ if ((usedbyrefreservation > refreservation || \
+ usedbyrefreservation < diff_ref)); then
+ log_fail "$dataset: usedbyrefreservation($usedbyrefreservation) checking is not ok"
+ fi
+}
+
+function check_usedbyrefreservation # dataset
+{
+ typeset dataset=$1
+ for child in $(zfs list -rH -t filesystem,volume -o name $dataset)
+ do
+ _check_usedbyrefreservation $child
+ done
+}
+
+function check_usedbysnapshots # dataset
+{
+ typeset dataset=$1
+ typeset -i usedbysnapshots_sum=0
+ typeset -i parent_usedbysnapshots=0
+ for child in $(zfs list -rH -t filesystem,volume,snapshot -o name $dataset)
+ do
+ # parent
+ if [[ "$child" == "$dataset" ]]; then
+ parent_usedbysnapshots=$(get_prop usedbysnapshots $child)
+ continue
+ fi
+
+ if [[ "$(get_prop type $child)" != "snapshot" ]]; then
+ continue
+ fi
+
+ if [[ "$child" != "$dataset@"* ]]; then
+ continue
+ fi
+
+ # snapshot
+ used=$(get_prop used $child)
+ ((usedbysnapshots_sum += used))
+ done
+
+ if ((parent_usedbysnapshots < usedbysnapshots_sum)); then
+ log_fail "$dataset: usedbysnapshots($parent_usedbysnapshots) is not more than or equal to" \
+ "the sum($usedbysnapshots_sum) of used of snapshots"
+ fi
+}
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_001_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_001_pos.ksh
new file mode 100755
index 000000000000..302ba40c38a3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapused/snapused.kshlib
+
+#
+# DESCRIPTION:
+# Verify used is correct.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Set refreservation of the filesystem.
+# 3. Make file in the filesystem.
+# 4. Create sub filesystem and make file in it.
+# 5. Create volume under it.
+# 6. Snapshot it.
+# 7. Check used=usedbychildren+usedbydataset+
+# usedbyrefreservation+usedbysnapshots.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rR $USEDTEST
+}
+
+log_assert "Verify used is correct."
+log_onexit cleanup
+
+log_must zfs create $USEDTEST
+check_used $USEDTEST
+
+typeset -i i=0
+typeset -i r_size=0
+mntpnt=$(get_prop mountpoint $USEDTEST)
+while ((i < 5)); do
+ ((r_size=(i+1)*16))
+
+ #usedbyrefreservation
+ log_must zfs set refreservation="$r_size"M $USEDTEST
+
+ #usedbydataset
+ log_must mkfile 16M $mntpnt/file$i
+
+ #usedbychildren
+ log_must zfs create $USEDTEST/fs$i
+ log_must mkfile 16M $mntpnt/fs$i/file$i
+
+ if is_global_zone; then
+ log_must zfs create -V 16M $USEDTEST/vol$i
+ fi
+
+ #usedbysnapshots
+ log_must zfs snapshot -r $USEDTEST@snap$i
+
+ check_used $USEDTEST
+
+ ((i = i + 1))
+done
+
+log_pass "Verify used is correct."
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_002_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_002_pos.ksh
new file mode 100755
index 000000000000..96d2df6c6522
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_002_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 2009 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/snapused/snapused.kshlib
+
+#
+# DESCRIPTION:
+# Verify usedbychildren is correct.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Create sub filesystem and make file in it.
+# 3. Set reservation of the sub filesystem.
+# 4. Create volume under it.
+# 5. Snapshot it.
+# 6. Check usedbychildren is correct.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rR $USEDTEST
+}
+
+log_assert "Verify usedbychildren is correct."
+log_onexit cleanup
+
+log_must zfs create $USEDTEST
+check_usedbychildren $USEDTEST
+
+typeset -i i=0
+typeset -i r_size=0
+mntpnt=$(get_prop mountpoint $USEDTEST)
+while ((i < 5)); do
+ ((r_size=(i+1)*16))
+
+ log_must zfs create $USEDTEST/fs$i
+ log_must zfs set reservation="$r_size"M $USEDTEST/fs$i
+ log_must mkfile 48M $mntpnt/fs$i/file$i
+
+ if is_global_zone; then
+ log_must zfs create -V 32M $USEDTEST/vol$i
+ fi
+
+ log_must zfs snapshot -r $USEDTEST@snap$i
+
+ check_usedbychildren $USEDTEST
+
+ ((i = i + 1))
+done
+
+log_pass "Verify usedbychildren is correct."
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_003_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_003_pos.ksh
new file mode 100755
index 000000000000..d4726ff40cbd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_003_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 2009 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/snapused/snapused.kshlib
+
+#
+# DESCRIPTION:
+# Verify usedbydataset is correct.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Make file in the filesystem.
+# 3. Snapshot it.
+# 4. Clone it and make file in the cloned filesystem.
+# 5. Check usedbydataset is correct.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rR $USEDTEST
+}
+
+log_assert "Verify usedbydataset is correct."
+log_onexit cleanup
+
+log_must zfs create $USEDTEST
+check_usedbydataset $USEDTEST
+
+typeset -i i=0
+typeset -i r_size=0
+mntpnt=$(get_prop mountpoint $USEDTEST)
+while ((i < 5)); do
+ ((r_size=(i+1)*16))
+
+ log_must mkfile 16M $mntpnt/file$i
+ log_must mkfile "$r_size"M $mntpnt/file_var$i
+ log_must zfs snapshot -r $USEDTEST@snap$i
+
+ log_must zfs clone $USEDTEST@snap$i $USEDTEST/cln$i
+ log_must zfs set is:cloned=yes $USEDTEST/cln$i
+
+ mntpnt_cln=$(get_prop mountpoint $USEDTEST/cln$i)
+ log_must mkfile 16M $mntpnt_cln/file_cln$i
+ log_must mkfile "$r_size"M $mntpnt_cln/file_cln_var$i
+
+ check_usedbydataset $USEDTEST
+
+ ((i = i + 1))
+done
+
+log_pass "Verify usedbydataset is correct."
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_004_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_004_pos.ksh
new file mode 100755
index 000000000000..64ca3e2b3508
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_004_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/snapused/snapused.kshlib
+
+#
+# DESCRIPTION:
+# Verify usedbyrefreservation is correct.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Set refreservation of the filesystem.
+# 3. Make file in the filesystem.
+# 4. Create sub filesystem and make file in it.
+# 5. Set refreservation of the sub filesystem.
+# 6. Create volume under it.
+# 7. Snapshot it.
+# 8. Clone it and set refreservation of the cloned filesystem.
+# 9. Makefile the cloned filesystem.
+# 10. Check usedbyrefreservation is correct.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rR $USEDTEST
+}
+
+log_assert "Verify usedbyrefreservation is correct."
+log_onexit cleanup
+
+log_must zfs create $USEDTEST
+check_usedbyrefreservation $USEDTEST
+
+typeset -i i=0
+typeset -i r_size=0
+mntpnt=$(get_prop mountpoint $USEDTEST)
+while ((i < 5)); do
+ ((r_size=(i+1)*16))
+ log_must zfs set refreservation="$r_size"M $USEDTEST
+
+ log_must mkfile 16M $mntpnt/file$i
+
+ log_must zfs create $USEDTEST/fs$i
+ log_must zfs set refreservation="$r_size"M $USEDTEST/fs$i
+ log_must mkfile 16M $mntpnt/fs$i/file$i
+
+ if is_global_zone; then
+ log_must zfs create -V 16M $USEDTEST/vol$i
+ fi
+
+ log_must zfs snapshot -r $USEDTEST@snap$i
+
+ log_must zfs clone $USEDTEST@snap$i $USEDTEST/cln$i
+
+ mntpnt_cln=$(get_prop mountpoint $USEDTEST/cln$i)
+ log_must zfs set refreservation="$r_size"M $USEDTEST/cln$i
+ log_must mkfile 16M $mntpnt_cln/file_cln$i
+
+ check_usedbyrefreservation $USEDTEST
+
+ ((i = i + 1))
+done
+
+log_pass "Verify usedbyrefreservation is correct."
diff --git a/tests/zfs-tests/tests/functional/snapused/snapused_005_pos.ksh b/tests/zfs-tests/tests/functional/snapused/snapused_005_pos.ksh
new file mode 100755
index 000000000000..ac5224caf6dc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/snapused/snapused_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 2009 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/snapused/snapused.kshlib
+
+#
+# DESCRIPTION:
+# Verify usedbysnapshots is correct.
+#
+# STRATEGY:
+# 1. Create a filesystem.
+# 2. Make file in the filesystem.
+# 3. Snapshot it.
+# 4. Check check_usedbysnapshots is correct.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ log_must zfs destroy -rR $USEDTEST
+}
+
+log_assert "Verify usedbysnapshots is correct."
+log_onexit cleanup
+
+log_must zfs create $USEDTEST
+check_usedbysnapshots $USEDTEST
+
+typeset -i i=0
+typeset -i r_size=0
+mntpnt=$(get_prop mountpoint $USEDTEST)
+while ((i < 5)); do
+ ((r_size=(i+1)*16))
+
+ log_must mkfile "$r_size"M $mntpnt/file$i
+
+ log_must zfs snapshot $USEDTEST@snap$i
+ check_usedbysnapshots $USEDTEST
+
+ ((i = i + 1))
+done
+
+log_pass "Verify usedbysnapshots is correct."
diff --git a/tests/zfs-tests/tests/functional/sparse/Makefile.am b/tests/zfs-tests/tests/functional/sparse/Makefile.am
new file mode 100644
index 000000000000..f1b9e04dcefe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/sparse/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/sparse
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ sparse_001_pos.ksh
+
+dist_pkgdata_DATA = \
+ sparse.cfg
diff --git a/tests/zfs-tests/tests/functional/sparse/cleanup.ksh b/tests/zfs-tests/tests/functional/sparse/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/sparse/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/sparse/setup.ksh b/tests/zfs-tests/tests/functional/sparse/setup.ksh
new file mode 100755
index 000000000000..3a45ec8d510d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/sparse/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+disk=${DISKS%% *}
+
+default_setup $disk
diff --git a/tests/zfs-tests/tests/functional/sparse/sparse.cfg b/tests/zfs-tests/tests/functional/sparse/sparse.cfg
new file mode 100644
index 000000000000..0fc669148aa1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/sparse/sparse.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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export TESTFILE=testfile.sparse
+export HOLES_FILESIZE=${HOLES_FILESIZE-"67108864"} # 64 Mb
+export HOLES_BLKSIZE=${HOLES_BLKSIZE-"512"}
+export HOLES_SEED=${HOLES_SEED-""}
+export HOLES_FILEOFFSET=${HOLES_FILEOFFSET-""}
+export HOLES_COUNT=${HOLES_COUNT-"16384"} # FILESIZE/BLKSIZE/8
+export STF_TIMEOUT=3600
+
+export DISKSARRAY=$DISKS
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+set_device_dir
diff --git a/tests/zfs-tests/tests/functional/sparse/sparse_001_pos.ksh b/tests/zfs-tests/tests/functional/sparse/sparse_001_pos.ksh
new file mode 100755
index 000000000000..6ad252adf325
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/sparse/sparse_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/sparse/sparse.cfg
+
+#
+# DESCRIPTION:
+# Holes in ZFS files work correctly.
+#
+# STRATEGY:
+# 1. Open file
+# 2. Write random blocks in random places
+# 3. Read each block back to check for correctness.
+# 4. Repeat steps 2 and 3 lots of times
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Ensure random blocks are read back correctly"
+
+options=""
+options_display="default options"
+
+log_onexit cleanup
+
+[[ -n "$HOLES_FILESIZE" ]] && options=" $options -f $HOLES_FILESIZE "
+
+[[ -n "$HOLES_BLKSIZE" ]] && options="$options -b $HOLES_BLKSIZE "
+
+[[ -n "$HOLES_COUNT" ]] && options="$options -c $HOLES_COUNT "
+
+[[ -n "$HOLES_SEED" ]] && options="$options -s $HOLES_SEED "
+
+[[ -n "$HOLES_FILEOFFSET" ]] && options="$options -o $HOLES_FILEOFFSET "
+
+options="$options -r "
+
+[[ -n "$options" ]] && options_display=$options
+
+log_note "Invoking file_trunc with: $options_display"
+log_must file_trunc $options $TESTDIR/$TESTFILE
+
+typeset dir=$(get_device_dir $DISKS)
+verify_filesys "$TESTPOOL" "$TESTPOOL/$TESTFS" "$dir"
+
+log_pass "Random blocks have been read back correctly."
diff --git a/tests/zfs-tests/tests/functional/suid/.gitignore b/tests/zfs-tests/tests/functional/suid/.gitignore
new file mode 100644
index 000000000000..a9a3db79ba44
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/.gitignore
@@ -0,0 +1 @@
+/suid_write_to_file
diff --git a/tests/zfs-tests/tests/functional/suid/Makefile.am b/tests/zfs-tests/tests/functional/suid/Makefile.am
new file mode 100644
index 000000000000..594d2b77ca8e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/Makefile.am
@@ -0,0 +1,16 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/suid
+
+dist_pkgdata_SCRIPTS = \
+ suid_write_to_suid.ksh \
+ suid_write_to_sgid.ksh \
+ suid_write_to_suid_sgid.ksh \
+ suid_write_to_none.ksh \
+ cleanup.ksh \
+ setup.ksh
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/suid
+
+pkgexec_PROGRAMS = suid_write_to_file
+suid_write_to_file_SOURCES = suid_write_to_file.c
diff --git a/tests/zfs-tests/tests/functional/suid/cleanup.ksh b/tests/zfs-tests/tests/functional/suid/cleanup.ksh
new file mode 100755
index 000000000000..6e41e02faf58
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/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) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/suid/setup.ksh b/tests/zfs-tests/tests/functional/suid/setup.ksh
new file mode 100755
index 000000000000..d04d5568c003
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/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) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_file.c b/tests/zfs-tests/tests/functional/suid/suid_write_to_file.c
new file mode 100644
index 000000000000..571dc553bec2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_file.c
@@ -0,0 +1,133 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL 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) 2019 by Tomohiro Kusumi. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+static void
+test_stat_mode(mode_t extra)
+{
+ struct stat st;
+ int i, fd;
+ char fpath[1024];
+ char *penv[] = {"TESTDIR", "TESTFILE0"};
+ char buf[] = "test";
+ mode_t res;
+ mode_t mode = 0777 | extra;
+
+ /*
+ * Get the environment variable values.
+ */
+ for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
+ if ((penv[i] = getenv(penv[i])) == NULL) {
+ fprintf(stderr, "getenv(penv[%d])\n", i);
+ exit(1);
+ }
+ }
+
+ umask(0);
+ if (stat(penv[0], &st) == -1 && mkdir(penv[0], mode) == -1) {
+ perror("mkdir");
+ exit(2);
+ }
+
+ snprintf(fpath, sizeof (fpath), "%s/%s", penv[0], penv[1]);
+ unlink(fpath);
+ if (stat(fpath, &st) == 0) {
+ fprintf(stderr, "%s exists\n", fpath);
+ exit(3);
+ }
+
+ fd = creat(fpath, mode);
+ if (fd == -1) {
+ perror("creat");
+ exit(4);
+ }
+ close(fd);
+
+ if (setuid(65534) == -1) {
+ perror("setuid");
+ exit(5);
+ }
+
+ fd = open(fpath, O_RDWR);
+ if (fd == -1) {
+ perror("open");
+ exit(6);
+ }
+
+ if (write(fd, buf, sizeof (buf)) == -1) {
+ perror("write");
+ exit(7);
+ }
+ close(fd);
+
+ if (stat(fpath, &st) == -1) {
+ perror("stat");
+ exit(8);
+ }
+ unlink(fpath);
+
+ /* Verify SUID/SGID are dropped */
+ res = st.st_mode & (0777 | S_ISUID | S_ISGID);
+ if (res != (mode & 0777)) {
+ fprintf(stderr, "stat(2) %o\n", res);
+ exit(9);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ const char *name;
+ mode_t extra;
+
+ if (argc < 2) {
+ fprintf(stderr, "Invalid argc\n");
+ exit(1);
+ }
+
+ name = argv[1];
+ if (strcmp(name, "SUID") == 0) {
+ extra = S_ISUID;
+ } else if (strcmp(name, "SGID") == 0) {
+ extra = S_ISGID;
+ } else if (strcmp(name, "SUID_SGID") == 0) {
+ extra = S_ISUID | S_ISGID;
+ } else if (strcmp(name, "NONE") == 0) {
+ extra = 0;
+ } else {
+ fprintf(stderr, "Invalid name %s\n", name);
+ exit(1);
+ }
+
+ test_stat_mode(extra);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_none.ksh
new file mode 100755
index 000000000000..dd01978619f9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_none.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) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify write(2) to regular file by non-owner.
+# Also see https://github.com/pjd/pjdfstest/blob/master/tests/chmod/12.t
+#
+# STRATEGY:
+# 1. creat(2) a file.
+# 2. write(2) to the file with uid=65534.
+# 3. stat(2) the file and verify .st_mode value.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -f $TESTDIR/$TESTFILE0
+}
+
+log_onexit cleanup
+log_note "Verify write(2) to regular file by non-owner"
+
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "NONE"
+
+log_pass "Verify write(2) to regular file by non-owner passed"
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.ksh
new file mode 100755
index 000000000000..49ae2bd1b31e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_sgid.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) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify write(2) to SGID file by non-owner.
+# Also see https://github.com/pjd/pjdfstest/blob/master/tests/chmod/12.t
+#
+# STRATEGY:
+# 1. creat(2) a file with SGID.
+# 2. write(2) to the file with uid=65534.
+# 3. stat(2) the file and verify .st_mode value.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -f $TESTDIR/$TESTFILE0
+}
+
+log_onexit cleanup
+log_note "Verify write(2) to SGID file by non-owner"
+
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SGID"
+
+log_pass "Verify write(2) to SGID file by non-owner passed"
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.ksh
new file mode 100755
index 000000000000..3983aad2e51d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid.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) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify write(2) to SUID file by non-owner.
+# Also see https://github.com/pjd/pjdfstest/blob/master/tests/chmod/12.t
+#
+# STRATEGY:
+# 1. creat(2) a file with SUID.
+# 2. write(2) to the file with uid=65534.
+# 3. stat(2) the file and verify .st_mode value.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -f $TESTDIR/$TESTFILE0
+}
+
+log_onexit cleanup
+log_note "Verify write(2) to SUID file by non-owner"
+
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID"
+
+log_pass "Verify write(2) to SUID file by non-owner passed"
diff --git a/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.ksh
new file mode 100755
index 000000000000..a058c7e7d4bc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/suid/suid_write_to_suid_sgid.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) 2019 by Tomohiro Kusumi. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify write(2) to SUID/SGID file by non-owner.
+# Also see https://github.com/pjd/pjdfstest/blob/master/tests/chmod/12.t
+#
+# STRATEGY:
+# 1. creat(2) a file with SUID/SGID.
+# 2. write(2) to the file with uid=65534.
+# 3. stat(2) the file and verify .st_mode value.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ rm -f $TESTDIR/$TESTFILE0
+}
+
+log_onexit cleanup
+log_note "Verify write(2) to SUID/SGID file by non-owner"
+
+log_must $STF_SUITE/tests/functional/suid/suid_write_to_file "SUID_SGID"
+
+log_pass "Verify write(2) to SUID/SGID file by non-owner passed"
diff --git a/tests/zfs-tests/tests/functional/threadsappend/.gitignore b/tests/zfs-tests/tests/functional/threadsappend/.gitignore
new file mode 100644
index 000000000000..4c8c8cdf34c1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/threadsappend/.gitignore
@@ -0,0 +1 @@
+/threadsappend
diff --git a/tests/zfs-tests/tests/functional/threadsappend/Makefile.am b/tests/zfs-tests/tests/functional/threadsappend/Makefile.am
new file mode 100644
index 000000000000..80f7788c8d86
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/threadsappend/Makefile.am
@@ -0,0 +1,8 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/threadsappend
+
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ threadsappend_001_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/threadsappend/cleanup.ksh b/tests/zfs-tests/tests/functional/threadsappend/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/threadsappend/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/threadsappend/setup.ksh b/tests/zfs-tests/tests/functional/threadsappend/setup.ksh
new file mode 100755
index 000000000000..4fc55cd47803
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/threadsappend/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+
+default_setup ${DISK}
diff --git a/tests/zfs-tests/tests/functional/threadsappend/threadsappend_001_pos.ksh b/tests/zfs-tests/tests/functional/threadsappend/threadsappend_001_pos.ksh
new file mode 100755
index 000000000000..8154214a0ca7
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/threadsappend/threadsappend_001_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 2007 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
+
+#
+# DESCRIPTION:
+#
+# Ensure multiple threads performing write appends to the same ZFS
+# file succeed.
+#
+# STRATEGY:
+# 1) Verify this is a multi-processor system
+# 2) Create multiple threads with each appending to a file
+# 3) Verify that the resulting file is the expected size
+#
+
+verify_runnable "both"
+
+log_assert "Ensure multiple threads performing write appends to the same" \
+ "ZFS file succeed"
+
+#
+# $FILE_SIZE is hardcoded into threadsappend.c and is the expected
+# size of the file after all the threads have appended to it
+#
+typeset -i FILE_SIZE=1310720
+TESTFILE='testfile-threadsappend'
+
+#
+# This test should be run on a multi-processor system because otherwise the FS
+# will not be concurrently used by the threads
+#
+if ! is_mp; then
+ log_fail "This test should be executed on a multi-processor system."
+fi
+
+#
+# zfs_threadsappend tries to append to $TESTFILE using threads
+# so that the resulting file is $FILE_SIZE bytes in size
+#
+log_must threadsappend ${TESTDIR}/${TESTFILE}
+
+#
+# Check the size of the resulting file
+#
+SIZE=`ls -l ${TESTDIR}/${TESTFILE} | awk '{print $5}'`
+if [[ $SIZE -ne $FILE_SIZE ]]; then
+ log_fail "'The length of ${TESTDIR}/${TESTFILE}' doesn't equal 1310720."
+fi
+
+log_pass "Multiple thread appends succeeded. File size as expected"
diff --git a/tests/zfs-tests/tests/functional/tmpfile/.gitignore b/tests/zfs-tests/tests/functional/tmpfile/.gitignore
new file mode 100644
index 000000000000..de014c5256ce
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/.gitignore
@@ -0,0 +1,5 @@
+/tmpfile_test
+/tmpfile_001_pos
+/tmpfile_002_pos
+/tmpfile_003_pos
+/tmpfile_stat_mode
diff --git a/tests/zfs-tests/tests/functional/tmpfile/Makefile.am b/tests/zfs-tests/tests/functional/tmpfile/Makefile.am
new file mode 100644
index 000000000000..35a1f44c1693
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/Makefile.am
@@ -0,0 +1,16 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/tmpfile
+
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/tmpfile
+
+pkgexec_PROGRAMS = tmpfile_test tmpfile_001_pos tmpfile_002_pos \
+ tmpfile_003_pos tmpfile_stat_mode
+tmpfile_test_SOURCES= tmpfile_test.c
+tmpfile_001_pos_SOURCES = tmpfile_001_pos.c
+tmpfile_002_pos_SOURCES = tmpfile_002_pos.c
+tmpfile_003_pos_SOURCES = tmpfile_003_pos.c
diff --git a/tests/zfs-tests/tests/functional/tmpfile/cleanup.ksh b/tests/zfs-tests/tests/functional/tmpfile/cleanup.ksh
new file mode 100755
index 000000000000..3166bd6ec16e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/tmpfile/setup.ksh b/tests/zfs-tests/tests/functional/tmpfile/setup.ksh
new file mode 100755
index 000000000000..bc00a2a22c5a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/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.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+DISK=${DISKS%% *}
+default_setup_noexit $DISK
+
+if ! $STF_SUITE/tests/functional/tmpfile/tmpfile_test $TESTDIR; then
+ default_cleanup_noexit
+ log_unsupported "The kernel/filesystem doesn't support O_TMPFILE"
+fi
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_001_pos.c b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_001_pos.c
new file mode 100644
index 000000000000..b0c236081928
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_001_pos.c
@@ -0,0 +1,109 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/xattr.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+
+/* backward compat in case it's not defined */
+#ifndef O_TMPFILE
+#define O_TMPFILE (020000000|O_DIRECTORY)
+#endif
+
+/*
+ * DESCRIPTION:
+ * Verify we can create tmpfile.
+ *
+ * STRATEGY:
+ * 1. open(2) with O_TMPFILE.
+ * 2. write(2) random data to it, then read(2) and compare.
+ * 3. fsetxattr(2) random data, then fgetxattr(2) and compare.
+ * 4. Verify the above operations run successfully.
+ *
+ */
+
+#define BSZ 64
+
+static void
+fill_random(char *buf, int len)
+{
+ int i;
+ srand(time(NULL));
+ for (i = 0; i < len; i++) {
+ buf[i] = (char)rand();
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ int i, fd;
+ char buf1[BSZ], buf2[BSZ] = {};
+ char *penv[] = {"TESTDIR"};
+
+ (void) fprintf(stdout, "Verify O_TMPFILE is working properly.\n");
+
+ /*
+ * Get the environment variable values.
+ */
+ for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
+ if ((penv[i] = getenv(penv[i])) == NULL) {
+ (void) fprintf(stderr, "getenv(penv[%d])\n", i);
+ exit(1);
+ }
+ }
+
+ fill_random(buf1, BSZ);
+
+ fd = open(penv[0], O_RDWR|O_TMPFILE, 0666);
+ if (fd < 0) {
+ perror("open");
+ exit(2);
+ }
+
+ if (write(fd, buf1, BSZ) < 0) {
+ perror("write");
+ close(fd);
+ exit(3);
+ }
+
+ if (pread(fd, buf2, BSZ, 0) < 0) {
+ perror("pread");
+ close(fd);
+ exit(4);
+ }
+
+ if (memcmp(buf1, buf2, BSZ) != 0) {
+ fprintf(stderr, "data corrupted\n");
+ close(fd);
+ exit(5);
+ }
+
+ memset(buf2, 0, BSZ);
+
+ if (fsetxattr(fd, "user.test", buf1, BSZ, 0) < 0) {
+ perror("fsetxattr");
+ close(fd);
+ exit(6);
+ }
+
+ if (fgetxattr(fd, "user.test", buf2, BSZ) < 0) {
+ perror("fgetxattr");
+ close(fd);
+ exit(7);
+ }
+
+ if (memcmp(buf1, buf2, BSZ) != 0) {
+ fprintf(stderr, "xattr corrupted\n");
+ close(fd);
+ exit(8);
+ }
+
+ close(fd);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c
new file mode 100644
index 000000000000..c92e6127d6a3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_002_pos.c
@@ -0,0 +1,98 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+/* backward compat in case it's not defined */
+#ifndef O_TMPFILE
+#define O_TMPFILE (020000000|O_DIRECTORY)
+#endif
+
+/*
+ * DESCRIPTION:
+ * Verify we can link tmpfile.
+ *
+ * STRATEGY:
+ * 1. open(2) with O_TMPFILE.
+ * 2. linkat(2).
+ * 3. freeze the pool, export and re-import the pool.
+ * 3. stat(2) the path to verify it has been created.
+ *
+ */
+
+int
+main(int argc, char *argv[])
+{
+ int i, fd, ret;
+ char spath[1024], dpath[1024];
+ char *penv[] = {"TESTDIR", "TESTFILE0"};
+ struct stat sbuf;
+
+ (void) fprintf(stdout, "Verify O_TMPFILE file can be linked.\n");
+
+ /*
+ * Get the environment variable values.
+ */
+ for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
+ if ((penv[i] = getenv(penv[i])) == NULL) {
+ (void) fprintf(stderr, "getenv(penv[%d])\n", i);
+ exit(1);
+ }
+ }
+
+ fd = open(penv[0], O_RDWR|O_TMPFILE, 0666);
+ if (fd < 0) {
+ perror("open");
+ exit(2);
+ }
+
+ snprintf(spath, 1024, "/proc/self/fd/%d", fd);
+ snprintf(dpath, 1024, "%s/%s", penv[0], penv[1]);
+ if (linkat(AT_FDCWD, spath, AT_FDCWD, dpath, AT_SYMLINK_FOLLOW) < 0) {
+ perror("linkat");
+ close(fd);
+ exit(3);
+ }
+
+ if ((ret = system("sudo zpool freeze $TESTPOOL"))) {
+ if (ret == -1)
+ perror("system \"zpool freeze\"");
+ else
+ fprintf(stderr, "zpool freeze exits with %d\n",
+ WEXITSTATUS(ret));
+ exit(4);
+ }
+
+ close(fd);
+
+ if ((ret = system("sudo zpool export $TESTPOOL"))) {
+ if (ret == -1)
+ perror("system \"zpool export\"");
+ else
+ fprintf(stderr, "zpool export exits with %d\n",
+ WEXITSTATUS(ret));
+ exit(4);
+ }
+
+ if ((ret = system("sudo zpool import $TESTPOOL"))) {
+ if (ret == -1)
+ perror("system \"zpool import\"");
+ else
+ fprintf(stderr, "zpool import exits with %d\n",
+ WEXITSTATUS(ret));
+ exit(4);
+ }
+
+ if (stat(dpath, &sbuf) < 0) {
+ perror("stat");
+ unlink(dpath);
+ exit(5);
+ }
+ unlink(dpath);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_003_pos.c b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_003_pos.c
new file mode 100644
index 000000000000..477ef3f81948
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_003_pos.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+
+/* backward compat in case it's not defined */
+#ifndef O_TMPFILE
+#define O_TMPFILE (020000000|O_DIRECTORY)
+#endif
+
+/*
+ * DESCRIPTION:
+ * Verify O_EXCL tmpfile cannot be linked.
+ *
+ * STRATEGY:
+ * 1. open(2) with O_TMPFILE|O_EXCL.
+ * 2. linkat(2).
+ * 3. stat(2) the path to verify it wasn't created.
+ *
+ */
+
+int
+main(int argc, char *argv[])
+{
+ int i, fd;
+ char spath[1024], dpath[1024];
+ char *penv[] = {"TESTDIR", "TESTFILE0"};
+ struct stat sbuf;
+
+ (void) fprintf(stdout, "Verify O_EXCL tmpfile cannot be linked.\n");
+
+ /*
+ * Get the environment variable values.
+ */
+ for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
+ if ((penv[i] = getenv(penv[i])) == NULL) {
+ (void) fprintf(stderr, "getenv(penv[%d])\n", i);
+ exit(1);
+ }
+ }
+
+ fd = open(penv[0], O_RDWR|O_TMPFILE|O_EXCL, 0666);
+ if (fd < 0) {
+ perror("open");
+ exit(2);
+ }
+
+ snprintf(spath, 1024, "/proc/self/fd/%d", fd);
+ snprintf(dpath, 1024, "%s/%s", penv[0], penv[1]);
+ if (linkat(AT_FDCWD, spath, AT_FDCWD, dpath, AT_SYMLINK_FOLLOW) == 0) {
+ fprintf(stderr, "linkat returns successfully\n");
+ close(fd);
+ exit(3);
+ }
+
+ if (stat(dpath, &sbuf) == 0) {
+ fprintf(stderr, "stat returns successfully\n");
+ close(fd);
+ exit(4);
+ }
+ close(fd);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c
new file mode 100644
index 000000000000..bf71d429c3fd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_stat_mode.c
@@ -0,0 +1,121 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL 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) 2019 by Tomohiro Kusumi. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* backward compat in case it's not defined */
+#ifndef O_TMPFILE
+#define O_TMPFILE (020000000|O_DIRECTORY)
+#endif
+
+/*
+ * DESCRIPTION:
+ * Verify stat(2) for O_TMPFILE file considers umask.
+ *
+ * STRATEGY:
+ * 1. open(2) with O_TMPFILE.
+ * 2. linkat(2).
+ * 3. fstat(2)/stat(2) and verify .st_mode value.
+ */
+
+static void
+test_stat_mode(mode_t mask)
+{
+ struct stat st, fst;
+ int i, fd;
+ char spath[1024], dpath[1024];
+ char *penv[] = {"TESTDIR", "TESTFILE0"};
+ mode_t masked = 0777 & ~mask;
+ mode_t mode;
+
+ /*
+ * Get the environment variable values.
+ */
+ for (i = 0; i < sizeof (penv) / sizeof (char *); i++) {
+ if ((penv[i] = getenv(penv[i])) == NULL) {
+ fprintf(stderr, "getenv(penv[%d])\n", i);
+ exit(1);
+ }
+ }
+
+ umask(mask);
+ fd = open(penv[0], O_RDWR|O_TMPFILE, 0777);
+ if (fd == -1) {
+ perror("open");
+ exit(2);
+ }
+
+ if (fstat(fd, &fst) == -1) {
+ perror("fstat");
+ close(fd);
+ exit(3);
+ }
+
+ snprintf(spath, sizeof (spath), "/proc/self/fd/%d", fd);
+ snprintf(dpath, sizeof (dpath), "%s/%s", penv[0], penv[1]);
+
+ unlink(dpath);
+ if (linkat(AT_FDCWD, spath, AT_FDCWD, dpath, AT_SYMLINK_FOLLOW) == -1) {
+ perror("linkat");
+ close(fd);
+ exit(4);
+ }
+ close(fd);
+
+ if (stat(dpath, &st) == -1) {
+ perror("stat");
+ exit(5);
+ }
+ unlink(dpath);
+
+ /* Verify fstat(2) result */
+ mode = fst.st_mode & 0777;
+ if (mode != masked) {
+ fprintf(stderr, "fstat(2) %o != %o\n", mode, masked);
+ exit(6);
+ }
+
+ /* Verify stat(2) result */
+ mode = st.st_mode & 0777;
+ if (mode != masked) {
+ fprintf(stderr, "stat(2) %o != %o\n", mode, masked);
+ exit(7);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ fprintf(stdout, "Verify stat(2) for O_TMPFILE file considers umask.\n");
+
+ test_stat_mode(0022);
+ test_stat_mode(0077);
+
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/tmpfile/tmpfile_test.c b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_test.c
new file mode 100644
index 000000000000..91527ac5e0e5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/tmpfile/tmpfile_test.c
@@ -0,0 +1,53 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+/* backward compat in case it's not defined */
+#ifndef O_TMPFILE
+#define O_TMPFILE (020000000|O_DIRECTORY)
+#endif
+
+/*
+ * DESCRIPTION:
+ * Check if the kernel support O_TMPFILE.
+ */
+
+int
+main(int argc, char *argv[])
+{
+ int fd;
+ struct stat buf;
+
+ if (argc < 2) {
+ fprintf(stderr, "Usage: %s dir\n", argv[0]);
+ return (2);
+ }
+ if (stat(argv[1], &buf) < 0) {
+ perror("stat");
+ return (2);
+ }
+ if (!S_ISDIR(buf.st_mode)) {
+ fprintf(stderr, "\"%s\" is not a directory\n", argv[1]);
+ return (2);
+ }
+
+ fd = open(argv[1], O_TMPFILE | O_WRONLY, 0666);
+ if (fd < 0) {
+ if (errno == EISDIR) {
+ fprintf(stderr,
+ "The kernel doesn't support O_TMPFILE\n");
+ return (1);
+ } else if (errno == EOPNOTSUPP) {
+ fprintf(stderr,
+ "The filesystem doesn't support O_TMPFILE\n");
+ return (2);
+ }
+ perror("open");
+ } else {
+ close(fd);
+ }
+ return (0);
+}
diff --git a/tests/zfs-tests/tests/functional/trim/Makefile.am b/tests/zfs-tests/tests/functional/trim/Makefile.am
new file mode 100644
index 000000000000..8917ed726e90
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/Makefile.am
@@ -0,0 +1,12 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/trim
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ trim.kshlib \
+ trim.cfg \
+ autotrim_integrity.ksh \
+ autotrim_config.ksh \
+ autotrim_trim_integrity.ksh \
+ trim_integrity.ksh \
+ trim_config.ksh \
+ trim_l2arc.ksh
diff --git a/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh b/tests/zfs-tests/tests/functional/trim/autotrim_config.ksh
new file mode 100755
index 000000000000..d48ee45d03b1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/autotrim_config.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) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/trim/trim.kshlib
+. $STF_SUITE/tests/functional/trim/trim.cfg
+
+#
+# DESCRIPTION:
+# Check various pool geometries stripe, mirror, raidz)
+#
+# STRATEGY:
+# 1. Create a pool on file vdevs to trim.
+# 2. Set 'autotrim=on' on pool.
+# 3. Fill the pool to a known percentage of capacity.
+# 4. Verify the vdevs contain 75% or more allocated blocks.
+# 5. Remove all files making it possible to trim the entire pool.
+# 6. Wait for auto trim to issue trim IOs for the free blocks.
+# 7. Verify the disks contain 30% or less allocated blocks.
+# 8. Repeat for test for striped, mirrored, and RAIDZ pools.
+
+verify_runnable "global"
+
+log_assert "Set 'autotrim=on' verify pool disks were trimmed"
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must rm -f $TRIM_VDEVS
+
+ log_must set_tunable64 TRIM_EXTENT_BYTES_MIN $trim_extent_bytes_min
+ log_must set_tunable64 TRIM_TXG_BATCH $trim_txg_batch
+ log_must set_tunable64 VDEV_MIN_MS_COUNT $vdev_min_ms_count
+}
+log_onexit cleanup
+
+# 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
+
+# Reduced TRIM_TXG_BATCH to make trimming more frequent.
+typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
+log_must set_tunable64 TRIM_TXG_BATCH 8
+
+# Increased metaslabs to better simulate larger more realistic devices.
+typeset vdev_min_ms_count=$(get_tunable VDEV_MIN_MS_COUNT)
+log_must set_tunable64 VDEV_MIN_MS_COUNT 32
+
+typeset VDEV_MAX_MB=$(( floor(4 * MINVDEVSIZE * 0.75 / 1024 / 1024) ))
+typeset VDEV_MIN_MB=$(( floor(4 * MINVDEVSIZE * 0.30 / 1024 / 1024) ))
+
+for type in "" "mirror" "raidz2"; do
+
+ if [[ "$type" = "" ]]; then
+ VDEVS="$TRIM_VDEV1"
+ elif [[ "$type" = "mirror" ]]; then
+ VDEVS="$TRIM_VDEV1 $TRIM_VDEV2"
+ else
+ VDEVS="$TRIM_VDEV1 $TRIM_VDEV2 $TRIM_VDEV3"
+ fi
+
+ log_must truncate -s $((4 * MINVDEVSIZE)) $VDEVS
+ log_must zpool create -f $TESTPOOL $VDEVS
+ log_must zpool set autotrim=on $TESTPOOL
+
+ typeset availspace=$(get_prop available $TESTPOOL)
+ typeset fill_mb=$(( floor(availspace * 0.90 / 1024 / 1024) ))
+
+ # Fill the pool, verify the vdevs are no longer sparse.
+ file_write -o create -f /$TESTPOOL/file -b 1048576 -c $fill_mb -d R
+ verify_vdevs "-ge" "$VDEV_MAX_MB" $VDEVS
+
+ # Remove the file, wait for trim, verify the vdevs are now sparse.
+ log_must rm /$TESTPOOL/file
+ wait_trim_io $TESTPOOL "ind" 64
+ verify_vdevs "-le" "$VDEV_MIN_MB" $VDEVS
+
+ log_must zpool destroy $TESTPOOL
+ log_must rm -f $VDEVS
+done
+
+log_pass "Auto trim successfully shrunk vdevs"
diff --git a/tests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh b/tests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh
new file mode 100755
index 000000000000..6af877241d0d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/autotrim_integrity.ksh
@@ -0,0 +1,87 @@
+#!/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/trim/trim.kshlib
+. $STF_SUITE/tests/functional/trim/trim.cfg
+
+#
+# DESCRIPTION:
+# Verify automatic trim pool data integrity.
+#
+# STRATEGY:
+# 1. Create a pool on sparse file vdevs to trim.
+# 2. Set autotrim=on to enable asynchronous pool trimming.
+# 3. Generate some interesting pool data which can be trimmed.
+# 4. Verify trim IOs of the expected type were issued for the pool.
+# 5. Verify data integrity of the pool after trim.
+# 6. Repeat test for striped, mirrored, and RAIDZ pools.
+
+verify_runnable "global"
+
+log_assert "Set 'autotrim=on' pool property verify pool data integrity"
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must rm -f $TRIM_VDEVS
+
+ log_must set_tunable64 TRIM_EXTENT_BYTES_MIN $trim_extent_bytes_min
+ log_must set_tunable64 TRIM_TXG_BATCH $trim_txg_batch
+}
+log_onexit cleanup
+
+# 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
+
+# Reduced TRIM_TXG_BATCH to make trimming more frequent.
+typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
+log_must set_tunable64 TRIM_TXG_BATCH 8
+
+for type in "" "mirror" "raidz" "raidz2" "raidz3"; do
+ log_must truncate -s 1G $TRIM_VDEVS
+
+ log_must zpool create -f $TESTPOOL $type $TRIM_VDEVS
+ log_must zpool set autotrim=on $TESTPOOL
+
+ # Add and remove data from the pool in a random fashion in order
+ # to generate a variety of interesting ranges to be auto trimmed.
+ for n in {0..10}; do
+ dir="/$TESTPOOL/autotrim-$((RANDOM % 5))"
+ filesize=$((4096 + ((RANDOM * 691) % 131072) ))
+ log_must rm -rf $dir
+ log_must fill_fs $dir 10 10 $filesize 1 R
+ zpool sync
+ done
+ log_must du -hs /$TESTPOOL
+
+ verify_trim_io $TESTPOOL "ind" 10
+ verify_pool $TESTPOOL
+
+ log_must zpool destroy $TESTPOOL
+ log_must rm -f $TRIM_VDEVS
+done
+
+log_pass "Automatic trim successfully validated"
diff --git a/tests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh b/tests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh
new file mode 100755
index 000000000000..a0dd1c88496d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/autotrim_trim_integrity.ksh
@@ -0,0 +1,92 @@
+#!/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/trim/trim.kshlib
+. $STF_SUITE/tests/functional/trim/trim.cfg
+
+#
+# DESCRIPTION:
+# Verify automatic trim and manual trim coexist correctly.
+#
+# STRATEGY:
+# 1. Create a pool on sparse file vdevs to trim.
+# 2. Set autotrim=on to enable asynchronous pool trimming.
+# 3. Generate some interesting pool data which can be trimmed.
+# 4. While generating data issue manual trims.
+# 4. Verify trim IOs of the expected type were issued for the pool.
+# 5. Verify data integrity of the pool after trim.
+# 6. Repeat test for striped, mirrored, and RAIDZ pools.
+
+verify_runnable "global"
+
+log_assert "Set 'autotrim=on', run 'zpool trim' and verify pool data integrity"
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must rm -f $TRIM_VDEVS
+
+ log_must set_tunable64 TRIM_EXTENT_BYTES_MIN $trim_extent_bytes_min
+ log_must set_tunable64 TRIM_TXG_BATCH $trim_txg_batch
+}
+log_onexit cleanup
+
+# 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
+
+# Reduced TRIM_TXG_BATCH to make trimming more frequent.
+typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
+log_must set_tunable64 TRIM_TXG_BATCH 8
+
+for type in "" "mirror" "raidz" "raidz2" "raidz3"; do
+ log_must truncate -s 1G $TRIM_VDEVS
+
+ log_must zpool create -f $TESTPOOL $type $TRIM_VDEVS
+ log_must zpool set autotrim=on $TESTPOOL
+
+ # Add and remove data from the pool in a random fashion in order
+ # to generate a variety of interesting ranges to be auto trimmed.
+ for n in {0..10}; do
+ dir="/$TESTPOOL/autotrim-$((RANDOM % 5))"
+ filesize=$((4096 + ((RANDOM * 691) % 131072) ))
+ log_must rm -rf $dir
+ log_must fill_fs $dir 10 10 $filesize 1 R
+ zpool sync
+
+ if [[ $((n % 4)) -eq 0 ]]; then
+ log_must timeout 120 zpool trim -w $TESTPOOL
+ fi
+ done
+ log_must du -hs /$TESTPOOL
+
+ verify_trim_io $TESTPOOL "ind" 10
+ verify_pool $TESTPOOL
+
+ log_must zpool destroy $TESTPOOL
+ log_must rm -f $TRIM_VDEVS
+done
+
+log_pass "Automatic trim and manual trim coexistence successfully validated"
diff --git a/tests/zfs-tests/tests/functional/trim/cleanup.ksh b/tests/zfs-tests/tests/functional/trim/cleanup.ksh
new file mode 100755
index 000000000000..29d14044a35c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/cleanup.ksh
@@ -0,0 +1,48 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+#!/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
+
+TRIM_DIR="$TEST_BASE_DIR"
+TRIM_VDEVS="$TRIM_DIR/trim-vdev1 $TRIM_DIR/trim-vdev2 \
+ $TRIM_DIR/trim-vdev3 $TRIM_DIR/trim-vdev4"
+
+rm -rf $TRIM_VDEVS
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/trim/setup.ksh b/tests/zfs-tests/tests/functional/trim/setup.ksh
new file mode 100755
index 000000000000..09489600b3dc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/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/trim/trim.cfg b/tests/zfs-tests/tests/functional/trim/trim.cfg
new file mode 100644
index 000000000000..91adb7624326
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/trim.cfg
@@ -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 (c) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+TRIM_DIR="$TEST_BASE_DIR"
+TRIM_VDEV1="$TRIM_DIR/trim-vdev1"
+TRIM_VDEV2="$TRIM_DIR/trim-vdev2"
+TRIM_VDEV3="$TRIM_DIR/trim-vdev3"
+TRIM_VDEV4="$TRIM_DIR/trim-vdev4"
+TRIM_VDEVS="$TRIM_VDEV1 $TRIM_VDEV2 $TRIM_VDEV3 $TRIM_VDEV4"
diff --git a/tests/zfs-tests/tests/functional/trim/trim.kshlib b/tests/zfs-tests/tests/functional/trim/trim.kshlib
new file mode 100644
index 000000000000..bede946a09c5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/trim.kshlib
@@ -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) 2019 by Tim Chase. All rights reserved.
+# Copyright (c) 2019 Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# Get the actual size on disk for the provided file.
+#
+function get_size_mb
+{
+ typeset rval=$(du --block-size 1048576 -s "$1" | awk '{print $1}')
+ echo -n "$rval"
+}
+
+#
+# Get the number of trim IOs issued for the pool (ind or agg).
+#
+function get_trim_io
+{
+ typeset pool="${1-:$TESTPOOL}"
+ typeset type="${2-:ind}"
+ typeset vdev="${3}"
+ typeset rval
+
+ # Sum the ind or agg columns of the trim request size histogram.
+ case "$type" in
+ "ind")
+ rval=$(zpool iostat -pr $pool $vdev | awk \
+ '$1 ~ /[0-9].*/ { sum += $12 } END { print sum }')
+ echo -n "$rval"
+ ;;
+ "agg")
+ rval=$(zpool iostat -pr $pool $vdev | awk \
+ '$1 ~ /[0-9].*/ { sum += $13 } END { print sum }')
+ echo -n "$rval"
+ ;;
+ *)
+ log_fail "Type must be 'ind' or 'agg'"
+ ;;
+ esac
+}
+
+#
+# Verify that trim IOs were send to devices in the pool.
+#
+function verify_trim_io
+{
+ typeset pool="${1:-$TESTPOOL}"
+ typeset type="${2:-ind}"
+ typeset min_trim_ios=${3:-100}
+ typeset vdev="${4}"
+ typeset ios
+
+ ios=$(get_trim_io $pool $type $vdev)
+ if [[ $ios -ge $min_trim_ios ]]; then
+ log_note "Issued $ios $type trim IOs for pool $pool"
+ else
+ log_fail "Too few trim IOs issued $ios/$min_trim_ios"
+ fi
+}
+
+#
+# Run N txgs which should be enough to trim the entire pool.
+#
+function wait_trim_io # pool type txgs
+{
+ typeset pool="${1-:$TESTPOOL}"
+ typeset type="${2-:ind}"
+ typeset txgs=${3:-10}
+ typeset timeout=120
+ typeset stop_time=$(( $(date +%s) + $timeout ))
+
+ typeset -i i=0
+ while [[ $i -lt $txgs ]]; do
+ if [ "$(date +%s)" -ge $stop_time ]; then
+ log_fail "Exceeded trim time limit of ${timeout}s"
+ return
+ fi
+
+ zpool sync -f
+ ((i = i + 1))
+ done
+
+ typeset ios=$(get_trim_io $pool $type)
+ log_note "Waited for $txgs txgs, $ios $type TRIM IOs"
+}
+
+#
+# Verify that file vdevs against a target value.
+#
+function verify_vdevs # op size vdevs
+{
+ typeset tgt_op=$1
+ typeset tgt_size=$2
+ shift 2
+ typeset vdevs=$@
+
+ for vdev in $vdevs; do
+ typeset size=$(get_size_mb $vdev)
+ if test $size $tgt_op $tgt_size; then
+ log_note "Success $vdev is $size MB which is $tgt_op" \
+ "than $tgt_size MB"
+ else
+ log_fail "Failure $vdev is $size MB which is not" \
+ "$tgt_op than $tgt_size MB"
+ fi
+ done
+}
diff --git a/tests/zfs-tests/tests/functional/trim/trim_config.ksh b/tests/zfs-tests/tests/functional/trim/trim_config.ksh
new file mode 100755
index 000000000000..44f187cc646c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/trim_config.ksh
@@ -0,0 +1,102 @@
+#!/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/trim/trim.kshlib
+. $STF_SUITE/tests/functional/trim/trim.cfg
+
+#
+# DESCRIPTION:
+# Check various pool geometries stripe, mirror, raidz
+#
+# STRATEGY:
+# 1. Create a pool on file vdevs to trim.
+# 2. Fill the pool to a known percentage of capacity.
+# 3. Verify the vdevs contain 75% or more allocated blocks.
+# 4. Remove all files making it possible to trim the entire pool.
+# 5. Manually trim the pool.
+# 6. Wait for trim to issue trim IOs for the free blocks.
+# 7. Verify the disks contain 30% or less allocated blocks.
+# 8. Repeat for test for striped, mirrored, and RAIDZ pools.
+
+verify_runnable "global"
+
+log_assert "Run 'zpool trim' verify pool disks were trimmed"
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must rm -f $TRIM_VDEVS
+
+ log_must set_tunable64 TRIM_EXTENT_BYTES_MIN $trim_extent_bytes_min
+ log_must set_tunable64 TRIM_TXG_BATCH $trim_txg_batch
+ log_must set_tunable64 VDEV_MIN_MS_COUNT $vdev_min_ms_count
+}
+log_onexit cleanup
+
+# 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
+
+# Reduced TRIM_TXG_BATCH to make trimming more frequent.
+typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
+log_must set_tunable64 TRIM_TXG_BATCH 8
+
+# Increased metaslabs to better simulate larger more realistic devices.
+typeset vdev_min_ms_count=$(get_tunable VDEV_MIN_MS_COUNT)
+log_must set_tunable64 VDEV_MIN_MS_COUNT 32
+
+typeset VDEV_MAX_MB=$(( floor(4 * MINVDEVSIZE * 0.75 / 1024 / 1024) ))
+typeset VDEV_MIN_MB=$(( floor(4 * MINVDEVSIZE * 0.30 / 1024 / 1024) ))
+
+for type in "" "mirror" "raidz2"; do
+
+ if [[ "$type" = "" ]]; then
+ VDEVS="$TRIM_VDEV1"
+ elif [[ "$type" = "mirror" ]]; then
+ VDEVS="$TRIM_VDEV1 $TRIM_VDEV2"
+ else
+ VDEVS="$TRIM_VDEV1 $TRIM_VDEV2 $TRIM_VDEV3"
+ fi
+
+ log_must truncate -s $((4 * MINVDEVSIZE)) $VDEVS
+ log_must zpool create -f $TESTPOOL $type $VDEVS
+
+ typeset availspace=$(get_prop available $TESTPOOL)
+ typeset fill_mb=$(( floor(availspace * 0.90 / 1024 / 1024) ))
+
+ # Fill the pool, verify the vdevs are no longer sparse.
+ file_write -o create -f /$TESTPOOL/file -b 1048576 -c $fill_mb -d R
+ verify_vdevs "-ge" "$VDEV_MAX_MB" $VDEVS
+
+ # Remove the file, issue trim, verify the vdevs are now sparse.
+ log_must rm /$TESTPOOL/file
+ log_must timeout 120 zpool trim -w $TESTPOOL
+ verify_vdevs "-le" "$VDEV_MIN_MB" $VDEVS
+
+ log_must zpool destroy $TESTPOOL
+ log_must rm -f $VDEVS
+done
+
+log_pass "Manual trim successfully shrunk vdevs"
diff --git a/tests/zfs-tests/tests/functional/trim/trim_integrity.ksh b/tests/zfs-tests/tests/functional/trim/trim_integrity.ksh
new file mode 100755
index 000000000000..e25b52747c69
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/trim_integrity.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/trim/trim.kshlib
+. $STF_SUITE/tests/functional/trim/trim.cfg
+
+#
+# DESCRIPTION:
+# Verify manual trim pool data integrity.
+#
+# STRATEGY:
+# 1. Create a pool on sparse file vdevs to trim.
+# 2. Generate some interesting pool data which can be trimmed.
+# 3. Manually trim the pool.
+# 4. Verify trim IOs of the expected type were issued for the pool.
+# 5. Verify data integrity of the pool after trim.
+# 6. Repeat test for striped, mirrored, and RAIDZ pools.
+
+verify_runnable "global"
+
+log_assert "Run 'zpool trim' and verify pool data integrity"
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must rm -f $TRIM_VDEVS
+
+ log_must set_tunable64 TRIM_EXTENT_BYTES_MIN $trim_extent_bytes_min
+ log_must set_tunable64 TRIM_TXG_BATCH $trim_txg_batch
+}
+log_onexit cleanup
+
+# 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
+
+# Reduced TRIM_TXG_BATCH to make trimming more frequent.
+typeset trim_txg_batch=$(get_tunable TRIM_TXG_BATCH)
+log_must set_tunable64 TRIM_TXG_BATCH 8
+
+for type in "" "mirror" "raidz" "raidz2" "raidz3"; do
+ log_must truncate -s 1G $TRIM_VDEVS
+
+ log_must zpool create -f $TESTPOOL $type $TRIM_VDEVS
+
+ # Add and remove data from the pool in a random fashion in order
+ # to generate a variety of interesting ranges to be manually trimmed.
+ for n in {0..10}; do
+ dir="/$TESTPOOL/trim-$((RANDOM % 5))"
+ filesize=$((4096 + ((RANDOM * 691) % 131072) ))
+ log_must rm -rf $dir
+ log_must fill_fs $dir 10 10 $filesize 1 R
+ zpool sync
+ done
+ log_must du -hs /$TESTPOOL
+
+ log_must timeout 120 zpool trim -w $TESTPOOL
+
+ verify_trim_io $TESTPOOL "ind" 10
+ verify_pool $TESTPOOL
+
+ log_must zpool destroy $TESTPOOL
+ log_must rm -f $TRIM_VDEVS
+done
+
+log_pass "Manual trim successfully validated"
diff --git a/tests/zfs-tests/tests/functional/trim/trim_l2arc.ksh b/tests/zfs-tests/tests/functional/trim/trim_l2arc.ksh
new file mode 100755
index 000000000000..ecf9f3424eb5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/trim/trim_l2arc.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
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/trim/trim.kshlib
+. $STF_SUITE/tests/functional/trim/trim.cfg
+
+#
+# DESCRIPTION:
+# Verify trimming of L2ARC
+#
+# STRATEGY:
+# 1. Set 'l2arc_trim_ahead = 1' and `l2arc_write_size = 64MB`.
+# 2. Create a pool on file vdevs to trim.
+# 3. Verify the cache device was trimmed.
+# 4. Fill the pool with a file larger than the L2ARC vdev.
+# 5. Randomly read the previous written file long enough for the
+# L2ARC vdev to be filled and overwritten 5 times.
+# 6. Verify trim IOs of the expected type were issued for the pool.
+# 7. Verify the allocated space on the cache device is less than
+# its size.
+#
+
+verify_runnable "global"
+
+log_assert "Trim of L2ARC succeeds."
+
+function cleanup
+{
+ if poolexists $TESTPOOL; then
+ destroy_pool $TESTPOOL
+ fi
+
+ log_must rm -f $VDEVS
+ log_must set_tunable32 L2ARC_TRIM_AHEAD $l2arc_trimahead
+ log_must set_tunable32 L2ARC_WRITE_MAX $l2arc_writemax
+}
+log_onexit cleanup
+
+# The cache device $TRIM_VDEV2 has to be small enough, so that
+# dev->l2ad_hand loops around and dev->l2ad_first=0. Otherwise
+# l2arc_evict() exits before evicting/trimming.
+typeset l2arc_trimahead=$(get_tunable L2ARC_TRIM_AHEAD)
+typeset l2arc_writemax=$(get_tunable L2ARC_WRITE_MAX)
+log_must set_tunable32 L2ARC_TRIM_AHEAD 1
+log_must set_tunable32 L2ARC_WRITE_MAX $((64 * 1024 * 1024))
+VDEVS="$TRIM_VDEV1 $TRIM_VDEV2"
+log_must truncate -s $((MINVDEVSIZE)) $TRIM_VDEV2
+log_must truncate -s $((4 * MINVDEVSIZE)) $TRIM_VDEV1
+typeset VDEV_MIN_MB=$((MINVDEVSIZE * 0.30 / 1024 / 1024))
+
+log_must zpool create -f $TESTPOOL $TRIM_VDEV1 cache $TRIM_VDEV2
+verify_vdevs "-le" "$VDEV_MIN_MB" $TRIM_VDEV2
+
+typeset fill_mb=$(( floor(2 * MINVDEVSIZE) ))
+export DIRECTORY=/$TESTPOOL
+export NUMJOBS=1
+export FILE_SIZE=${fill_mb}
+export PERF_RANDSEED=1234
+export PERF_COMPPERCENT=66
+export PERF_COMPCHUNK=0
+export RUNTIME=30
+export BLOCKSIZE=128K
+export SYNC_TYPE=0
+export DIRECT=1
+
+# Write to the pool.
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+
+# Read randomly from the pool to fill L2ARC.
+export RUNTIME=30
+log_must fio $FIO_SCRIPTS/random_reads.fio
+
+export RUNTIME=1
+typeset do_once=true
+while $do_once || [[ $l2_size1 -le $l2_size2 ]]; do
+ typeset l2_size1=$(get_arcstat l2_size)
+ log_must fio $FIO_SCRIPTS/random_reads.fio
+ typeset l2_size2=$(get_arcstat l2_size)
+ do_once=false
+done
+
+verify_trim_io $TESTPOOL "ind" 5 $TRIM_VDEV2
+
+typeset cache_size=$(zpool list -vp | grep $TRIM_VDEV2 | awk '{print $2}')
+typeset cache_alloc=$(zpool list -vp | grep $TRIM_VDEV2 | awk '{print $3}')
+
+log_must test $cache_alloc -lt $cache_size
+
+log_must zpool destroy $TESTPOOL
+log_must rm -f $VDEVS
+
+log_pass "Trim of L2ARC succeeds."
diff --git a/tests/zfs-tests/tests/functional/truncate/.gitignore b/tests/zfs-tests/tests/functional/truncate/.gitignore
new file mode 100644
index 000000000000..f28d93573c51
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/.gitignore
@@ -0,0 +1 @@
+/truncate_test
diff --git a/tests/zfs-tests/tests/functional/truncate/Makefile.am b/tests/zfs-tests/tests/functional/truncate/Makefile.am
new file mode 100644
index 000000000000..b2d804b5d4c2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/Makefile.am
@@ -0,0 +1,18 @@
+include $(top_srcdir)/config/Rules.am
+
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/truncate
+
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ truncate_001_pos.ksh \
+ truncate_002_pos.ksh \
+ truncate_timestamps.ksh
+
+dist_pkgdata_DATA = \
+ truncate.cfg
+
+pkgexecdir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/truncate
+
+pkgexec_PROGRAMS = truncate_test
+truncate_test_SOURCES = truncate_test.c
diff --git a/tests/zfs-tests/tests/functional/truncate/cleanup.ksh b/tests/zfs-tests/tests/functional/truncate/cleanup.ksh
new file mode 100755
index 000000000000..9756c0fab805
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/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/truncate/setup.ksh b/tests/zfs-tests/tests/functional/truncate/setup.ksh
new file mode 100755
index 000000000000..863492db531d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/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/truncate/truncate.cfg b/tests/zfs-tests/tests/functional/truncate/truncate.cfg
new file mode 100644
index 000000000000..13cdafab133b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/truncate.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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export TESTFILE=testfile.$$
+export TRUNC_FILESIZE=${TRUNC_FILESIZE-"67108864"} # 64 Mb
+export TRUNC_BLKSIZE=${TRUNC_BLKSIZE-"512"}
+export TRUNC_SEED=${TRUNC_SEED-""}
+export TRUNC_FILEOFFSET=${TRUNC_FILEOFFSET-""}
+export TRUNC_COUNT=${TRUNC_COUNT-"16384"} # FILESIZE/BLKSIZE/8
+
+export DISKSARRAY=$DISKS
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+
+set_device_dir
diff --git a/tests/zfs-tests/tests/functional/truncate/truncate_001_pos.ksh b/tests/zfs-tests/tests/functional/truncate/truncate_001_pos.ksh
new file mode 100755
index 000000000000..1ae2d74e0d4e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/truncate_001_pos.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 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/truncate/truncate.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Tests file truncation within ZFS.
+#
+# STRATEGY:
+# 1. Open file
+# 2. Write random blocks in random places
+# 3. Truncate the file
+# 4. Repeat steps 2 and 3 lots of times
+# 5. Close the file.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+}
+
+log_assert "Ensure file with random blocks is truncated properly"
+
+options=""
+options_display="default options"
+
+log_onexit cleanup
+
+[[ -n "$TRUNC_FILESIZE" ]] && options=" $options -f $TRUNC_FILESIZE "
+
+[[ -n "$TRUNC_BLKSIZE" ]] && options="$options -b $TRUNC_BLKSIZE "
+
+[[ -n "$TRUNC_COUNT" ]] && options="$options -c $TRUNC_COUNT "
+
+[[ -n "$TRUNC_SEED" ]] && options="$options -s $TRUNC_SEED "
+
+[[ -n "$TRUNC_FILEOFFSET" ]] && options="$options -o $TRUNC_FILEOFFSET "
+
+[[ -n "$options" ]] && options_display=$options
+
+log_note "Invoking file_trunc with: $options_display"
+log_must file_trunc $options $TESTDIR/$TESTFILE
+
+typeset dir=$(get_device_dir $DISKS)
+verify_filesys "$TESTPOOL" "$TESTPOOL/$TESTFS" "$dir"
+
+log_pass "Random blocks have been truncated properly."
diff --git a/tests/zfs-tests/tests/functional/truncate/truncate_002_pos.ksh b/tests/zfs-tests/tests/functional/truncate/truncate_002_pos.ksh
new file mode 100755
index 000000000000..2a4996a1d926
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/truncate_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/tests/functional/truncate/truncate.cfg
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Tests file truncation within ZFS while a sync operation is in progress.
+#
+# STRATEGY:
+# 1. Copy a file to ZFS filesystem
+# 2. Copy /dev/null to same file on ZFS filesystem
+# 3. Execute a sync command
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/*
+ [[ -f $srcfile ]] && rm -f $srcfile
+}
+
+log_assert "Ensure zeroed file gets written correctly during a sync operation"
+
+srcfile="$TESTDIR/cosmo.$$"
+log_must dd if=/dev/urandom of=$srcfile bs=1024k count=1
+
+log_onexit cleanup
+log_must cp $srcfile $TESTDIR/$TESTFILE
+log_must cp /dev/null $TESTDIR/$TESTFILE
+log_must sync
+if [[ -s $TESTDIR/$TESTFILE ]]; then
+ log_note "$(ls -l $TESTDIR/$TESTFILE)"
+ log_fail "testfile not truncated"
+fi
+
+log_pass "Successful truncation while a sync operation is in progress."
diff --git a/tests/zfs-tests/tests/functional/truncate/truncate_test.c b/tests/zfs-tests/tests/functional/truncate/truncate_test.c
new file mode 100644
index 000000000000..3e277e8657b5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/truncate_test.c
@@ -0,0 +1,103 @@
+/*
+ * 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, 2014 by Delphix. All rights reserved.
+ * Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+ */
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define FSIZE 256*1024*1024
+
+static long fsize = FSIZE;
+static int errflag = 0;
+static char *filename = NULL;
+static int ftruncflag = 0;
+
+static void parse_options(int argc, char *argv[]);
+
+static void
+usage(char *execname)
+{
+ (void) fprintf(stderr,
+ "usage: %s [-s filesize] [-f] /path/to/file\n", execname);
+ (void) exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int fd;
+
+ parse_options(argc, argv);
+
+ if (ftruncflag) {
+ fd = open(filename, O_RDWR|O_CREAT, 0666);
+ if (fd < 0) {
+ perror("open");
+ return (1);
+ }
+ if (ftruncate(fd, fsize) < 0) {
+ perror("ftruncate");
+ return (1);
+ }
+ if (close(fd)) {
+ perror("close");
+ return (1);
+ }
+ } else {
+ if (truncate(filename, fsize) < 0) {
+ perror("truncate");
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static void
+parse_options(int argc, char *argv[])
+{
+ int c;
+ extern char *optarg;
+ extern int optind, optopt;
+
+ while ((c = getopt(argc, argv, "s:f")) != -1) {
+ switch (c) {
+ case 's':
+ fsize = atoi(optarg);
+ break;
+ case 'f':
+ ftruncflag++;
+ break;
+ case ':':
+ (void) fprintf(stderr,
+ "Option -%c requires an operand\n", optopt);
+ errflag++;
+ break;
+ }
+ if (errflag) {
+ (void) usage(argv[0]);
+ }
+ }
+
+ if (argc <= optind) {
+ (void) fprintf(stderr, "No filename specified\n");
+ usage(argv[0]);
+ }
+ filename = argv[optind];
+}
diff --git a/tests/zfs-tests/tests/functional/truncate/truncate_timestamps.ksh b/tests/zfs-tests/tests/functional/truncate/truncate_timestamps.ksh
new file mode 100755
index 000000000000..27b28e82eb5b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/truncate/truncate_timestamps.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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/truncate/truncate.cfg
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+
+#
+# DESCRIPTION:
+# Ensure both truncate(2)/ftruncate(2) update target file mtime/ctime attributes
+#
+# STRATEGY:
+# 1. Create a file
+# 2. Truncate the file
+# 3. Verify both mtime/ctime are updated
+# 4. Rinse and repeat for both truncate(2) and ftruncate(2) with various sizes
+#
+
+verify_runnable "both"
+
+function verify_truncate # <filename> <filesize> <option>
+{
+ typeset filename="$1"
+ typeset -i size="$2"
+ typeset option="$3"
+
+ log_must mkfile $sizeavg $filename # always start with $sizeavg
+ if is_freebsd; then
+ typeset -i timestm="$(stat -f "%m" $filename)"
+ typeset -i timestc="$(stat -f "%c" $filename)"
+ log_must sleep 1
+ log_must $STF_SUITE/tests/functional/truncate/truncate_test -s $size $filename $option
+ verify_eq $size "$(stat_size $filename)" "size"
+ verify_ne $timestm "$(stat -f "%m" $filename)" "mtime"
+ verify_ne $timestc "$(stat -f "%c" $filename)" "ctime"
+ else
+ typeset -i timestm="$(stat -c %Y $filename)"
+ typeset -i timestc="$(stat -c %Z $filename)"
+ log_must sleep 1
+ log_must $STF_SUITE/tests/functional/truncate/truncate_test -s $size $filename $option
+ verify_eq $size "$(stat_size $filename)" "size"
+ verify_ne $timestm "$(stat -c %Y $filename)" "mtime"
+ verify_ne $timestc "$(stat -c %Z $filename)" "ctime"
+ fi
+ log_must rm -f $filename
+}
+
+function cleanup
+{
+ [[ -f $truncfile ]] && rm -f $truncfile
+}
+
+log_assert "Ensure both truncate(2)/ftruncate(2) update target file timestamps"
+log_onexit cleanup
+
+truncfile="$TESTDIR/truncate.$$"
+sizemin="123"
+sizeavg="$((256*1024))"
+sizemax="$((1024*1024))"
+
+# truncate(2)
+verify_truncate $truncfile $sizemin ""
+verify_truncate $truncfile $sizeavg ""
+verify_truncate $truncfile $sizemax ""
+
+# ftruncate(2)
+verify_truncate $truncfile $sizemin "-f"
+verify_truncate $truncfile $sizeavg "-f"
+verify_truncate $truncfile $sizemax "-f"
+
+log_pass "Successful truncation correctly update timestamps"
diff --git a/tests/zfs-tests/tests/functional/upgrade/Makefile.am b/tests/zfs-tests/tests/functional/upgrade/Makefile.am
new file mode 100644
index 000000000000..743baa484522
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/upgrade/Makefile.am
@@ -0,0 +1,10 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/upgrade
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ upgrade_userobj_001_pos.ksh \
+ upgrade_projectquota_001_pos.ksh \
+ upgrade_readonly_pool.ksh
+
+dist_pkgdata_DATA = \
+ upgrade_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/upgrade/cleanup.ksh b/tests/zfs-tests/tests/functional/upgrade/cleanup.ksh
new file mode 100755
index 000000000000..1f0c9b63d9f1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/upgrade/cleanup.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.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+#
+# Copyright (c) 2016 by Jinshan Xiong. No rights reserved.
+#
+
+. $STF_SUITE/tests/functional/upgrade/upgrade_common.kshlib
+
+verify_runnable "global"
+
+log_must rm -f $TMPDEV
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/upgrade/setup.ksh b/tests/zfs-tests/tests/functional/upgrade/setup.ksh
new file mode 100755
index 000000000000..c25d25df6b9e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/upgrade/setup.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) 2013 by Delphix. All rights reserved.
+#
+
+#
+# Copyright (c) 2016 by Jinshan Xiong. No rights reserved.
+#
+
+. $STF_SUITE/tests/functional/upgrade/upgrade_common.kshlib
+
+verify_runnable "global"
+
+# create a pool without any features
+log_must mkfile 128m $TMPDEV
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib b/tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib
new file mode 100644
index 000000000000..6ffd85b5b1b6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/upgrade/upgrade_common.kshlib
@@ -0,0 +1,41 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+export TMPDEV=$TEST_BASE_DIR/zpool_upgrade_test.dat
+
+function cleanup_upgrade
+{
+ destroy_dataset "$TESTPOOL/fs1"
+ destroy_dataset "$TESTPOOL/fs2"
+ destroy_dataset "$TESTPOOL/fs3"
+ destroy_pool "$TESTPOOL"
+}
diff --git a/tests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_pos.ksh b/tests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_pos.ksh
new file mode 100755
index 000000000000..364f67e34584
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/upgrade/upgrade_projectquota_001_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 (c) 2017 by Fan Yong. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/upgrade/upgrade_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# Check whether zfs upgrade for project quota works or not.
+# The project quota is per dataset based feature, this test
+# will create multiple datasets and try different upgrade methods.
+#
+# STRATEGY:
+# 1. Create a pool with all features disabled
+# 2. Create a few dataset for testing
+# 3. Make sure automatic upgrade work
+# 4. Make sure manual upgrade work
+#
+
+verify_runnable "global"
+
+if ! lsattr -pd > /dev/null 2>&1; then
+ log_unsupported "Current lsattr does not support set/show project ID"
+fi
+
+log_assert "pool upgrade for projectquota should work"
+log_onexit cleanup_upgrade
+
+log_must zpool create -d -m $TESTDIR $TESTPOOL $TMPDEV
+
+log_must mkfiles $TESTDIR/tf $((RANDOM % 100 + 1))
+log_must zfs create $TESTPOOL/fs1
+log_must mkfiles $TESTDIR/fs1/tf $((RANDOM % 100 + 1))
+log_must zfs umount $TESTPOOL/fs1
+
+log_must zfs create $TESTPOOL/fs2
+log_must mkdir $TESTDIR/fs2/dir
+log_must mkfiles $TESTDIR/fs2/tf $((RANDOM % 100 + 1))
+
+log_must zfs create $TESTPOOL/fs3
+log_must mkdir $TESTDIR/fs3/dir
+log_must mkfiles $TESTDIR/fs3/tf $((RANDOM % 100 + 1))
+
+# Make sure project quota is disabled
+zfs projectspace -o used $TESTPOOL | grep -q "USED" &&
+ log_fail "project quota should be disabled initially"
+
+# set projectquota before upgrade will fail
+log_mustnot zfs set projectquota@100=100m $TESTDIR/fs3
+
+# set projectobjquota before upgrade will fail
+log_mustnot zfs set projectobjquota@100=1000 $TESTDIR/fs3
+
+# 'chattr -p' should fail before upgrade
+log_mustnot chattr -p 100 $TESTDIR/fs3/dir
+
+# 'chattr +P' should fail before upgrade
+log_mustnot chattr +P $TESTDIR/fs3/dir
+
+# Upgrade zpool to support all features
+log_must zpool upgrade $TESTPOOL
+
+# Double check project quota is disabled
+zfs projectspace -o used $TESTPOOL | grep -q "USED" &&
+ log_fail "project quota should be disabled after pool upgrade"
+
+# Mount dataset should trigger upgrade
+log_must zfs mount $TESTPOOL/fs1
+log_must sleep 3 # upgrade done in the background so let's wait for a while
+zfs projectspace -o used $TESTPOOL/fs1 | grep -q "USED" ||
+ log_fail "project quota should be enabled for $TESTPOOL/fs1"
+
+# Create file should trigger dataset upgrade
+log_must mkfile 1m $TESTDIR/fs2/dir/tf
+log_must sleep 3 # upgrade done in the background so let's wait for a while
+zfs projectspace -o used $TESTPOOL/fs2 | grep -q "USED" ||
+ log_fail "project quota should be enabled for $TESTPOOL/fs2"
+
+# "lsattr -p" should NOT trigger upgrade
+log_must lsattr -p -d $TESTDIR/fs3/dir
+zfs projectspace -o used $TESTPOOL/fs3 | grep -q "USED" &&
+ log_fail "project quota should not active for $TESTPOOL/fs3"
+
+# 'chattr -p' should trigger dataset upgrade
+log_must chattr -p 100 $TESTDIR/fs3/dir
+log_must sleep 5 # upgrade done in the background so let's wait for a while
+zfs projectspace -o used $TESTPOOL/fs3 | grep -q "USED" ||
+ log_fail "project quota should be enabled for $TESTPOOL/fs3"
+cnt=$(zfs get -H projectobjused@100 $TESTPOOL/fs3 | awk '{print $3}')
+# if 'xattr=on', then 'cnt = 2'
+[[ $cnt -ne 1 ]] && [[ $cnt -ne 2 ]] &&
+ log_fail "projectquota accounting failed $cnt"
+
+# All in all, after having been through this, the dataset for testpool
+# still shouldn't be upgraded
+zfs projectspace -o used $TESTPOOL | grep -q "USED" &&
+ log_fail "project quota should be disabled for $TESTPOOL"
+
+# Manual upgrade root dataset
+# uses an ioctl which will wait for the upgrade to be done before returning
+log_must zfs set version=current $TESTPOOL
+zfs projectspace -o used $TESTPOOL | grep -q "USED" ||
+ log_fail "project quota should be enabled for $TESTPOOL"
+
+log_pass "Project Quota upgrade done"
diff --git a/tests/zfs-tests/tests/functional/upgrade/upgrade_readonly_pool.ksh b/tests/zfs-tests/tests/functional/upgrade/upgrade_readonly_pool.ksh
new file mode 100755
index 000000000000..750620e6d450
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/upgrade/upgrade_readonly_pool.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 2019, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/upgrade/upgrade_common.kshlib
+
+#
+# DESCRIPTION:
+# User accounting upgrade should not be executed on readonly pool
+#
+# STRATEGY:
+# 1. Create a pool with the feature@userobj_accounting disabled to simulate
+# a legacy pool from a previous ZFS version.
+# 2. Create a file on the "legecy" dataset and store its checksum
+# 3. Enable feature@userobj_accounting on the pool and verify it is only
+# "enabled" and not "active": upgrading starts when the filesystem is mounted
+# 4. Export the pool and re-import is readonly, without mounting any filesystem
+# 5. Try to mount the root dataset manually without the "ro" option, then verify
+# filesystem status and the pool feature status (not "active") to ensure the
+# pool "readonly" status is enforced.
+#
+
+verify_runnable "global"
+
+TESTFILE="$TESTDIR/file.bin"
+
+log_assert "User accounting upgrade should not be executed on readonly pool"
+log_onexit cleanup_upgrade
+
+# 1. Create a pool with the feature@userobj_accounting disabled to simulate
+# a legacy pool from a previous ZFS version.
+log_must zpool create -d -m $TESTDIR $TESTPOOL $TMPDEV
+
+# 2. Create a file on the "legecy" dataset
+log_must touch $TESTDIR/file.bin
+
+# 3. Enable feature@userobj_accounting on the pool and verify it is only
+# "enabled" and not "active": upgrading starts when the filesystem is mounted
+log_must zpool set feature@userobj_accounting=enabled $TESTPOOL
+log_must test "enabled" == "$(get_pool_prop 'feature@userobj_accounting' $TESTPOOL)"
+
+# 4. Export the pool and re-import is readonly, without mounting any filesystem
+log_must zpool export $TESTPOOL
+log_must zpool import -o readonly=on -N -d "$(dirname $TMPDEV)" $TESTPOOL
+
+# 5. Try to mount the root dataset manually without the "ro" option, then verify
+# filesystem status and the pool feature status (not "active") to ensure the
+# pool "readonly" status is enforced.
+log_must mount -t zfs -o zfsutil $TESTPOOL $TESTDIR
+log_must stat "$TESTFILE"
+log_mustnot touch "$TESTFILE"
+log_must test "enabled" == "$(get_pool_prop 'feature@userobj_accounting' $TESTPOOL)"
+
+log_pass "User accounting upgrade is not executed on readonly pool"
diff --git a/tests/zfs-tests/tests/functional/upgrade/upgrade_userobj_001_pos.ksh b/tests/zfs-tests/tests/functional/upgrade/upgrade_userobj_001_pos.ksh
new file mode 100755
index 000000000000..b437a0cdfa3d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/upgrade/upgrade_userobj_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) 2013 by Jinshan Xiong. No rights reserved.
+# Copyright (c) 2017 Datto Inc.
+#
+
+. $STF_SUITE/tests/functional/upgrade/upgrade_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# Check that zfs upgrade for object count accounting works.
+# Since userobjaccounting is a per dataset feature, this test case
+# will create multiple dataset and try different upgrade method.
+#
+# STRATEGY:
+# 1. Create a pool with all features disabled
+# 2. Create a few dataset for testing
+# 3. Make sure automatic upgrade work
+# 4. Make sure manual upgrade work
+#
+
+verify_runnable "global"
+
+log_assert "pool upgrade for userobj accounting should work"
+log_onexit cleanup_upgrade
+
+log_must zpool create -d -m $TESTDIR $TESTPOOL $TMPDEV
+
+log_must mkfiles $TESTDIR/tf $((RANDOM % 1000 + 1))
+log_must zfs create $TESTPOOL/fs1
+log_must mkfiles $TESTDIR/fs1/tf $((RANDOM % 1000 + 1))
+log_must zfs create $TESTPOOL/fs2
+log_must mkfiles $TESTDIR/fs2/tf $((RANDOM % 1000 + 1))
+log_must zfs umount $TESTPOOL/fs2
+
+# Make sure userobj accounting is disabled
+zfs userspace -o objused -H $TESTPOOL | head -n 1 | grep -q "-" ||
+ log_fail "userobj accounting should be disabled initially"
+
+# Upgrade zpool to support all features
+log_must zpool upgrade $TESTPOOL
+
+# Make sure userobj accounting is disabled again
+zfs userspace -o objused -H $TESTPOOL | head -n 1 | grep -q "-" ||
+ log_fail "userobj accounting should be disabled after pool upgrade"
+
+# Create a file in fs1 should trigger dataset upgrade
+log_must mkfile 1m $TESTDIR/fs1/tf
+log_must sleep 1 # upgrade done in the background so let's give it a sec
+
+# Make sure userobj accounting is working for fs1
+zfs userspace -o objused -H $TESTPOOL/fs1 | head -n 1 | grep -q "-" &&
+ log_fail "userobj accounting should be enabled for $TESTPOOL/fs1"
+
+# Mount a dataset should trigger upgrade
+log_must zfs mount $TESTPOOL/fs2
+log_must sleep 1 # upgrade done in the background so let's give it a sec
+
+# Make sure userobj accounting is working for fs2
+zfs userspace -o objused -H $TESTPOOL/fs2 | head -n 1 | grep -q "-" &&
+ log_fail "userobj accounting should be enabled for $TESTPOOL/fs2"
+
+# All in all, after having been through this, the dataset for testpool
+# still shouldn't be upgraded
+zfs userspace -o objused -H $TESTPOOL | head -n 1 | grep -q "-" ||
+ log_fail "userobj accounting should be disabled for $TESTPOOL"
+
+# Manual upgrade root dataset
+# uses an ioctl which will wait for the upgrade to be done before returning
+log_must zfs set version=current $TESTPOOL
+zfs userspace -o objused -H $TESTPOOL | head -n 1 | grep -q "-" &&
+ log_fail "userobj accounting should be enabled for $TESTPOOL"
+
+log_pass "all tests passed - what a lucky day!"
diff --git a/tests/zfs-tests/tests/functional/user_namespace/Makefile.am b/tests/zfs-tests/tests/functional/user_namespace/Makefile.am
new file mode 100644
index 000000000000..5f95dbf8d967
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/user_namespace/Makefile.am
@@ -0,0 +1,9 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/user_namespace
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ user_namespace_001.ksh
+
+dist_pkgdata_DATA = \
+ user_namespace_common.kshlib \
+ user_namespace.cfg
diff --git a/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh b/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh
new file mode 100755
index 000000000000..61caf3910042
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/user_namespace/cleanup.ksh
@@ -0,0 +1,25 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/user_namespace/setup.ksh b/tests/zfs-tests/tests/functional/user_namespace/setup.ksh
new file mode 100755
index 000000000000..354cc9a6b17d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/user_namespace/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
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+if ! [ -f /proc/self/uid_map ]; then
+ log_unsupported "The kernel doesn't support user namespaces."
+fi
+
+verify_runnable "both"
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg b/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg
new file mode 100644
index 000000000000..9e55398e239c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace.cfg
@@ -0,0 +1,23 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+export ROOT_UID=100000
+export OTHER_UID=101000
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.ksh
new file mode 100755
index 000000000000..6be30ab4d204
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_001.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
+#
+
+. $STF_SUITE/tests/functional/user_namespace/user_namespace_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Regression test for secpolicy_vnode_setids_setgids
+#
+#
+# STRATEGY:
+# 1. Create files with various owners.
+# 2. Try to set setgid bit.
+#
+
+verify_runnable "both"
+
+# rroot: real root,
+# uroot: root within user namespace
+# uother: other user within user namespace
+set -A files rroot_rroot uroot_uroot uroot_other uother_uroot uother_uother
+
+function cleanup
+{
+ for i in ${files[*]}; do
+ log_must rm -f $TESTDIR/$i
+ done
+}
+
+log_onexit cleanup
+
+log_assert "Check root in user namespaces"
+
+TOUCH=$(readlink -e $(which touch))
+CHMOD=$(readlink -e $(which chmod))
+
+for i in ${files[*]}; do
+ log_must $TOUCH $TESTDIR/$i
+ log_must $CHMOD 0644 $TESTDIR/$i
+done
+
+log_must chown 0:0 $TESTDIR/rroot_rroot
+log_must chown $ROOT_UID:$ROOT_UID $TESTDIR/uroot_uroot
+log_must chown $ROOT_UID:$OTHER_UID $TESTDIR/uroot_other
+log_must chown $OTHER_UID:$ROOT_UID $TESTDIR/uother_uroot
+log_must chown $OTHER_UID:$OTHER_UID $TESTDIR/uother_uother
+
+log_mustnot user_ns_exec $CHMOD 02755 $TESTDIR/rroot_rroot
+log_mustnot test -g $TESTDIR/rroot_rroot
+
+log_must user_ns_exec $CHMOD 02755 $TESTDIR/uroot_uroot
+log_must test -g $TESTDIR/uroot_uroot
+
+log_must user_ns_exec $CHMOD 02755 $TESTDIR/uroot_other
+log_must test -g $TESTDIR/uroot_other
+
+log_must user_ns_exec $CHMOD 02755 $TESTDIR/uother_uroot
+log_must test -g $TESTDIR/uother_uroot
+
+log_must user_ns_exec $CHMOD 02755 $TESTDIR/uother_uother
+log_must test -g $TESTDIR/uother_uother
+
+log_mustnot user_ns_exec $TOUCH $TESTDIR/rroot_rroot
+log_must $CHMOD 0666 $TESTDIR/rroot_rroot
+for i in ${files[*]}; do
+ log_must user_ns_exec $TOUCH $TESTDIR/$i
+done
+
+log_pass "Check root in user namespaces"
diff --git a/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib
new file mode 100644
index 000000000000..8577294d0eaa
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/user_namespace/user_namespace_common.kshlib
@@ -0,0 +1,23 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/user_namespace/user_namespace.cfg
diff --git a/tests/zfs-tests/tests/functional/userquota/Makefile.am b/tests/zfs-tests/tests/functional/userquota/Makefile.am
new file mode 100644
index 000000000000..8f0287bc17b2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/Makefile.am
@@ -0,0 +1,27 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/userquota
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ groupspace_001_pos.ksh \
+ groupspace_002_pos.ksh \
+ groupspace_003_pos.ksh \
+ userquota_001_pos.ksh \
+ userquota_002_pos.ksh \
+ userquota_003_pos.ksh \
+ userquota_004_pos.ksh \
+ userquota_005_neg.ksh \
+ userquota_006_pos.ksh \
+ userquota_007_pos.ksh \
+ userquota_008_pos.ksh \
+ userquota_009_pos.ksh \
+ userquota_010_pos.ksh \
+ userquota_011_pos.ksh \
+ userquota_012_neg.ksh \
+ userquota_013_pos.ksh \
+ userspace_001_pos.ksh \
+ userspace_002_pos.ksh \
+ userspace_003_pos.ksh
+
+dist_pkgdata_DATA = \
+ userquota.cfg \
+ userquota_common.kshlib
diff --git a/tests/zfs-tests/tests/functional/userquota/cleanup.ksh b/tests/zfs-tests/tests/functional/userquota/cleanup.ksh
new file mode 100755
index 000000000000..5c8229b1874f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/cleanup.ksh
@@ -0,0 +1,41 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+log_must cleanup_quota
+log_must clean_user_group
+
+typeset mntp=$(get_prop mountpoint $QFS)
+chmod 0755 $mntp
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/userquota/groupspace_001_pos.ksh b/tests/zfs-tests/tests/functional/userquota/groupspace_001_pos.ksh
new file mode 100755
index 000000000000..fb7a19057acf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/groupspace_001_pos.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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the zfs groupspace with all parameters
+#
+#
+# STRATEGY:
+# 1. set zfs groupquota to a fs
+# 2. write some data to the fs with specified user and group
+# 3. use zfs groupspace with all possible parameters to check the result
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the zfs groupspace with all possible parameters"
+
+set -A params -- "-n" "-H" "-p" "-o type,name,used,quota" \
+ "-o name,used,quota" "-o used,quota" "-o used" "-o quota" "-s type" \
+ "-s name" "-s used" "-s quota" "-S type" "-S name" "-S used" "-S quota" \
+ "-t posixuser" "-t posixgroup" "-t all" "-i" "-t smbuser" "-t smbgroup"
+
+typeset snap_fs=$QFS@snap
+
+log_must zfs set groupquota@$QGROUP=500m $QFS
+mkmount_writable $QFS
+log_must user_run $QUSER1 mkfile 50m $QFILE
+
+sync
+
+log_must zfs snapshot $snap_fs
+
+for param in "${params[@]}"; do
+ log_must eval "zfs groupspace $param $QFS >/dev/null 2>&1"
+ log_must eval "zfs groupspace $param $snap_fs >/dev/null 2>&1"
+done
+
+log_pass "Check the zfs groupspace with all possible parameters"
diff --git a/tests/zfs-tests/tests/functional/userquota/groupspace_002_pos.ksh b/tests/zfs-tests/tests/functional/userquota/groupspace_002_pos.ksh
new file mode 100755
index 000000000000..20d0f7319df1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/groupspace_002_pos.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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the user used and groupspace size in zfs groupspace
+#
+#
+# STRATEGY:
+# 1. set zfs groupquota to a fs
+# 2. write some data to the fs with specified user and size
+# 3. use zfs groupspace to check the used size and quota size
+#
+
+function cleanup
+{
+ if datasetexists $snapfs; then
+ log_must zfs destroy $snapfs
+ fi
+ log_must cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the zfs groupspace used and quota"
+
+log_must zfs set groupquota@$QGROUP=500m $QFS
+mkmount_writable $QFS
+log_must user_run $QUSER1 mkfile 100m $QFILE
+
+sync
+
+typeset snapfs=$QFS@snap
+
+log_must zfs snapshot $snapfs
+
+log_must eval "zfs groupspace $QFS >/dev/null 2>&1"
+log_must eval "zfs groupspace $snapfs >/dev/null 2>&1"
+
+for fs in "$QFS" "$snapfs"; do
+ log_note "check the quota size in zfs groupspace $fs"
+ log_must eval "zfs groupspace $fs | grep $QGROUP | grep 500M"
+
+ log_note "check the user used size in zfs groupspace $fs"
+ log_must eval "zfs groupspace $fs | grep $QGROUP | grep 100M"
+done
+
+log_pass "Check the zfs groupspace used and quota pass as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/groupspace_003_pos.ksh b/tests/zfs-tests/tests/functional/userquota/groupspace_003_pos.ksh
new file mode 100755
index 000000000000..56b7af031550
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/groupspace_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 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the user used and groupspace object counts in zfs groupspace
+#
+#
+# STRATEGY:
+# 1. set zfs groupquota to a fs
+# 2. create objects for different users in the same group
+# 3. use zfs groupspace to check the object count
+#
+
+function cleanup
+{
+ if datasetexists $snapfs; then
+ log_must zfs destroy $snapfs
+ fi
+
+ log_must rm -f ${QFILE}_*
+ log_must cleanup_quota
+}
+
+function group_object_count
+{
+ typeset fs=$1
+ typeset group=$2
+ typeset -i groupspacecnt=$(zfs groupspace -oname,objused $fs |
+ awk /$group/'{print $2}')
+ typeset -i zfsgetcnt=$(zfs get -H -ovalue groupobjused@$group $fs)
+
+ # 'zfs groupspace' and 'zfs get groupobjused@' should be equal
+ verify_eq "$groupspacecnt" "$zfsgetcnt" "groupobjused@$group"
+
+ echo $groupspacecnt
+}
+
+log_onexit cleanup
+
+log_assert "Check the zfs groupspace object used"
+
+mkmount_writable $QFS
+log_must zfs set xattr=sa $QFS
+
+((user1_cnt = RANDOM % 100 + 1))
+((user2_cnt = RANDOM % 100 + 1))
+log_must user_run $QUSER1 mkfiles ${QFILE}_1 $user1_cnt
+log_must user_run $QUSER2 mkfiles ${QFILE}_2 $user2_cnt
+((grp_cnt = user1_cnt + user2_cnt))
+sync_pool
+
+typeset snapfs=$QFS@snap
+
+log_must zfs snapshot $snapfs
+
+log_must eval "zfs groupspace $QFS >/dev/null 2>&1"
+log_must eval "zfs groupspace $snapfs >/dev/null 2>&1"
+
+for fs in "$QFS" "$snapfs"; do
+ log_note "check the object count in zfs groupspace $fs"
+ [[ $(group_object_count $fs $QGROUP) -eq $grp_cnt ]] ||
+ log_fail "expected $grp_cnt"
+done
+
+log_note "file removal"
+log_must rm ${QFILE}_*
+sync_pool
+
+[[ $(group_object_count $QFS $QGROUP) -eq 0 ]] ||
+ log_fail "expected 0 files for $QGROUP"
+
+[[ $(group_object_count $snapfs $QGROUP) -eq $grp_cnt ]] ||
+ log_fail "expected $grp_cnt files for $QGROUP"
+
+cleanup
+log_pass "Check the zfs groupspace object used pass as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/setup.ksh b/tests/zfs-tests/tests/functional/userquota/setup.ksh
new file mode 100755
index 000000000000..d4b3cdcaba92
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+verify_runnable "both"
+
+log_must clean_user_group
+
+log_must add_group $QGROUP
+log_must add_user $QGROUP $QUSER1
+log_must add_user $QGROUP $QUSER2
+
+#
+# Verify the test user can execute the zfs utilities. This may not
+# be possible due to default permissions on the user home directory.
+# This can be resolved granting group read access.
+#
+# chmod 0750 $HOME
+#
+user_run $QUSER1 zfs list
+if [ $? -ne 0 ]; then
+ log_unsupported "Test user $QUSER1 cannot execute zfs utilities"
+fi
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota.cfg b/tests/zfs-tests/tests/functional/userquota/userquota.cfg
new file mode 100644
index 000000000000..893428deaf0a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota.cfg
@@ -0,0 +1,46 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+export QUSER1=quser1
+export QUSER2=quser2
+
+export QGROUP=qgroup
+export QGROUP1=qgroup1
+export QGROUP1=qgroup2
+
+export UQUOTA_SIZE=1000000
+export GQUOTA_SIZE=4000000
+
+export QFS=$TESTPOOL/$TESTFS
+export QFILE=$TESTDIR/qf
+export OFILE=$TESTDIR/of
+
+export SNAP_QUOTA=100m
+export TEST_QUOTA=88888
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_001_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_001_pos.ksh
new file mode 100755
index 000000000000..dd8f6d3552bb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_001_pos.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 2009 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/userquota/userquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check the basic function of the userquota and groupquota
+#
+#
+# STRATEGY:
+# 1. Set userquota and overwrite the quota size
+# 2. The write operation should fail with Disc quota exceeded
+# 3. Set groupquota and overwrite the quota size
+# 4. The write operation should fail with Disc quota exceeded
+#
+#
+
+function cleanup
+{
+ cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "If write operation overwrite {user|group}quota size, it will fail"
+
+mkmount_writable $QFS
+log_note "Check the userquota@$QUSER1"
+log_must zfs set userquota@$QUSER1=$UQUOTA_SIZE $QFS
+log_must user_run $QUSER1 mkfile $UQUOTA_SIZE $QFILE
+sync_pool
+log_mustnot user_run $QUSER1 mkfile 1 $OFILE
+cleanup_quota
+
+log_note "Check the groupquota@$QGROUP"
+log_must zfs set groupquota@$QGROUP=$GQUOTA_SIZE $QFS
+mkmount_writable $QFS
+log_must user_run $QUSER1 mkfile $GQUOTA_SIZE $QFILE
+sync_pool
+log_mustnot user_run $QUSER1 mkfile 1 $OFILE
+
+cleanup_quota
+
+log_pass "Write operation overwrite {user|group}quota size, it as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_002_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_002_pos.ksh
new file mode 100755
index 000000000000..4e13691dac43
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# the userquota and groupquota can be set during zpool or zfs creation"
+#
+#
+# STRATEGY:
+# 1. Set userquota and groupquota via "zpool -O or zfs create -o"
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ if poolexists $TESTPOOL1; then
+ log_must zpool destroy $TESTPOOL1
+ fi
+
+ if [[ -f $pool_vdev ]]; then
+ rm -f $pool_vdev
+ fi
+}
+
+log_onexit cleanup
+
+log_assert \
+ "the userquota and groupquota can be set during zpool,zfs creation"
+
+typeset pool_vdev=$TEST_BASE_DIR/pool_dev.$$
+
+log_must mkfile 500m $pool_vdev
+
+if poolexists $TESTPOOL1; then
+ zpool destroy $TESTPOOL1
+fi
+
+log_must zpool create -O userquota@$QUSER1=$UQUOTA_SIZE \
+ -O groupquota@$QGROUP=$GQUOTA_SIZE $TESTPOOL1 $pool_vdev
+
+log_must eval "zfs list -r -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL1 > /dev/null 2>&1"
+
+log_must check_quota "userquota@$QUSER1" $TESTPOOL1 "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $TESTPOOL1 "$GQUOTA_SIZE"
+
+log_must zfs create -o userquota@$QUSER1=$UQUOTA_SIZE \
+ -o groupquota@$QGROUP=$GQUOTA_SIZE $TESTPOOL1/fs
+
+log_must eval "zfs list -r -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL1 > /dev/null 2>&1"
+
+log_must check_quota "userquota@$QUSER1" $TESTPOOL1/fs "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $TESTPOOL1/fs "$GQUOTA_SIZE"
+
+log_pass \
+ "the userquota and groupquota can be set during zpool,zfs creation"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_003_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_003_pos.ksh
new file mode 100755
index 000000000000..c4ac15c0dfe4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_003_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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the basic function of set/get userquota and groupquota on fs
+#
+#
+# STRATEGY:
+# 1. Set userquota on fs and check the zfs get
+# 2. Set groupquota on fs and check the zfs get
+#
+
+function cleanup
+{
+ cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the basic function of set/get userquota and groupquota on fs"
+
+log_note "Check the set|get userquota@$QUSER1 and groupquota@QGROUP"
+log_must zfs set userquota@$QUSER1=$UQUOTA_SIZE $QFS
+log_must check_quota "userquota@$QUSER1" $QFS "$UQUOTA_SIZE"
+
+log_must zfs set groupquota@$QGROUP=$GQUOTA_SIZE $QFS
+log_must check_quota "groupquota@$QGROUP" $QFS "$GQUOTA_SIZE"
+
+log_pass "Check the basic function of set/get userquota on fs passed as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_004_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_004_pos.ksh
new file mode 100755
index 000000000000..ae748e2c63d4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_004_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the basic function user|group used
+#
+#
+# STRATEGY:
+# 1. Write some data to fs by normal user and check the user|group used
+#
+
+function cleanup
+{
+ cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the basic function of {user|group} used"
+
+sync_pool
+typeset user_used=$(get_value "userused@$QUSER1" $QFS)
+typeset group_used=$(get_value "groupused@$QGROUP" $QFS)
+typeset file_size='100m'
+
+if [[ $user_used != 0 ]]; then
+ log_fail "FAIL: userused is $user_used, should be 0"
+fi
+if [[ $group_used != 0 ]]; then
+ log_fail "FAIL: groupused is $group_used, should be 0"
+fi
+
+mkmount_writable $QFS
+log_must user_run $QUSER1 mkfile $file_size $QFILE
+sync_pool
+
+user_used=$(get_value "userused@$QUSER1" $QFS)
+group_used=$(get_value "groupused@$QGROUP" $QFS)
+
+# get_value() reads the exact byte value which is slightly more than 100m
+if [[ "$(($user_used/1024/1024))m" != "$file_size" ]]; then
+ log_note "user $QUSER1 used is $user_used"
+ log_fail "userused for user $QUSER1 expected to be $file_size, " \
+ "not $user_used"
+fi
+
+if [[ $user_used != $group_used ]]; then
+ log_note "user $QUSER1 used is $user_used"
+ log_note "group $QGROUP used is $group_used"
+ log_fail "FAIL: userused should equal to groupused"
+fi
+
+log_pass "Check the basic function of {user|group}used pass as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_005_neg.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_005_neg.ksh
new file mode 100755
index 000000000000..5684b05b7e4b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_005_neg.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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the invalid parameter of zfs set user|group quota
+#
+#
+# STRATEGY:
+# 1. check the invalid zfs set user|group quota to fs
+# 1. check the valid zfs set user|group quota to snapshots
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the invalid parameter of zfs set user|group quota"
+typeset snap_fs=$QFS@snap
+
+log_must zfs snapshot $snap_fs
+
+set -A no_users "mms1234" "ss@#" "root-122"
+for user in "${no_users[@]}"; do
+ log_mustnot id $user
+ log_mustnot zfs set userquota@$user=100m $QFS
+done
+
+log_note "can set all numeric id even if that id does not exist"
+log_must zfs set userquota@12345678=100m $QFS
+log_mustnot zfs set userquota@12345678=100m $snap_fs
+
+set -A sizes "100mfsd" "m0.12m" "GGM" "-1234-m" "123m-m"
+
+for size in "${sizes[@]}"; do
+ log_note "can not set user quota with invalid size parameter"
+ log_mustnot zfs set userquota@root=$size $QFS
+done
+
+log_note "can not set user quota to snapshot $snap_fs"
+log_mustnot zfs set userquota@root=100m $snap_fs
+
+
+set -A no_groups "aidsf@dfsd@" "123223-dsfds#sdfsd" "mss_#ss" "@@@@"
+for group in "${no_groups[@]}"; do
+ log_mustnot eval "grep $group /etc/group"
+ log_mustnot zfs set groupquota@$group=100m $QFS
+done
+
+log_note "can not set group quota with invalid size parameter"
+log_mustnot zfs set groupquota@root=100msfsd $QFS
+
+log_note "can not set group quota to snapshot $snap_fs"
+log_mustnot zfs set groupquota@root=100m $snap_fs
+
+log_pass "Check the invalid parameter of zfs set user|group quota pas as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_006_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_006_pos.ksh
new file mode 100755
index 000000000000..7848a924bde8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_006_pos.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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the invalid parameter of zfs get user|group quota
+#
+#
+# STRATEGY:
+# 1. check the invalid zfs get user|group quota to fs
+# 2. check the valid zfs get user|group quota to snapshots
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the invalid parameter of zfs get user|group quota"
+typeset snap_fs=$QFS@snap
+
+log_must zfs snapshot $snap_fs
+
+set -A no_users "mms1234" "ss@#" "root-122" "1234"
+for user in "${no_users[@]}"; do
+ log_mustnot eval "id $user >/dev/null 2>&1"
+ log_must eval "zfs get userquota@$user $QFS >/dev/null 2>&1"
+ log_must eval "zfs get userquota@$user $snap_fs >/dev/null 2>&1"
+done
+
+set -A no_groups "aidsf@dfsd@" "123223-dsfds#sdfsd" "mss_#ss" "1234"
+for group in "${no_groups[@]}"; do
+ if is_freebsd; then
+ log_mustnot eval "pw groupdel -n $group >/dev/null 2>&1"
+ else
+ log_mustnot eval "groupdel $group >/dev/null 2>&1"
+ fi
+ log_must eval "zfs get groupquota@$group $QFS >/dev/null 2>&1"
+ log_must eval "zfs get groupquota@$group $snap_fs >/dev/null 2>&1"
+done
+
+log_pass "Check the invalid parameter of zfs get user|group quota pass as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_007_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_007_pos.ksh
new file mode 100755
index 000000000000..1dea4006618c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_007_pos.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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# userquota/groupquota can be set beyond the fs quota
+# userquota/groupquota can be set at a smaller size than its current usage.
+#
+# STRATEGY:
+# 1. set quota to a fs and set a larger size of userquota and groupquota
+# 2. write some data to the fs and set a smaller userquota and groupquota
+#
+
+function cleanup
+{
+ log_must cleanup_quota
+ log_must zfs set quota=none $QFS
+}
+
+log_onexit cleanup
+
+log_assert "Check set user|group quota to larger than the quota size of a fs"
+
+log_must zfs set quota=200m $QFS
+log_must zfs set userquota@$QUSER1=500m $QFS
+log_must zfs set groupquota@$QGROUP=600m $QFS
+
+log_must zfs get userquota@$QUSER1 $QFS
+log_must zfs get groupquota@$QGROUP $QFS
+
+log_note "write some data to the $QFS"
+mkmount_writable $QFS
+log_must user_run $QUSER1 mkfile 100m $QFILE
+sync
+
+log_note "set user|group quota at a smaller size than it current usage"
+log_must zfs set userquota@$QUSER1=90m $QFS
+log_must zfs set groupquota@$QGROUP=90m $QFS
+
+log_must zfs get userquota@$QUSER1 $QFS
+log_must zfs get groupquota@$QGROUP $QFS
+
+log_pass "set user|group quota to larger than quota size of a fs pass as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_008_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_008_pos.ksh
new file mode 100755
index 000000000000..c9404cd2868f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_008_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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# zfs get all <fs> does not print out userquota/groupquota
+#
+# STRATEGY:
+# 1. set userquota and groupquota to a fs
+# 2. check zfs get all fs
+#
+
+function cleanup
+{
+ log_must cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check zfs get all will not print out user|group quota"
+
+log_must zfs set userquota@$QUSER1=50m $QFS
+log_must zfs set groupquota@$QGROUP=100m $QFS
+
+log_mustnot zfs get all $QFS | grep userquota
+log_mustnot zfs get all $QFS | grep groupquota
+
+log_pass "zfs get all will not print out user|group quota"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_009_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_009_pos.ksh
new file mode 100755
index 000000000000..1c0fdde3fa46
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_009_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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check user|group quota to snapshot that:
+# 1) can not set user|group quota to snapshot directly
+# 2) snapshot can inherit the parent fs's user|groupquota
+# 3) the user|group quota will not change even the parent fs's quota changed.
+#
+#
+# STRATEGY:
+# 1. create a snapshot of a fs
+# 2. set the user|group quota to snapshot and expect fail
+# 3. set user|group quota to fs and check the snapshot
+# 4. re-set user|group quota to fs and check the snapshot's value
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the snapshot's user|group quota"
+typeset snap_fs=$QFS@snap
+
+
+log_must zfs set userquota@$QUSER1=$UQUOTA_SIZE $QFS
+log_must check_quota "userquota@$QUSER1" $QFS "$UQUOTA_SIZE"
+
+log_must zfs set groupquota@$QGROUP=$GQUOTA_SIZE $QFS
+log_must check_quota "groupquota@$QGROUP" $QFS "$GQUOTA_SIZE"
+
+log_must zfs snapshot $snap_fs
+
+log_note "check the snapshot $snap_fs user|group quota"
+log_must check_quota "userquota@$QUSER1" $snap_fs "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $snap_fs "$GQUOTA_SIZE"
+
+log_note "set userquota and groupquota to $snap_fs which will fail"
+log_mustnot zfs set userquota@$QUSER1=$SNAP_QUOTA $snap_fs
+log_mustnot zfs set groupquota@$QGROUP=$SNAP_QUOTA $snap_fs
+
+log_note "change the parent's userquota and groupquota"
+log_must zfs set userquota@$QUSER1=$TEST_QUOTA $QFS
+log_must zfs set groupquota@$QGROUP=$TEST_QUOTA $QFS
+
+log_must check_quota "userquota@$QUSER1" $QFS $TEST_QUOTA
+log_must check_quota "groupquota@$QGROUP" $QFS $TEST_QUOTA
+
+log_note "check the snapshot $snap_fs userquota and groupquota"
+log_must check_quota "userquota@$QUSER1" $snap_fs "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $snap_fs "$GQUOTA_SIZE"
+
+log_pass "Check the snapshot's user|group quota pass as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_010_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_010_pos.ksh
new file mode 100755
index 000000000000..20c9c56ba5ef
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_010_pos.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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check userquota and groupquota being exceeded at the same time
+#
+#
+# STRATEGY:
+# 1. Set userquota and groupquota to a fs
+# 2. write to exceed the userquota size to check the result
+# 3. write to exceed the groupquota size to check the result
+#
+
+function cleanup
+{
+ cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "overwrite any of the {user|group}quota size, it will fail"
+
+log_note "overwrite to $QFS to make it exceed userquota"
+log_must zfs set userquota@$QUSER1=$UQUOTA_SIZE $QFS
+log_must zfs set groupquota@$QGROUP=$GQUOTA_SIZE $QFS
+
+mkmount_writable $QFS
+log_must user_run $QUSER1 mkfile $UQUOTA_SIZE $QFILE
+sync_pool
+
+log_must eval "zfs get -p userused@$QUSER1 $QFS >/dev/null 2>&1"
+log_must eval "zfs get -p groupused@$GROUPUSED $QFS >/dev/null 2>&1"
+
+log_mustnot user_run $QUSER1 mkfile 1 $OFILE
+
+log_must rm -f $QFILE
+
+log_note "overwrite to $QFS to make it exceed userquota"
+log_mustnot user_run $QUSER1 mkfile $GQUOTA_SIZE $QFILE
+
+log_must eval "zfs get -p userused@$QUSER1 $QFS >/dev/null 2>&1"
+log_must eval "zfs get -p groupused@$GROUPUSED $QFS >/dev/null 2>&1"
+
+log_pass "overwrite any of the {user|group}quota size, it fail as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_011_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_011_pos.ksh
new file mode 100755
index 000000000000..93020ae8ded6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_011_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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# the userquota and groupquota will not change during zfs actions, such as
+# snapshot,clone,rename,upgrade,send,receive.
+#
+#
+# STRATEGY:
+# 1. Create a pool, and create fs with preset user,group quota
+# 2. Check set user|group quota via zfs snapshot|clone|list -o
+# 3. Check the user|group quota can not change during zfs rename|upgrade|promote
+# 4. Check the user|group quota can not change during zfs clone
+# 5. Check the user|group quota can not change during zfs send/receive
+#
+
+function cleanup
+{
+ for ds in $TESTPOOL/fs $TESTPOOL/fs-rename $TESTPOOL/fs-clone; do
+ if datasetexists $ds; then
+ log_must zfs destroy -rRf $ds
+ fi
+ done
+}
+
+log_onexit cleanup
+
+log_assert \
+ "the userquota and groupquota can't change during zfs actions"
+
+cleanup
+
+log_must zfs create -o userquota@$QUSER1=$UQUOTA_SIZE \
+ -o groupquota@$QGROUP=$GQUOTA_SIZE $TESTPOOL/fs
+
+log_must zfs snapshot $TESTPOOL/fs@snap
+log_must eval "zfs list -r -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "userquota@$QUSER1" $TESTPOOL/fs@snap "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $TESTPOOL/fs@snap "$GQUOTA_SIZE"
+
+
+log_note "clone fs gets its parent's userquota/groupquota initially"
+log_must zfs clone -o userquota@$QUSER1=$UQUOTA_SIZE \
+ -o groupquota@$QGROUP=$GQUOTA_SIZE \
+ $TESTPOOL/fs@snap $TESTPOOL/fs-clone
+
+log_must eval "zfs list -r -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "userquota@$QUSER1" $TESTPOOL/fs-clone "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $TESTPOOL/fs-clone "$GQUOTA_SIZE"
+
+log_must eval "zfs list -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL/fs-clone >/dev/null 2>&1"
+
+log_note "zfs promote can not change the previously set user|group quota"
+log_must zfs promote $TESTPOOL/fs-clone
+
+log_must eval "zfs list -r -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "userquota@$QUSER1" $TESTPOOL/fs-clone "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $TESTPOOL/fs-clone "$GQUOTA_SIZE"
+
+log_note "zfs send receive can not change the previously set user|group quota"
+log_must zfs send $TESTPOOL/fs-clone@snap | zfs receive $TESTPOOL/fs-rev
+
+log_must eval "zfs list -r -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "userquota@$QUSER1" $TESTPOOL/fs-rev "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $TESTPOOL/fs-rev "$GQUOTA_SIZE"
+
+log_note "zfs rename can not change the previously set user|group quota"
+log_must zfs rename $TESTPOOL/fs-rev $TESTPOOL/fs-rename
+
+log_must eval "zfs list -r -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "userquota@$QUSER1" $TESTPOOL/fs-rename "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $TESTPOOL/fs-rename "$GQUOTA_SIZE"
+
+log_note "zfs upgrade can not change the previously set user|group quota"
+log_must zfs upgrade $TESTPOOL/fs-rename
+
+log_must eval "zfs list -r -o userquota@$QUSER1,groupquota@$QGROUP \
+ $TESTPOOL >/dev/null 2>&1"
+
+log_must check_quota "userquota@$QUSER1" $TESTPOOL/fs-rename "$UQUOTA_SIZE"
+log_must check_quota "groupquota@$QGROUP" $TESTPOOL/fs-rename "$GQUOTA_SIZE"
+
+log_pass \
+ "the userquota and groupquota can't change during zfs actions"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_012_neg.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_012_neg.ksh
new file mode 100755
index 000000000000..b553f91d40da
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_012_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# userquota and groupquota can not be set against snapshot
+#
+#
+# STRATEGY:
+# 1. Set userquota on snap and check the zfs get
+# 2. Set groupquota on snap and check the zfs get
+#
+
+function cleanup
+{
+ cleanup_quota
+
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+}
+
+log_onexit cleanup
+
+typeset snap_fs=$QFS@snap
+log_assert "Check set userquota and groupquota on snapshot"
+
+log_note "Check can not set user|group quota on snapshot"
+log_must zfs snapshot $snap_fs
+
+log_mustnot zfs set userquota@$QUSER1=$UQUOTA_SIZE $snap_fs
+
+log_mustnot zfs set groupquota@$QGROUP=$GQUOTA_SIZE $snap_fs
+
+log_pass "Check set userquota and groupquota on snapshot"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_013_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userquota_013_pos.ksh
new file mode 100755
index 000000000000..84f2386af5b8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_013_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) 2016 by Jinshan Xiong. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+#
+# DESCRIPTION:
+# Check the basic function of the userobjquota and groupobjquota
+#
+#
+# STRATEGY:
+# 1. Set userobjquota and overwrite the quota size
+# 2. Creating new object should fail with Disc quota exceeded
+# 3. Set groupobjquota and overwrite the quota size
+# 4. Creating new object should fail with Disc quota exceeded
+#
+#
+
+function cleanup
+{
+ log_must rm -f ${QFILE}_*
+ cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "If creating object exceeds {user|group}objquota count, it will fail"
+
+mkmount_writable $QFS
+log_must zfs set xattr=sa $QFS
+
+log_note "Check the userobjquota@$QUSER1"
+log_must zfs set userobjquota@$QUSER1=100 $QFS
+log_must user_run $QUSER1 mkfiles ${QFILE}_1 100
+sync_pool
+log_mustnot user_run $QUSER1 mkfile 1 $OFILE
+cleanup_quota
+
+log_note "Check the groupobjquota@$QGROUP"
+log_must zfs set groupobjquota@$QGROUP=200 $QFS
+mkmount_writable $QFS
+log_must user_run $QUSER1 mkfiles ${QFILE}_2 100
+sync_pool
+log_mustnot user_run $QUSER2 mkfile 1 $OFILE
+
+cleanup
+log_pass "Creating objects exceeds {user|group}objquota count, it as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib b/tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib
new file mode 100644
index 000000000000..70b935d7fe19
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userquota_common.kshlib
@@ -0,0 +1,123 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota.cfg
+
+#
+# reset the userquota and groupquota and delete temporary files
+#
+function cleanup_quota
+{
+ if datasetexists $QFS; then
+ log_must zfs set userquota@$QUSER1=none $QFS
+ log_must zfs set userobjquota@$QUSER1=none $QFS
+ log_must zfs set userquota@$QUSER2=none $QFS
+ log_must zfs set userobjquota@$QUSER2=none $QFS
+ log_must zfs set groupquota@$QGROUP=none $QFS
+ log_must zfs set groupobjquota@$QGROUP=none $QFS
+ recovery_writable $QFS
+ fi
+
+ [[ -f $QFILE ]] && log_must rm -f $QFILE
+ [[ -f $OFILE ]] && log_must rm -f $OFILE
+ sync
+
+ return 0
+}
+
+#
+# delete user and group that created during the test
+#
+function clean_user_group
+{
+ for usr in $QUSER1 $QUSER2; do
+ log_must del_user $usr
+ done
+
+ log_must del_group $QGROUP
+
+ return 0
+}
+
+#
+# make the $QFS's mountpoint writable for all users
+#
+function mkmount_writable
+{
+ typeset fs=$1
+ typeset mntp=$(get_prop mountpoint $fs)
+ log_must chmod 0777 $mntp
+}
+
+#
+# recovery the directory permission for $QFS
+#
+function recovery_writable
+{
+ typeset fs=$1
+ typeset mntp=$(get_prop mountpoint $fs)
+ log_must chmod 0755 $mntp
+}
+
+#
+# check the quota value of a specific FS
+#
+function check_quota
+{
+ typeset fs=$2
+ typeset prop=$1
+ typeset expected=$3
+ typeset value=$(get_prop $prop $fs)
+
+ if (($value != $expected)); then
+ return 1
+ fi
+}
+
+#
+# zfs get prop, which return raw value not -p value.
+#
+function get_value # property dataset
+{
+ typeset prop_val
+ typeset prop=$1
+ typeset dataset=$2
+
+ prop_val=$(zfs get -H -p -o value $prop $dataset 2>/dev/null)
+ if [[ $? -ne 0 ]]; then
+ log_note "Unable to get $prop property for dataset " \
+ "$dataset"
+ return 1
+ fi
+
+ echo $prop_val
+ return 0
+}
diff --git a/tests/zfs-tests/tests/functional/userquota/userspace_001_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userspace_001_pos.ksh
new file mode 100755
index 000000000000..ef05338af41d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userspace_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 2009 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/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the zfs userspace with all parameters
+#
+#
+# STRATEGY:
+# 1. set zfs userspace to a fs
+# 2. write some data to the fs with specified user
+# 3. use zfs userspace with all possible parameters to check the result
+#
+
+function cleanup
+{
+ if datasetexists $snap_fs; then
+ log_must zfs destroy $snap_fs
+ fi
+
+ log_must cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the zfs userspace with all possible parameters"
+
+set -A params -- "-n" "-H" "-p" "-o type,name,used,quota" \
+ "-o name,used,quota" "-o used,quota" "-o used" "-o quota" "-s type" \
+ "-s name" "-s used" "-s quota" "-S type" "-S name" "-S used" "-S quota" \
+ "-t posixuser" "-t posixgroup" "-t all" "-i" "-tsmbuser" "-t smbgroup"
+
+typeset snap_fs=$QFS@snap
+
+log_must zfs set userquota@$QUSER1=100m $QFS
+mkmount_writable $QFS
+log_must user_run $QUSER1 mkfile 50m $QFILE
+sync
+
+log_must zfs snapshot $snap_fs
+
+for param in "${params[@]}"; do
+ log_must eval "zfs userspace $param $QFS >/dev/null 2>&1"
+ log_must eval "zfs userspace $param $snap_fs >/dev/null 2>&1"
+done
+
+log_pass "zfs userspace with all possible parameters pass as expect"
diff --git a/tests/zfs-tests/tests/functional/userquota/userspace_002_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userspace_002_pos.ksh
new file mode 100755
index 000000000000..8161cc152037
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userspace_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the user used size and quota in zfs userspace
+#
+#
+# STRATEGY:
+# 1. set zfs userquota to a fs
+# 2. write some data to the fs with specified user and size
+# 3. use zfs userspace to check the used size and quota size
+#
+
+function cleanup
+{
+ if datasetexists $snapfs; then
+ log_must zfs destroy $snapfs
+ fi
+
+ log_must cleanup_quota
+}
+
+log_onexit cleanup
+
+log_assert "Check the zfs userspace used and quota"
+
+log_must zfs set userquota@$QUSER1=100m $QFS
+
+mkmount_writable $QFS
+
+log_must user_run $QUSER1 mkfile 50m $QFILE
+sync
+
+typeset snapfs=$QFS@snap
+
+log_must zfs snapshot $snapfs
+
+log_must eval "zfs userspace $QFS >/dev/null 2>&1"
+log_must eval "zfs userspace $snapfs >/dev/null 2>&1"
+
+for fs in "$QFS" "$snapfs"; do
+ log_note "check the quota size in zfs userspace $fs"
+ log_must eval "zfs userspace $fs | grep $QUSER1 | grep 100M"
+
+ log_note "check the user used size in zfs userspace $fs"
+ log_must eval "zfs userspace $fs | grep $QUSER1 | grep 50\\.\*M"
+done
+
+log_pass "Check the zfs userspace used and quota"
diff --git a/tests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh b/tests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh
new file mode 100755
index 000000000000..96c3b1930c40
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/userquota/userspace_003_pos.ksh
@@ -0,0 +1,122 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 Jinshan Xiong. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/include/math.shlib
+. $STF_SUITE/tests/functional/userquota/userquota_common.kshlib
+
+#
+# DESCRIPTION:
+# Check the user used object accounting in zfs userspace
+#
+#
+# STRATEGY:
+# 1. create a bunch of files by specific users
+# 2. use zfs userspace to check the used objects
+# 3. change the owner of test files and verify object count
+# 4. delete files and verify object count
+#
+
+function cleanup
+{
+ if datasetexists $snapfs; then
+ log_must zfs destroy $snapfs
+ fi
+
+ log_must rm -f ${QFILE}_*
+ log_must cleanup_quota
+}
+
+function user_object_count
+{
+ typeset fs=$1
+ typeset user=$2
+ typeset -i userspacecnt=$(zfs userspace -oname,objused $fs |
+ awk /$user/'{print $2}')
+ typeset -i zfsgetcnt=$(zfs get -H -ovalue userobjused@$user $fs)
+
+ # 'zfs userspace' and 'zfs get userobjused@' should be equal
+ verify_eq "$userspacecnt" "$zfsgetcnt" "userobjused@$user"
+
+ echo $userspacecnt
+}
+
+log_onexit cleanup
+
+log_assert "Check the zfs userspace object used"
+
+mkmount_writable $QFS
+log_must zfs set xattr=sa $QFS
+
+((user1_cnt = RANDOM % 100 + 1))
+((user2_cnt = RANDOM % 100 + 1))
+
+log_must user_run $QUSER1 mkfiles ${QFILE}_1 $user1_cnt
+log_must user_run $QUSER2 mkfiles ${QFILE}_2 $user2_cnt
+sync_pool
+
+typeset snapfs=$QFS@snap
+
+log_must zfs snapshot $snapfs
+
+log_must eval "zfs userspace $QFS >/dev/null 2>&1"
+log_must eval "zfs userspace $snapfs >/dev/null 2>&1"
+
+for fs in "$QFS" "$snapfs"; do
+ log_note "check the user used objects in zfs userspace $fs"
+ [[ $(user_object_count $fs $QUSER1) -eq $user1_cnt ]] ||
+ log_fail "expected $user1_cnt"
+ [[ $(user_object_count $fs $QUSER2) -eq $user2_cnt ]] ||
+ log_fail "expected $user2_cnt"
+done
+
+log_note "change the owner of files"
+log_must chown $QUSER2 ${QFILE}_1*
+sync_pool
+
+[[ $(user_object_count $QFS $QUSER1) -eq 0 ]] ||
+ log_fail "expected 0 files for $QUSER1"
+
+[[ $(user_object_count $snapfs $QUSER1) -eq $user1_cnt ]] ||
+ log_fail "expected $user_cnt files for $QUSER1 in snapfs"
+
+[[ $(user_object_count $QFS $QUSER2) -eq $((user1_cnt+user2_cnt)) ]] ||
+ log_fail "expected $((user1_cnt+user2_cnt)) files for $QUSER2"
+
+log_note "file removal"
+log_must rm ${QFILE}_*
+sync_pool
+
+[[ $(user_object_count $QFS $QUSER2) -eq 0 ]] ||
+ log_fail "expected 0 files for $QUSER2"
+
+cleanup
+log_pass "Check the zfs userspace object used"
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/Makefile.am b/tests/zfs-tests/tests/functional/vdev_zaps/Makefile.am
new file mode 100644
index 000000000000..4efb1bcf233a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/Makefile.am
@@ -0,0 +1,14 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/vdev_zaps
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ vdev_zaps_001_pos.ksh \
+ vdev_zaps_002_pos.ksh \
+ vdev_zaps_003_pos.ksh \
+ vdev_zaps_004_pos.ksh \
+ vdev_zaps_005_pos.ksh \
+ vdev_zaps_006_pos.ksh \
+ vdev_zaps_007_pos.ksh
+
+dist_pkgdata_DATA = \
+ vdev_zaps.kshlib
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/cleanup.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/cleanup.ksh
new file mode 100755
index 000000000000..6c911198c40f
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/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) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/setup.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/setup.ksh
new file mode 100755
index 000000000000..b52cf92cf370
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/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) 2015 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+rm -rf $TESTDIR || log_fail Could not remove $TESTDIR
+mkdir -p $TESTDIR || log_fail Could not create $TESTDIR
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib
new file mode 100644
index 000000000000..aae2ab40ce58
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps.kshlib
@@ -0,0 +1,114 @@
+#
+# 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.
+#
+
+function get_conf_section # regex conf
+{
+ typeset dsk_line next_vd_line conf section
+ typeset regex="$1"
+ typeset conf="$2"
+
+ dsk_line=$(grep -n "$regex" "$conf" | awk -F: '{print $1}')
+ if [[ -z "$dsk_line" ]]; then
+ return
+ fi
+ next_vd_line=$(tail -n +$dsk_line "$conf" | \
+ grep -n "children\[" | awk -F: '{print $1}' | head -n 1)
+
+ if [[ -n "$next_vd_line" ]]; then
+ section=$(cat "$conf" | sed "1,${dsk_line}d" | head -n \
+ $(($next_vd_line - 2)))
+
+ else
+ section=$(tail -n +$dsk_line "$conf")
+ fi
+ echo "$section"
+}
+
+function get_leaf_vd_zap # dsk conf
+{
+ typeset section=$(get_conf_section "$1" "$2")
+ echo "$section" | egrep \
+ "com.delphix:vdev_zap_leaf: [0-9]+" | awk '{print $2}'
+}
+
+function get_top_vd_zap # dsk conf
+{
+ typeset section=$(get_conf_section "$1" "$2")
+ echo "$section" | egrep \
+ "com.delphix:vdev_zap_top: [0-9]+" | awk '{print $2}'
+}
+
+function assert_has_sentinel # conf
+{
+ res=$(grep "com.delphix:has_per_vdev_zaps" "$1")
+ [[ -z "$res" ]] && log_fail "Pool missing ZAP feature sentinel value"
+}
+
+function assert_zap_common # pool vd lvl zapobj
+{
+ typeset pool=$1
+ typeset vd="$2"
+ typeset lvl=$3
+ typeset zapobj=$4
+
+ if [[ -z "$zapobj" ]]; then
+ log_fail "$vd on $pool has no $lvl ZAP in config"
+ elif [[ -z "$(zdb -d $pool $zapobj | grep 'zap')" ]]; then
+ log_fail "$vd on $pool has no $lvl ZAP in MOS"
+ fi
+}
+
+function assert_top_zap # pool vd conf
+{
+ typeset pool=$1
+ typeset vd="$2"
+ typeset conf=$3
+
+ top_zap=$(get_top_vd_zap "$vd" $conf)
+ assert_zap_common $pool "$vd" "top" $top_zap
+}
+
+function assert_leaf_zap # pool vd conf
+{
+ typeset pool=$1
+ typeset vd="$2"
+ typeset conf=$3
+
+ leaf_zap=$(get_leaf_vd_zap "$vd" $conf)
+ assert_zap_common $pool "$vd" "leaf" $leaf_zap
+}
+
+#
+# Code common to setup/teardown for each test.
+#
+
+function cleanup
+{
+ if datasetexists $TESTPOOL ; then
+ log_must zpool destroy -f $TESTPOOL
+ fi
+ if [[ -e $conf ]]; then
+ log_must rm -f "$conf"
+ fi
+ if [[ -e $POOL2 ]]; then
+ log_must zpool destroy -f $POOL2
+ fi
+}
+
+log_onexit cleanup
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh
new file mode 100755
index 000000000000..fe7dff6570a1
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_001_pos.ksh
@@ -0,0 +1,42 @@
+#!/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.
+#
+
+#
+# Description:
+# Verify that per-vdev ZAPs are created with one vdev.
+#
+# Strategy:
+# 1. Create a pool with one disk.
+# 2. Verify that the disk has a top and leaf ZAP in its config and the MOS.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/vdev_zaps/vdev_zaps.kshlib
+
+log_assert "Per-vdev ZAPs are created on pool creation with one disk."
+
+DISK=${DISKS%% *}
+
+log_must zpool create -f $TESTPOOL $DISK
+conf="$TESTDIR/vz001"
+log_must zdb -PC $TESTPOOL > $conf
+
+assert_top_zap $TESTPOOL $DISK "$conf"
+assert_leaf_zap $TESTPOOL $DISK "$conf"
+assert_has_sentinel "$conf"
+
+log_pass "Per-vdev ZAPs are created in a one-disk pool."
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh
new file mode 100755
index 000000000000..01d04ab156db
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_002_pos.ksh
@@ -0,0 +1,44 @@
+#!/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.
+#
+
+#
+# Description:
+# Verify that per-vdev ZAPs are created with multiple vdevs.
+#
+# Strategy:
+# 1. Create a pool with multiple disks.
+# 2. Verify that each has both a top and leaf zap.
+# 3. Verify that each of those ZAPs exists in the MOS.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/vdev_zaps/vdev_zaps.kshlib
+
+log_assert "Per-vdev ZAPs are created on pool creation with many disks."
+
+log_must zpool create -f $TESTPOOL $DISKS
+
+conf="$TESTDIR/vz002"
+log_must zdb -PC $TESTPOOL > $conf
+
+assert_has_sentinel "$conf"
+for DISK in $DISKS; do
+ assert_top_zap $TESTPOOL $DISK "$conf"
+ assert_leaf_zap $TESTPOOL $DISK "$conf"
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh
new file mode 100755
index 000000000000..b6d9ffbda15c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_003_pos.ksh
@@ -0,0 +1,47 @@
+#!/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.
+#
+
+#
+# Description:
+# Verify that per-vdev ZAPs are created with multi-level vdev tree.
+#
+# Strategy:
+# 1. Create a pool with a multi-disk mirror.
+# 2. Verify that mirror has top ZAP but no leaf ZAP.
+# 3. Verify that each disk has a leaf ZAP but no top ZAP.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/vdev_zaps/vdev_zaps.kshlib
+
+log_assert "Per-vdev ZAPs are created on pool creation with multi-level vdev "\
+ "trees."
+
+log_must zpool create -f $TESTPOOL mirror $DISKS
+
+conf="$TESTDIR/vz003"
+log_must zdb -PC $TESTPOOL > $conf
+
+assert_has_sentinel "$conf"
+assert_top_zap $TESTPOOL "type: 'mirror'" "$conf"
+for DISK in $DISKS; do
+ assert_leaf_zap $TESTPOOL $DISK "$conf"
+ top_zap=$(get_top_vd_zap $DISK "$conf")
+ [[ -n "$top_zap" ]] && log_fail "Leaf vdev $DISK has top-level ZAP."
+done
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh
new file mode 100755
index 000000000000..a84de6577704
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_004_pos.ksh
@@ -0,0 +1,94 @@
+#!/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.
+#
+
+#
+# Description:
+# Verify that per-vdev ZAPs are properly transferred on attach/detach.
+#
+# Strategy:
+# 1. Create a pool with one disk. Verify that it has a top and leaf ZAP.
+# 2. Attach a disk.
+# 3. Verify that top-level and leaf-level ZAPs were transferred properly.
+# 4. Verify that the newly-attached disk has a leaf ZAP.
+# 5. Detach the original disk.
+# 6. Verify that top-level and leaf-level ZAPs were transferred properly.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/vdev_zaps/vdev_zaps.kshlib
+
+log_assert "Per-vdev ZAPs are transferred properly on attach/detach"
+
+DISK=${DISKS%% *}
+log_must zpool create -f $TESTPOOL $DISK
+
+# Make the pool.
+conf="$TESTDIR/vz004"
+log_must zdb -PC $TESTPOOL > $conf
+assert_has_sentinel "$conf"
+orig_top=$(get_top_vd_zap $DISK $conf)
+orig_leaf=$(get_leaf_vd_zap $DISK $conf)
+assert_zap_common $TESTPOOL $DISK "top" $orig_top
+
+#
+# Attach a disk.
+#
+
+disk2=$(echo $DISKS | awk '{print $2}')
+log_must zpool attach $TESTPOOL $DISK $disk2
+log_must zdb -PC $TESTPOOL > $conf
+
+# Ensure top-level ZAP was transferred successfully.
+new_top=$(get_top_vd_zap "type: 'mirror'" $conf)
+if [[ "$new_top" -ne "$orig_top" ]]; then
+ log_fail "Top-level ZAP wasn't transferred successfully on attach."
+fi
+
+# Ensure leaf ZAP of original disk was transferred successfully.
+new_leaf=$(get_leaf_vd_zap $DISK $conf)
+if [[ "$new_leaf" -ne "$orig_leaf" ]]; then
+ log_fail "$DISK used to have leaf-level ZAP $orig_leaf, now has "\
+ "$new_leaf"
+fi
+# Ensure original disk no longer has top-level ZAP.
+dsk1_top=$(get_top_vd_zap $DISK $conf)
+[[ -n "$dsk1_top" ]] && log_fail "$DISK has top-level ZAP, but is only leaf."
+
+# Ensure attached disk got a leaf-level ZAP but not a top-level ZAP.
+dsk2_top=$(get_top_vd_zap $disk2 $conf)
+dsk2_leaf=$(get_leaf_vd_zap $disk2 $conf)
+[[ -n "$dsk2_top" ]] && log_fail "Attached disk $disk2 has top ZAP."
+[[ -z "$dsk2_leaf" ]] && log_fail "Attached disk $disk2 has no leaf ZAP."
+
+#
+# Detach original disk.
+#
+
+log_must zpool detach $TESTPOOL $DISK
+log_must zdb -PC $TESTPOOL > $conf
+
+final_top=$(get_top_vd_zap $disk2 $conf)
+final_leaf=$(get_leaf_vd_zap $disk2 $conf)
+# Make sure top ZAP was successfully transferred.
+[[ "$final_top" -ne "$orig_top" ]] && log_fail "Lost top-level ZAP when "\
+ "promoting $disk2 (expected $orig_top, found $final_top)"
+
+# Make sure leaf ZAP was successfully transferred.
+[[ "$final_leaf" -ne "$dsk2_leaf" ]] && log_fail "$disk2 lost its leaf ZAP "\
+ "on promotion (expected $dsk2_leaf, got $final_leaf)"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh
new file mode 100755
index 000000000000..066be917e436
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_005_pos.ksh
@@ -0,0 +1,63 @@
+#!/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.
+#
+
+#
+# Description:
+# Verify that per-vdev ZAPs persist when the pool is exported and imported.
+#
+# Strategy:
+# 1. Create a pool with a disk.
+# 2. Export the pool and re-import it.
+# 3. Verify that the ZAPs aren't different.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/vdev_zaps/vdev_zaps.kshlib
+
+log_assert "Per-vdev ZAPs persist across export/import."
+
+DISK=${DISKS%% *}
+log_must zpool create -f $TESTPOOL $DISK
+
+# Make the pool.
+conf="$TESTDIR/vz005"
+log_must zdb -PC $TESTPOOL > $conf
+assert_has_sentinel "$conf"
+orig_top=$(get_top_vd_zap $DISK $conf)
+orig_leaf=$(get_leaf_vd_zap $DISK $conf)
+assert_zap_common $TESTPOOL $DISK "top" $orig_top
+assert_zap_common $TESTPOOL $DISK "leaf" $orig_leaf
+log_must zpool sync
+
+# Export the pool.
+log_must zpool export $TESTPOOL
+
+# Import the pool.
+log_must zpool import $TESTPOOL
+
+# Verify that ZAPs persisted.
+log_must zdb -PC $TESTPOOL > $conf
+
+new_top=$(get_top_vd_zap $DISK $conf)
+new_leaf=$(get_leaf_vd_zap $DISK $conf)
+
+[[ "$new_top" -ne "$orig_top" ]] && log_fail "Top ZAP ($new_top) after "\
+ "import does not match top ZAP before export ($orig_top)"
+[[ "$new_leaf" -ne "$orig_leaf" ]] && log_fail "Leaf ZAP ($new_leaf) after "\
+ "import does not match leaf ZAP before export ($orig_leaf)"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh
new file mode 100755
index 000000000000..0476bcda91ff
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_006_pos.ksh
@@ -0,0 +1,46 @@
+#!/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, 2016 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Verify that top-level per-vdev ZAPs are created for added devices
+#
+# Strategy:
+# 1. Create a pool with one disk.
+# 2. Add a disk.
+# 3. Verify its ZAPs were created.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/vdev_zaps/vdev_zaps.kshlib
+
+DISK_ARR=($DISKS)
+DISK=${DISK_ARR[0]}
+log_must zpool create -f $TESTPOOL $DISK
+
+log_assert "Per-vdev ZAPs are created for added vdevs."
+
+log_must zpool add -f $TESTPOOL ${DISK_ARR[1]}
+conf="$TESTDIR/vz006"
+log_must zdb -PC $TESTPOOL > $conf
+
+assert_has_sentinel "$conf"
+orig_top=$(get_top_vd_zap ${DISK_ARR[1]} $conf)
+assert_zap_common $TESTPOOL ${DISK_ARR[1]} "top" $orig_top
+assert_leaf_zap $TESTPOOL ${DISK_ARR[1]} "$conf"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh
new file mode 100755
index 000000000000..1f71b11ee562
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/vdev_zaps/vdev_zaps_007_pos.ksh
@@ -0,0 +1,74 @@
+#!/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.
+#
+
+#
+# Description:
+# Verify that ZAPs are handled properly during mirror pool splitting.
+#
+# Strategy:
+# 1. Create a pool with a two-way mirror.
+# 2. Split the pool.
+# 3. Verify that the ZAPs in the old pool persisted.
+# 4. Import the new pool.
+# 5. Verify that the ZAPs in the new pool persisted.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/vdev_zaps/vdev_zaps.kshlib
+
+DISK_ARR=($DISKS)
+POOL2=${TESTPOOL}2
+log_must zpool create -f $TESTPOOL mirror ${DISK_ARR[0]} ${DISK_ARR[1]}
+
+log_assert "Per-vdev ZAPs persist correctly on the original pool after split."
+conf="$TESTDIR/vz007"
+log_must zdb -PC $TESTPOOL > $conf
+
+assert_has_sentinel "$conf"
+orig_top=$(get_top_vd_zap "type: 'mirror'" $conf)
+orig_leaf0=$(get_leaf_vd_zap ${DISK_ARR[0]} $conf)
+orig_leaf1=$(get_leaf_vd_zap ${DISK_ARR[1]} $conf)
+assert_zap_common $TESTPOOL "type: 'mirror'" "top" $orig_top
+assert_zap_common $TESTPOOL ${DISK_ARR[0]} "leaf" $orig_leaf0
+assert_zap_common $TESTPOOL ${DISK_ARR[1]} "leaf" $orig_leaf1
+
+log_must zpool split $TESTPOOL $POOL2 ${DISK_ARR[1]}
+
+# Make sure old pool's ZAPs are consistent.
+log_must zdb -PC $TESTPOOL > $conf
+new_leaf0=$(get_leaf_vd_zap ${DISK_ARR[0]} $conf)
+new_top_s0=$(get_top_vd_zap ${DISK_ARR[0]} $conf)
+
+[[ "$new_leaf0" -ne "$orig_leaf0" ]] && log_fail "Leaf ZAP in original pool "\
+ "didn't persist (expected $orig_leaf0, got $new_leaf0)"
+[[ "$new_top_s0" -ne "$orig_top" ]] && log_fail "Top ZAP in original pool "\
+ "didn't persist (expected $orig_top, got $new_top_s0)"
+
+log_assert "Per-vdev ZAPs persist on the new pool after import."
+
+# Import the split pool.
+log_must zpool import $POOL2
+log_must zdb -PC $TESTPOOL > $conf
+
+new_leaf1=$(get_leaf_vd_zap ${DISK_ARR[1]} $conf)
+new_top_s1=$(get_top_vd_zap ${DISK_ARR[1]} $conf)
+[[ "$new_leaf1" -ne "$orig_leaf1" ]] && log_fail "Leaf ZAP in new pool "\
+ "didn't persist (expected $orig_leaf1, got $new_leaf1)"
+[[ "$new_top_s1" -ne "$orig_top" ]] && log_fail "Top ZAP in new pool "\
+ "didn't persist (expected $orig_top, got $new_top_s1)"
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/write_dirs/Makefile.am b/tests/zfs-tests/tests/functional/write_dirs/Makefile.am
new file mode 100644
index 000000000000..9bdc46b902e0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/write_dirs/Makefile.am
@@ -0,0 +1,6 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/write_dirs
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ write_dirs_001_pos.ksh \
+ write_dirs_002_pos.ksh
diff --git a/tests/zfs-tests/tests/functional/write_dirs/cleanup.ksh b/tests/zfs-tests/tests/functional/write_dirs/cleanup.ksh
new file mode 100755
index 000000000000..aa032084cdce
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/write_dirs/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+default_cleanup_noexit
+rm -f $TEST_BASE_DIR/disk0
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/write_dirs/setup.ksh b/tests/zfs-tests/tests/functional/write_dirs/setup.ksh
new file mode 100755
index 000000000000..a14eab27e958
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/write_dirs/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+DISK=$TEST_BASE_DIR/disk0
+truncate -s 2G $DISK
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.ksh b/tests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.ksh
new file mode 100755
index 000000000000..f7519eb6dd3b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/write_dirs/write_dirs_001_pos.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Create as many directories with 50 big files each until the file system
+# is full. The zfs file system should be stable and works well.
+#
+# STRATEGY:
+# 1. Create a pool & dataset
+# 2. Make directories in the zfs file system
+# 3. Create 50 big files in each directories
+# 4. Test case exit when the disk is full.
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/$TESTFS
+ wait_freeing $TESTPOOL
+ sync_pool $TESTPOOL
+ zfs create -o mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+typeset -i retval=0
+log_assert "Creating directories with 50 big files in each, until file system "\
+ "is full."
+
+log_onexit cleanup
+
+typeset -i bytes=8192
+typeset -i num_writes=300000
+typeset -i dirnum=50
+typeset -i filenum=50
+
+fill_fs "" $dirnum $filenum $bytes $num_writes
+retval=$?
+if (( retval == 28 )); then
+ log_note "No space left on device."
+elif (( retval != 0 )); then
+ log_fail "Unexpected exit: $retval"
+fi
+
+log_pass "Write big files in a directory succeeded."
diff --git a/tests/zfs-tests/tests/functional/write_dirs/write_dirs_002_pos.ksh b/tests/zfs-tests/tests/functional/write_dirs/write_dirs_002_pos.ksh
new file mode 100755
index 000000000000..07387017fa08
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/write_dirs/write_dirs_002_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 2007 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
+
+#
+# DESCRIPTION:
+# Create as many directories with 5000 files each until the file system
+# is full. The zfs file system should be work well and stable.
+#
+# STRATEGY:
+# 1. Create a pool & dataset
+# 2. Make directories in the zfs file system
+# 3. Create 5000 files in each directories
+# 4. Test case exit when the disk is full
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_dataset $TESTPOOL/$TESTFS
+ wait_freeing $TESTPOOL
+ sync_pool $TESTPOOL
+ zfs create -o mountpoint=$TESTDIR $TESTPOOL/$TESTFS
+}
+
+typeset -i retval=0
+
+log_assert "Creating directories with 5000 files in each, until file system " \
+ "is full."
+
+log_onexit cleanup
+
+typeset -i bytes=8192
+typeset -i num_writes=20
+typeset -i dirnum=50
+typeset -i filenum=5000
+
+fill_fs "" $dirnum $filenum $bytes $num_writes
+retval=$?
+if (( retval == 28 )); then
+ log_note "No space left on device."
+elif (( retval != 0 )); then
+ log_fail "Unexpected exit: $retval"
+fi
+
+log_pass "Create many files in a directory succeeded."
diff --git a/tests/zfs-tests/tests/functional/xattr/Makefile.am b/tests/zfs-tests/tests/functional/xattr/Makefile.am
new file mode 100644
index 000000000000..17001885f1ca
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/Makefile.am
@@ -0,0 +1,21 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/xattr
+dist_pkgdata_SCRIPTS = \
+ setup.ksh \
+ cleanup.ksh \
+ xattr_001_pos.ksh \
+ xattr_002_neg.ksh \
+ xattr_003_neg.ksh \
+ xattr_004_pos.ksh \
+ xattr_005_pos.ksh \
+ xattr_006_pos.ksh \
+ xattr_007_neg.ksh \
+ xattr_008_pos.ksh \
+ xattr_009_neg.ksh \
+ xattr_010_neg.ksh \
+ xattr_011_pos.ksh \
+ xattr_012_pos.ksh \
+ xattr_013_pos.ksh
+
+dist_pkgdata_DATA = \
+ xattr_common.kshlib \
+ xattr.cfg
diff --git a/tests/zfs-tests/tests/functional/xattr/cleanup.ksh b/tests/zfs-tests/tests/functional/xattr/cleanup.ksh
new file mode 100755
index 000000000000..b3629629c78c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/cleanup.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 2007 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/xattr/xattr_common.kshlib
+
+USES_NIS=$(cat $TEST_BASE_DIR/zfs-xattr-test-nis.txt)
+rm $TEST_BASE_DIR/zfs-xattr-test-nis.txt
+
+if [ "${USES_NIS}" == "true" ]
+then
+ svcadm enable svc:/network/nis/client:default
+fi
+
+default_cleanup_noexit
+
+del_user $ZFS_USER
+del_group $ZFS_GROUP
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/xattr/setup.ksh b/tests/zfs-tests/tests/functional/xattr/setup.ksh
new file mode 100755
index 000000000000..d9228c426577
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/setup.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 2007 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/xattr/xattr_common.kshlib
+
+# if we're running NIS, turn it off until we clean up
+# (it can cause useradd to take a long time, hitting our TIMEOUT)
+if is_illumos; then
+ USES_NIS=false
+ svcs svc:/network/nis/client:default | grep online > /dev/null
+ if [ $? -eq 0 ]
+ then
+ svcadm disable -t svc:/network/nis/client:default
+ USES_NIS=true
+ fi
+else
+ USES_NIS=false
+fi
+
+# Make sure we use a brand new user for this
+log_must add_group $ZFS_GROUP
+log_must add_user $ZFS_GROUP $ZFS_USER
+
+echo $ZFS_USER > $TEST_BASE_DIR/zfs-xattr-test-user.txt
+echo $USES_NIS > $TEST_BASE_DIR/zfs-xattr-test-nis.txt
+
+DISK=${DISKS%% *}
+default_setup $DISK
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr.cfg b/tests/zfs-tests/tests/functional/xattr/xattr.cfg
new file mode 100644
index 000000000000..d61fc46cb08c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr.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) 2017 by Lawrence Livermore National Security, LLC.
+# Use is subject to license terms.
+#
+
+export NISSTAFILE=$TEST_BASE_DIR/nis_state
+
+export ZFS_USER=zxtr
+export ZFS_GROUP=zfsgrp
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_001_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_001_pos.ksh
new file mode 100755
index 000000000000..ffb700438528
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_001_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# Creating, reading and writing xattrs on ZFS filesystems works as expected
+#
+# STRATEGY:
+# 1. Create an xattr on a ZFS-based file using runat
+# 2. Read an empty xattr directory
+# 3. Write the xattr using runat and cat
+# 3. Read the xattr using runat
+# 4. Delete the xattr
+# 5. List the xattr namespace successfully, checking for deletion
+#
+
+function cleanup {
+
+ if [ -f $TESTDIR/myfile.$$ ]
+ then
+ log_must rm $TESTDIR/myfile.$$
+ fi
+}
+
+set -A args "on" "sa"
+
+log_assert "Create/read/write/append of xattrs works"
+log_onexit cleanup
+
+for arg in ${args[*]}; do
+ log_must zfs set xattr=$arg $TESTPOOL
+
+ log_must touch $TESTDIR/myfile.$$
+ create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+ verify_write_xattr $TESTDIR/myfile.$$ passwd
+ delete_xattr $TESTDIR/myfile.$$ passwd
+done
+
+log_pass "Create/read/write of xattrs works"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_002_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_002_neg.ksh
new file mode 100755
index 000000000000..e379d1586ea9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_002_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 2007 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/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# Trying to read a non-existent xattr should fail.
+#
+# STRATEGY:
+# 1. Create a file
+# 2. Try to read a non-existent xattr, check that an error is returned.
+#
+
+function cleanup {
+
+ log_must rm $TESTDIR/myfile.$$
+
+}
+
+set -A args "on" "sa"
+
+log_assert "A read of a non-existent xattr fails"
+log_onexit cleanup
+
+for arg in ${args[*]}; do
+ log_must zfs set xattr=$arg $TESTPOOL
+
+ # create a file
+ log_must touch $TESTDIR/myfile.$$
+ log_mustnot eval "cat $TESTDIR/myfile.$$ not-here.txt > /dev/null 2>&1"
+
+ log_pass "A read of a non-existent xattr fails"
+done
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_003_neg.ksh
new file mode 100755
index 000000000000..a3b25ff66266
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_003_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# Attempting to read an xattr on a file for which we have no permissions
+# should fail.
+#
+# STRATEGY:
+# 1. Create a file with an xattr
+# 2. Set the file permissions to 000
+# 3. Check that we're unable to read the xattr as a non-root user
+# 4. Check that we're unable to write an xattr as a non-root user
+#
+
+function cleanup {
+
+ log_must rm $TESTDIR/myfile.$$
+
+}
+
+log_assert "read/write xattr on a file with no permissions fails"
+log_onexit cleanup
+
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+log_must chmod 000 $TESTDIR/myfile.$$
+if is_illumos; then
+ log_mustnot su $ZFS_USER -c "runat $TESTDIR/myfile.$$ cat passwd"
+ log_mustnot su $ZFS_USER -c "runat $TESTDIR/myfile.$$ cp /etc/passwd ."
+else
+ user_run $ZFS_USER eval \
+ "get_xattr passwd $TESTDIR/myfile.$$ >/tmp/passwd.$$"
+ log_mustnot diff /etc/passwd /tmp/passwd.$$
+ log_must rm /tmp/passwd.$$
+
+ user_run $ZFS_USER eval \
+ "set_xattr_stdin passwd $TESTDIR/myfile.$$ </etc/group"
+ log_must chmod 644 $TESTDIR/myfile.$$
+ get_xattr passwd $TESTDIR/myfile.$$ >/tmp/passwd.$$
+ log_must diff /etc/passwd /tmp/passwd.$$
+ log_must rm /tmp/passwd.$$
+fi
+
+log_pass "read/write xattr on a file with no permissions fails"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh
new file mode 100755
index 000000000000..0a25d7ac507d
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_004_pos.ksh
@@ -0,0 +1,143 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# Creating files on ufs|ext and tmpfs, and copying those files to ZFS with
+# appropriate cp flags, the xattrs will still be readable.
+#
+# STRATEGY:
+# 1. Create files in ufs|ext and tmpfs with xattrs
+# 2. Copy those files to zfs
+# 3. Ensure the xattrs can be read and written
+# 4. Do the same in reverse.
+#
+
+# we need to be able to create zvols to hold our test ufs|ext filesystem.
+verify_runnable "global"
+
+# Make sure we clean up properly
+function cleanup {
+ if ismounted /tmp/$NEWFS_DEFAULT_FS.$$ $NEWFS_DEFAULT_FS; then
+ log_must umount /tmp/$NEWFS_DEFAULT_FS.$$
+ log_must rm -rf /tmp/$NEWFS_DEFAULT_FS.$$
+ fi
+}
+
+log_assert "Files from $NEWFS_DEFAULT_FS,tmpfs with xattrs copied to zfs retain xattr info."
+log_onexit cleanup
+
+# Create a ufs|ext file system that we can work in
+log_must zfs create -V128m $TESTPOOL/$TESTFS/zvol
+block_device_wait
+log_must eval "new_fs $ZVOL_DEVDIR/$TESTPOOL/$TESTFS/zvol > /dev/null 2>&1"
+
+log_must mkdir /tmp/$NEWFS_DEFAULT_FS.$$
+log_must mkdir /tmp/tmpfs.$$
+if is_illumos; then
+ log_must mount $ZVOL_DEVDIR/$TESTPOOL/$TESTFS/zvol \
+ /tmp/$NEWFS_DEFAULT_FS.$$
+
+ # Create files in ufs and tmpfs, and set some xattrs on them.
+ log_must touch /tmp/$NEWFS_DEFAULT_FS.$$/$NEWFS_DEFAULT_FS-file.$$
+ log_must touch /tmp/tmpfs-file.$$
+
+ log_must runat /tmp/$NEWFS_DEFAULT_FS.$$/$NEWFS_DEFAULT_FS-file.$$ \
+ cp /etc/passwd .
+ log_must runat /tmp/tmpfs-file.$$ cp /etc/group .
+
+ # copy those files to ZFS
+ log_must cp -@ /tmp/$NEWFS_DEFAULT_FS.$$/$NEWFS_DEFAULT_FS-file.$$ \
+ $TESTDIR
+ log_must cp -@ /tmp/tmpfs-file.$$ $TESTDIR
+
+ # ensure the xattr information has been copied correctly
+ log_must runat $TESTDIR/$NEWFS_DEFAULT_FS-file.$$ \
+ diff passwd /etc/passwd
+ log_must runat $TESTDIR/tmpfs-file.$$ diff group /etc/group
+
+ log_must umount /tmp/$NEWFS_DEFAULT_FS.$$
+else
+ if is_linux; then
+ options="-o user_xattr"
+ fi
+ log_must mount ${options:+""} \
+ $ZVOL_DEVDIR/$TESTPOOL/$TESTFS/zvol /tmp/$NEWFS_DEFAULT_FS.$$
+
+ # Create files in ext and tmpfs, and set some xattrs on them.
+ # Use small values for xattrs for ext compatibility.
+ log_must touch /tmp/$NEWFS_DEFAULT_FS.$$/$NEWFS_DEFAULT_FS-file.$$
+
+ echo "TEST XATTR" >/tmp/xattr1
+ echo "1234567890" >/tmp/xattr2
+
+ log_must set_xattr_stdin xattr1 \
+ /tmp/$NEWFS_DEFAULT_FS.$$/$NEWFS_DEFAULT_FS-file.$$ </tmp/xattr1
+
+ if is_linux; then
+ log_must touch /tmp/tmpfs-file.$$
+ log_must set_xattr_stdin xattr2 /tmp/tmpfs-file.$$ </tmp/xattr2
+ fi
+
+ # copy those files to ZFS
+ if is_freebsd; then
+ # cp does not preserve extattrs on FreeBSD
+ export TAPE="-"
+ log_must eval "tar cC /tmp/$NEWFS_DEFAULT_FS.$$ \
+ $NEWFS_DEFAULT_FS-file.$$ | tar xC $TESTDIR"
+ else
+ log_must cp -a \
+ /tmp/$NEWFS_DEFAULT_FS.$$/$NEWFS_DEFAULT_FS-file.$$ \
+ $TESTDIR
+ log_must cp -a /tmp/tmpfs-file.$$ $TESTDIR
+ fi
+
+ # ensure the xattr information has been copied correctly
+ log_must eval "get_xattr xattr1 $TESTDIR/$NEWFS_DEFAULT_FS-file.$$ \
+ >/tmp/xattr1.$$"
+ log_must diff /tmp/xattr1.$$ /tmp/xattr1
+ log_must rm $TESTDIR/$NEWFS_DEFAULT_FS-file.$$
+ log_must rm /tmp/xattr1 /tmp/xattr1.$$
+
+ if is_linux; then
+ log_must eval "get_xattr xattr2 $TESTDIR/tmpfs-file.$$ \
+ >/tmp/xattr2.$$"
+ log_must diff /tmp/xattr2.$$ /tmp/xattr2
+ log_must rm /tmp/tmpfs-file.$$
+ log_must rm /tmp/xattr2 /tmp/xattr2.$$
+ fi
+
+ log_must umount /tmp/$NEWFS_DEFAULT_FS.$$
+fi
+
+log_pass "Files from $NEWFS_DEFAULT_FS,tmpfs with xattrs copied to zfs retain xattr info."
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_005_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_005_pos.ksh
new file mode 100755
index 000000000000..e5fbe6f18b50
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_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 2007 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/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+# read/write/create/delete xattr on a clone filesystem
+#
+#
+# STRATEGY:
+# 1. Create an xattr on a filesystem
+# 2. Snapshot the filesystem and clone it
+# 3. Verify the xattr can still be read, written, deleted
+# 4. Verify we can create new xattrs on new files created on the clone
+#
+
+function cleanup {
+
+ log_must zfs destroy $TESTPOOL/$TESTFS/clone
+ log_must zfs destroy $TESTPOOL/$TESTFS@snapshot1
+ log_must rm $TESTDIR/myfile.$$
+}
+
+log_assert "read/write/create/delete xattr on a clone filesystem"
+log_onexit cleanup
+
+# create a file, and an xattr on it
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+# snapshot & clone the filesystem
+log_must zfs snapshot $TESTPOOL/$TESTFS@snapshot1
+log_must zfs clone $TESTPOOL/$TESTFS@snapshot1 $TESTPOOL/$TESTFS/clone
+log_must zfs set mountpoint=$TESTDIR/clone $TESTPOOL/$TESTFS/clone
+
+# check for the xattrs on the clone
+verify_xattr $TESTDIR/clone/myfile.$$ passwd /etc/passwd
+
+# check we can create xattrs on the clone
+create_xattr $TESTDIR/clone/myfile.$$ foo /etc/passwd
+delete_xattr $TESTDIR/clone/myfile.$$ foo
+
+# delete the original dataset xattr
+delete_xattr $TESTDIR/myfile.$$ passwd
+
+# verify it's still there on the clone
+verify_xattr $TESTDIR/clone/myfile.$$ passwd /etc/passwd
+delete_xattr $TESTDIR/clone/myfile.$$ passwd
+
+log_pass "read/write/create/delete xattr on a clone filesystem"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_006_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_006_pos.ksh
new file mode 100755
index 000000000000..56f29c88d8eb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_006_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 2007 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/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+# Xattrs present on a file in a snapshot should be visible.
+#
+# STRATEGY:
+# 1. Create a file and give it an xattr
+# 2. Take a snapshot of the filesystem
+# 3. Verify that we can take a snapshot of it.
+#
+
+function cleanup {
+
+ log_must zfs destroy $TESTPOOL/$TESTFS@snap
+ log_must rm $TESTDIR/myfile.$$
+
+}
+
+log_assert "read xattr on a snapshot"
+log_onexit cleanup
+
+# create a file, and an xattr on it
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+# snapshot the filesystem
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap
+
+# check for the xattr on the snapshot
+verify_xattr $TESTDIR/.zfs/snapshot/snap/myfile.$$ passwd /etc/passwd
+
+log_pass "read xattr on a snapshot"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_007_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_007_neg.ksh
new file mode 100755
index 000000000000..5189b627271a
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_007_neg.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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+# Creating and writing xattrs on files in snapshot directories fails. Also,
+# we shouldn't be able to list the xattrs of files in snapshots who didn't have
+# xattrs when the snapshot was created (the xattr namespace wouldn't have been
+# created yet, and snapshots are read-only) See fsattr(5) for more details.
+#
+# STRATEGY:
+# 1. Create a file and add an xattr to it.
+# 2. Create another file, but don't add an xattr to it.
+# 3. Snapshot the filesystem
+# 4. Verify we're unable to alter the xattr on the first file
+# 5. Verify we're unable to list the xattrs on the second file
+#
+
+function cleanup {
+ log_must zfs destroy $TESTPOOL/$TESTFS@snap
+ log_must rm $TESTDIR/myfile2.$$
+ log_must rm $TESTDIR/myfile.$$
+ log_must rm $TEST_BASE_DIR/output.$$
+ [[ -e $TEST_BASE_DIR/expected_output.$$ ]] && log_must rm \
+ $TEST_BASE_DIR/expected_output.$$
+}
+
+log_assert "create/write xattr on a snapshot fails"
+log_onexit cleanup
+
+# create a file, and an xattr on it
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+# create another file that doesn't have an xattr
+log_must touch $TESTDIR/myfile2.$$
+
+# snapshot the filesystem
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap
+
+# we shouldn't be able to alter the first file's xattr
+if is_illumos; then
+ log_mustnot eval " runat $TESTDIR/.zfs/snapshot/snap/myfile.$$ \
+ cp /etc/passwd . > $TEST_BASE_DIR/output.$$ 2>&1"
+ log_must grep -i Read-only $TEST_BASE_DIR/output.$$
+ log_must eval "runat $TESTDIR/.zfs/snapshot/snap/myfile2.$$ \
+ ls > $TEST_BASE_DIR/output.$$ 2>&1"
+ create_expected_output $TEST_BASE_DIR/expected_output.$$ SUNWattr_ro SUNWattr_rw
+else
+ log_mustnot eval "set_xattr_stdin cp $TESTDIR/.zfs/snapshot/snap/myfile.$$ \
+ </etc/passwd > $TEST_BASE_DIR/output.$$ 2>&1"
+ log_must grep -i Read-only $TEST_BASE_DIR/output.$$
+ log_must eval "ls_xattr $TESTDIR/.zfs/snapshot/snap/myfile2.$$ \
+ > $TEST_BASE_DIR/output.$$ 2>&1"
+ log_must eval "ls_xattr $TESTDIR/myfile2.$$ > $TEST_BASE_DIR/expected_output.$$"
+fi
+
+log_must diff $TEST_BASE_DIR/output.$$ $TEST_BASE_DIR/expected_output.$$
+
+log_pass "create/write xattr on a snapshot fails"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_008_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_008_pos.ksh
new file mode 100755
index 000000000000..099a61010afd
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_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 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/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+# We verify that the special . and .. dirs work as expected for xattrs.
+#
+# STRATEGY:
+# 1. Create a file and an xattr on that file
+# 2. List the . directory, verifying the output
+# 3. Verify we're unable to list the ../ directory
+#
+
+function cleanup {
+ typeset file
+
+ for file in $TEST_BASE_DIR/output.$$ $TEST_BASE_DIR/expected-output.$$ \
+ $TESTDIR/myfile.$$ ; do
+ log_must rm -f $file
+ done
+}
+
+log_assert "special . and .. dirs work as expected for xattrs"
+log_onexit cleanup
+
+# create a file, and an xattr on it
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+# listing the directory .
+log_must eval "runat $TESTDIR/myfile.$$ ls . > $TEST_BASE_DIR/output.$$"
+create_expected_output $TEST_BASE_DIR/expected-output.$$ \
+ SUNWattr_ro SUNWattr_rw passwd
+log_must diff $TEST_BASE_DIR/output.$$ $TEST_BASE_DIR/expected-output.$$
+# list the directory . long form
+log_must eval "runat $TESTDIR/myfile.$$ ls -a . > $TEST_BASE_DIR/output.$$"
+create_expected_output $TEST_BASE_DIR/expected-output.$$ . .. \
+ SUNWattr_ro SUNWattr_rw passwd
+log_must diff $TEST_BASE_DIR/output.$$ $TEST_BASE_DIR/expected-output.$$
+
+# list the directory .. expecting one file
+OUTPUT=$(runat $TESTDIR/myfile.$$ ls ..)
+if [ "$OUTPUT" != ".." ]
+then
+ log_fail "Listing the .. directory doesn't show \"..\" as expected."
+fi
+
+# verify we can't list ../
+log_mustnot eval "runat $TESTDIR/myfile.$$ ls ../ > /dev/null 2>&1"
+
+log_pass "special . and .. dirs work as expected for xattrs"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_009_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_009_neg.ksh
new file mode 100755
index 000000000000..c9d636ecbca3
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_009_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 2007 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/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+# links between xattr and normal file namespace fail
+#
+# STRATEGY:
+# 1. Create a file and add an xattr to it (to ensure the namespace exists)
+# 2. Verify we're unable to create a symbolic link
+# 3. Verify we're unable to create a hard link
+#
+
+function cleanup {
+
+ log_must rm $TESTDIR/myfile.$$
+
+}
+
+log_assert "links between xattr and normal file namespace fail"
+log_onexit cleanup
+
+# create a file, and an xattr on it
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+# Try to create a soft link from the xattr namespace to the default namespace
+log_mustnot runat $TESTDIR/myfile.$$ ln -s /etc/passwd foo
+
+# Try to create a hard link from the xattr namespace to the default namespace
+log_mustnot runat $TESTDIR/myfile.$$ ln /etc/passwd foo
+
+log_pass "links between xattr and normal file namespace fail"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_010_neg.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_010_neg.ksh
new file mode 100755
index 000000000000..43502bfff28b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_010_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify that mkdir and various mknods fail inside the xattr namespace
+#
+# STRATEGY:
+# 1. Create a file and add an xattr to it (to ensure the namespace exists)
+# 2. Verify that mkdir fails inside the xattr namespace
+# 3. Verify that various mknods fails inside the xattr namespace
+#
+#
+
+function cleanup {
+
+ log_must rm $TESTDIR/myfile.$$
+}
+
+log_assert "mkdir, mknod fail"
+log_onexit cleanup
+
+# create a file, and an xattr on it
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+# Try to create directory in the xattr namespace
+log_mustnot runat $TESTDIR/myfile.$$ mkdir foo
+
+# Try to create a range of different filetypes in the xattr namespace
+log_mustnot runat $TESTDIR/myfile.$$ mknod block b 888 888
+
+log_mustnot runat $TESTDIR/myfile.$$ mknod char c
+
+log_mustnot runat $TESTDIR/myfile.$$ mknod fifo p
+
+log_pass "mkdir, mknod fail"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh
new file mode 100755
index 000000000000..fdfefbf674e9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_011_pos.ksh
@@ -0,0 +1,241 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+#
+# Basic applications work with xattrs: cpio cp find mv pax tar
+#
+# STRATEGY:
+# 1. For each application
+# 2. Create an xattr and archive/move/copy/find files with xattr support
+# 3. Also check that when appropriate flag is not used, the xattr
+# doesn't get copied
+#
+
+function cleanup {
+
+ log_must rm $TESTDIR/myfile.$$
+}
+
+log_assert "Basic applications work with xattrs: cpio cp find mv pax tar"
+log_onexit cleanup
+
+# Create a file, and set an xattr on it. This file is used in several of the
+# test scenarios below.
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+
+# For the archive applications below (tar, cpio, pax)
+# we create two archives, one with xattrs, one without
+# and try various cpio options extracting the archives
+# with and without xattr support, checking for correct behaviour
+
+if is_illumos; then
+ log_note "Checking cpio"
+ log_must touch $TESTDIR/cpio.$$
+ create_xattr $TESTDIR/cpio.$$ passwd /etc/passwd
+ echo $TESTDIR/cpio.$$ | cpio -o@ > $TEST_BASE_DIR/xattr.$$.cpio
+ echo $TESTDIR/cpio.$$ | cpio -o > $TEST_BASE_DIR/noxattr.$$.cpio
+
+ # we should have no xattr here
+ log_must cpio -iu < $TEST_BASE_DIR/xattr.$$.cpio
+ log_mustnot eval "runat $TESTDIR/cpio.$$ cat passwd > /dev/null 2>&1"
+
+ # we should have an xattr here
+ log_must cpio -iu@ < $TEST_BASE_DIR/xattr.$$.cpio
+ log_must eval "runat $TESTDIR/cpio.$$ cat passwd > /dev/null 2>&1"
+
+ # we should have no xattr here
+ log_must cpio -iu < $TEST_BASE_DIR/noxattr.$$.cpio
+ log_mustnot eval "runat $TESTDIR/cpio.$$ cat passwd > /dev/null 2>&1"
+
+ # we should have no xattr here
+ log_must cpio -iu@ < $TEST_BASE_DIR/noxattr.$$.cpio
+ log_mustnot eval "runat $TESTDIR/cpio.$$ cat passwd > /dev/null 2>&1"
+ log_must rm $TESTDIR/cpio.$$ $TEST_BASE_DIR/xattr.$$.cpio $TEST_BASE_DIR/noxattr.$$.cpio
+else
+ log_note "Checking cpio - unsupported"
+fi
+
+# check that with the right flag, the xattr is preserved
+if is_freebsd; then
+ log_note "Checking cp - unsupported"
+elif is_linux; then
+ log_note "Checking cp"
+ log_must cp -a $TESTDIR/myfile.$$ $TESTDIR/myfile2.$$
+
+ compare_xattrs $TESTDIR/myfile.$$ $TESTDIR/myfile2.$$ passwd
+ log_must rm $TESTDIR/myfile2.$$
+
+ # without the right flag, there should be no xattr
+ log_must cp $TESTDIR/myfile.$$ $TESTDIR/myfile2.$$
+ log_mustnot get_xattr passwd $TESTDIR/myfile2.$$
+ log_must rm $TESTDIR/myfile2.$$
+else
+ log_note "Checking cp"
+ log_must cp -@ $TESTDIR/myfile.$$ $TESTDIR/myfile2.$$
+
+ compare_xattrs $TESTDIR/myfile.$$ $TESTDIR/myfile2.$$ passwd
+ log_must rm $TESTDIR/myfile2.$$
+
+ # without the right flag, there should be no xattr
+ log_must cp $TESTDIR/myfile.$$ $TESTDIR/myfile2.$$
+ log_mustnot eval "runat $TESTDIR/myfile2.$$ ls passwd > /dev/null 2>&1"
+ log_must rm $TESTDIR/myfile2.$$
+fi
+
+# create a file without xattrs, and check that find -xattr only finds
+# our test file that has an xattr.
+if is_illumos; then
+ log_note "Checking find"
+ log_must mkdir $TESTDIR/noxattrs
+ log_must touch $TESTDIR/noxattrs/no-xattr
+
+ find $TESTDIR -xattr | grep myfile.$$
+ [[ $? -ne 0 ]] && \
+ log_fail "find -xattr didn't find our file that had an xattr."
+ find $TESTDIR -xattr | grep no-xattr
+ [[ $? -eq 0 ]] && \
+ log_fail "find -xattr found a file that didn't have an xattr."
+ log_must rm -rf $TESTDIR/noxattrs
+else
+ log_note "Checking find - unsupported"
+fi
+
+log_note "Checking mv"
+# mv doesn't have any flags to preserve/omit xattrs - they're
+# always moved.
+log_must touch $TESTDIR/mvfile.$$
+create_xattr $TESTDIR/mvfile.$$ passwd /etc/passwd
+log_must mv $TESTDIR/mvfile.$$ $TESTDIR/mvfile2.$$
+verify_xattr $TESTDIR/mvfile2.$$ passwd /etc/passwd
+log_must rm $TESTDIR/mvfile2.$$
+
+if is_illumos; then
+ log_note "Checking pax"
+ log_must touch $TESTDIR/pax.$$
+ create_xattr $TESTDIR/pax.$$ passwd /etc/passwd
+ log_must pax -w -f $TESTDIR/noxattr.pax $TESTDIR/pax.$$
+ log_must pax -w@ -f $TESTDIR/xattr.pax $TESTDIR/pax.$$
+ log_must rm $TESTDIR/pax.$$
+
+ # we should have no xattr here
+ log_must pax -r -f $TESTDIR/noxattr.pax
+ log_mustnot eval "runat $TESTDIR/pax.$$ cat passwd > /dev/null 2>&1"
+ log_must rm $TESTDIR/pax.$$
+
+ # we should have no xattr here
+ log_must pax -r@ -f $TESTDIR/noxattr.pax
+ log_mustnot eval "runat $TESTDIR/pax.$$ cat passwd > /dev/null 2>&1"
+ log_must rm $TESTDIR/pax.$$
+
+ # we should have an xattr here
+ log_must pax -r@ -f $TESTDIR/xattr.pax
+ verify_xattr $TESTDIR/pax.$$ passwd /etc/passwd
+ log_must rm $TESTDIR/pax.$$
+
+ # we should have no xattr here
+ log_must pax -r -f $TESTDIR/xattr.pax $TESTDIR
+ log_mustnot eval "runat $TESTDIR/pax.$$ cat passwd > /dev/null 2>&1"
+ log_must rm $TESTDIR/pax.$$ $TESTDIR/noxattr.pax $TESTDIR/xattr.pax
+else
+ log_note "Checking pax - unsupported"
+fi
+
+log_note "Checking tar"
+if is_illumos; then
+ log_must touch $TESTDIR/tar.$$
+ create_xattr $TESTDIR/tar.$$ passwd /etc/passwd
+
+ log_must cd $TESTDIR
+
+ log_must tar cf noxattr.tar tar.$$
+ log_must tar c@f xattr.tar tar.$$
+ log_must rm $TESTDIR/tar.$$
+
+ # we should have no xattr here
+ log_must tar xf xattr.tar
+ log_mustnot eval "runat $TESTDIR/tar.$$ cat passwd > /dev/null 2>&1"
+ log_must rm $TESTDIR/tar.$$
+
+ # we should have an xattr here
+ log_must tar x@f xattr.tar
+ verify_xattr tar.$$ passwd /etc/passwd
+ log_must rm $TESTDIR/tar.$$
+
+ # we should have no xattr here
+ log_must tar xf $TESTDIR/noxattr.tar
+ log_mustnot eval "runat $TESTDIR/tar.$$ cat passwd > /dev/null 2>&1"
+ log_must rm $TESTDIR/tar.$$
+
+ # we should have no xattr here
+ log_must tar x@f $TESTDIR/noxattr.tar
+ log_mustnot eval "runat $TESTDIR/tar.$$ cat passwd > /dev/null 2>&1"
+ log_must rm $TESTDIR/tar.$$ $TESTDIR/noxattr.tar $TESTDIR/xattr.tar
+else
+ log_must touch $TESTDIR/tar.$$
+ create_xattr $TESTDIR/tar.$$ passwd /etc/passwd
+
+ log_must cd $TESTDIR
+
+ log_must tar --no-xattrs -cf noxattr.tar tar.$$
+ log_must tar --xattrs -cf xattr.tar tar.$$
+ log_must rm $TESTDIR/tar.$$
+
+ # we should have no xattr here
+ log_must tar --no-xattrs -xf xattr.tar
+ log_mustnot get_xattr passwd $TESTDIR/tar.$$
+ log_must rm $TESTDIR/tar.$$
+
+ # we should have an xattr here
+ log_must tar --xattrs -xf xattr.tar
+ verify_xattr tar.$$ passwd /etc/passwd
+ log_must rm $TESTDIR/tar.$$
+
+ # we should have no xattr here
+ log_must tar --no-xattrs -xf $TESTDIR/noxattr.tar
+ log_mustnot get_xattr passwd $TESTDIR/tar.$$
+ log_must rm $TESTDIR/tar.$$
+
+ # we should have no xattr here
+ log_must tar --xattrs -xf $TESTDIR/noxattr.tar
+ log_mustnot get_xattr passwd $TESTDIR/tar.$$
+ log_must rm $TESTDIR/tar.$$ $TESTDIR/noxattr.tar $TESTDIR/xattr.tar
+fi
+
+log_assert "Basic applications work with xattrs: cpio cp find mv pax tar"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh
new file mode 100755
index 000000000000..693ca0a634d5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_012_pos.ksh
@@ -0,0 +1,122 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 (c) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+# xattr file sizes count towards normal disk usage
+#
+# STRATEGY:
+# 1. Create a file, and check pool and filesystem usage
+# 2. Create a 200mb xattr in that file
+# 3. Check pool and filesystem usage, to ensure it reflects the size
+# of the xattr
+#
+
+function cleanup {
+ log_must rm $TESTDIR/myfile.$$
+ if is_freebsd; then
+ log_must rm /tmp/xattr.$$
+ fi
+}
+
+function get_pool_size {
+ poolname=$1
+ psize=$(zpool list -H -o allocated $poolname)
+ if [[ $psize == *[mM] ]]
+ then
+ returnvalue=$(echo $psize | sed -e 's/m//g' -e 's/M//g')
+ returnvalue=$((returnvalue * 1024))
+ else
+ returnvalue=$(echo $psize | sed -e 's/k//g' -e 's/K//g')
+ fi
+ echo $returnvalue
+}
+
+log_assert "xattr file sizes count towards normal disk usage"
+log_onexit cleanup
+
+log_must touch $TESTDIR/myfile.$$
+
+POOL_SIZE=0
+NEW_POOL_SIZE=0
+
+if is_global_zone
+then
+ # get pool and filesystem sizes. Since we're starting with an empty
+ # pool, the usage should be small - a few k.
+ POOL_SIZE=$(get_pool_size $TESTPOOL)
+fi
+
+FS_SIZE=$(zfs get -p -H -o value used $TESTPOOL/$TESTFS)
+
+if is_freebsd; then
+ # FreeBSD setextattr has awful scaling with respect to input size.
+ # It reallocs after every 1024 bytes. For now we'll just break up
+ # the 200MB into 10 20MB attributes, but this test could be revisited
+ # if someone cared about large extattrs and improves setextattr -i.
+ log_must mkfile 20m /tmp/xattr.$$
+ for i in {0..10}; do
+ log_must eval "set_xattr_stdin xattr$i $TESTDIR/myfile.$$ \
+ < /tmp/xattr.$$"
+ done
+elif is_linux; then
+ # Linux setxattr() syscalls limits individual xattrs to 64k. Create
+ # 100 files, with 128 xattrs each of size 16k. 100*128*16k=200m
+ log_must xattrtest -k -f 100 -x 128 -s 16384 -p $TESTDIR
+else
+ log_must runat $TESTDIR/myfile.$$ mkfile 200m xattr
+fi
+
+#Make sure the newly created file is counted into zpool usage
+sync_pool
+
+# now check to see if our pool disk usage has increased
+if is_global_zone
+then
+ NEW_POOL_SIZE=$(get_pool_size $TESTPOOL)
+ (($NEW_POOL_SIZE <= $POOL_SIZE)) && \
+ log_fail "The new pool size $NEW_POOL_SIZE was less \
+ than or equal to the old pool size $POOL_SIZE."
+
+fi
+
+# also make sure our filesystem usage has increased
+NEW_FS_SIZE=$(zfs get -p -H -o value used $TESTPOOL/$TESTFS)
+(($NEW_FS_SIZE <= $FS_SIZE)) && \
+ log_fail "The new filesystem size $NEW_FS_SIZE was less \
+ than or equal to the old filesystem size $FS_SIZE."
+
+log_pass "xattr file sizes count towards normal disk usage"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_013_pos.ksh b/tests/zfs-tests/tests/functional/xattr/xattr_013_pos.ksh
new file mode 100755
index 000000000000..efa9faab96f5
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_013_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 2007 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/xattr/xattr_common.kshlib
+
+#
+# DESCRIPTION:
+# The noxattr mount option functions as expected
+#
+# STRATEGY:
+# 1. Create a file on a filesystem and add an xattr to it
+# 2. Unmount the filesystem, and mount it -o noxattr
+# 3. Verify that the xattr cannot be read and new files
+# cannot have xattrs set on them.
+# 4. Unmount and mount the filesystem normally
+# 5. Verify that xattrs can be set and accessed again
+#
+
+function cleanup {
+
+ log_must rm $TESTDIR/myfile.$$
+}
+
+
+log_assert "The noxattr mount option functions as expected"
+log_onexit cleanup
+
+zfs set 2>&1 | grep xattr > /dev/null
+if [ $? -ne 0 ]
+then
+ log_unsupported "noxattr mount option not supported on this release."
+fi
+
+log_must touch $TESTDIR/myfile.$$
+create_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+log_must umount $TESTDIR
+log_must zfs mount -o noxattr $TESTPOOL/$TESTFS
+
+# check that we can't perform xattr operations
+if is_illumos; then
+ log_mustnot eval "runat $TESTDIR/myfile.$$ cat passwd > /dev/null 2>&1"
+ log_mustnot eval "runat $TESTDIR/myfile.$$ rm passwd > /dev/null 2>&1"
+ log_mustnot eval "runat $TESTDIR/myfile.$$ cp /etc/passwd . \
+ > /dev/null 2>&1"
+
+ log_must touch $TESTDIR/new.$$
+ log_mustnot eval "runat $TESTDIR/new.$$ cp /etc/passwd . \
+ > /dev/null 2>&1"
+ log_mustnot eval "runat $TESTDIR/new.$$ rm passwd > /dev/null 2>&1"
+else
+ log_mustnot get_xattr passwd $TESTDIR/myfile.$$
+ log_mustnot rm_xattr passwd $TESTDIR/myfile.$$
+ log_mustnot set_xattr_stdin passwd $TESTDIR/myfile.$$ </etc/passwd
+
+ log_must touch $TESTDIR/new.$$
+ log_mustnot set_xattr_stdin passwd $TESTDIR/new.$$ </etc/passwd
+ log_mustnot rm_xattr passwd $TESTDIR/new.$$
+fi
+
+# now mount the filesystem again as normal
+log_must umount $TESTDIR
+log_must zfs mount $TESTPOOL/$TESTFS
+
+# we should still have an xattr on the first file
+verify_xattr $TESTDIR/myfile.$$ passwd /etc/passwd
+
+# there should be no xattr on the file we created while the fs was mounted
+# -o noxattr
+if is_illumos; then
+ log_mustnot eval "runat $TESTDIR/new.$$ cat passwd > /dev/null 2>&1"
+else
+ log_mustnot get_xattr passwd $TESTDIR/new.$$
+fi
+create_xattr $TESTDIR/new.$$ passwd /etc/passwd
+
+log_pass "The noxattr mount option functions as expected"
diff --git a/tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib b/tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib
new file mode 100644
index 000000000000..bc06f4716867
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/xattr/xattr_common.kshlib
@@ -0,0 +1,137 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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/xattr/xattr.cfg
+
+# a function that takes a file, then creates and verifies
+# an xattr on that file. The xattr_contents is the file
+# that should appear in the xattr namespace.
+function create_xattr { # filename xattr_name xattr_contents
+ typeset FILE=$1
+ typeset XATTR_NAME=$2
+ typeset XATTR_CONTENTS=$3
+
+ if is_illumos; then
+ # read any empty xattr on that file
+ log_must runat $FILE ls
+ # create the xattr
+ log_must runat $FILE cp $XATTR_CONTENTS $XATTR_NAME
+ else
+ log_mustnot get_xattr $XATTR_NAME $FILE
+ log_must set_xattr_stdin $XATTR_NAME $FILE < $XATTR_CONTENTS
+ fi
+
+ verify_xattr $FILE $XATTR_NAME $XATTR_CONTENTS
+}
+
+# a function that compares the a single xattr between two files
+# and checks to see if their contents are identical
+function compare_xattrs { # filename1 filename2 xattr_name
+ typeset FILE1=$1
+ typeset FILE2=$2
+ typeset XATTR_NAME=$3
+
+ if is_illumos; then
+ runat $FILE1 cat $XATTR_NAME > $TEST_BASE_DIR/file1.$$
+ runat $FILE2 cat $XATTR_NAME > $TEST_BASE_DIR/file2.$$
+ else
+ get_xattr $XATTR_NAME $FILE1 > $TEST_BASE_DIR/file1.$$
+ get_xattr $XATTR_NAME $FILE2 > $TEST_BASE_DIR/file2.$$
+ fi
+
+ log_must diff $TEST_BASE_DIR/file1.$$ $TEST_BASE_DIR/file2.$$
+ log_must rm $TEST_BASE_DIR/file1.$$ $TEST_BASE_DIR/file2.$$
+}
+
+function verify_xattr { # filename xattr_name xattr_contents
+ typeset FILE=$1
+ typeset XATTR_NAME=$2
+ typeset XATTR_CONTENTS=$3
+
+ # read the xattr, writing it to a temp file
+ if is_illumos; then
+ log_must eval \
+ "runat $FILE cat $XATTR_NAME > $TEST_BASE_DIR/$XATTR_NAME.$$ 2>&1"
+ else
+ log_must eval \
+ "get_xattr $XATTR_NAME $FILE > $TEST_BASE_DIR/$XATTR_NAME.$$"
+ fi
+
+ log_must diff $XATTR_CONTENTS $TEST_BASE_DIR/$XATTR_NAME.$$
+ rm $TEST_BASE_DIR/$XATTR_NAME.$$
+}
+
+function delete_xattr { # filename xattr_name
+ typeset FILE=$1
+ typeset XATTR_NAME=$2
+
+ # delete the xattr
+ if is_illumos; then
+ log_must runat $FILE rm $XATTR_NAME
+ log_mustnot eval "runat $FILE ls $XATTR_NAME > /dev/null 2>&1"
+ else
+ log_must rm_xattr $XATTR_NAME $FILE
+ log_mustnot get_xattr $XATTR_NAME $FILE
+ fi
+}
+
+# not sure about this : really this should be testing write/append
+function verify_write_xattr { # filename xattr_name
+ typeset FILE=$1
+ typeset XATTR_NAME=$2
+
+ if is_illumos; then
+ log_must eval "runat $FILE dd if=/etc/passwd of=$XATTR_NAME"
+ log_must eval \
+ "runat $FILE cat $XATTR_NAME > $TEST_BASE_DIR/$XATTR_NAME.$$ 2>&1"
+ else
+ log_must set_xattr_stdin $XATTR_NAME $FILE < /etc/passwd
+ log_must eval \
+ "get_xattr $XATTR_NAME $FILE > $TEST_BASE_DIR/$XATTR_NAME.$$"
+ fi
+ log_must dd if=/etc/passwd of=$TEST_BASE_DIR/passwd_dd.$$
+ log_must diff $TEST_BASE_DIR/passwd_dd.$$ $TEST_BASE_DIR/$XATTR_NAME.$$
+ log_must rm $TEST_BASE_DIR/passwd_dd.$$ $TEST_BASE_DIR/$XATTR_NAME.$$
+}
+
+# this function is to create the expected output
+function create_expected_output { # expected_output_file contents_of_the_output
+ typeset FILE=$1
+ shift
+ if [[ -f $FILE ]]; then
+ log_must rm $FILE
+ fi
+
+ for line in $@
+ do
+ log_must eval "echo $line >> $FILE"
+ done
+}
diff --git a/tests/zfs-tests/tests/functional/zvol/Makefile.am b/tests/zfs-tests/tests/functional/zvol/Makefile.am
new file mode 100644
index 000000000000..e4910754bb81
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/Makefile.am
@@ -0,0 +1,10 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/zvol
+dist_pkgdata_DATA = \
+ zvol.cfg \
+ zvol_common.shlib
+
+SUBDIRS = \
+ zvol_ENOSPC \
+ zvol_cli \
+ zvol_misc \
+ zvol_swap
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol.cfg b/tests/zfs-tests/tests/functional/zvol/zvol.cfg
new file mode 100644
index 000000000000..fb2a0385a24c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol.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) 2013 by Delphix. All rights reserved.
+#
+
+export DISK=${DISKS%% *}
+
+export TESTVOL=testvol
+export TESTFILE=testfile
+export TESTSNAP=testsnap
+export VOLSIZE=256m
+export BLOCKSIZE=4K
+export DATA=0
+export ENOSPC=28
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/Makefile.am b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/Makefile.am
new file mode 100644
index 000000000000..9cd9b4149eaf
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/Makefile.am
@@ -0,0 +1,8 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/zvol/zvol_ENOSPC
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zvol_ENOSPC_001_pos.ksh
+
+dist_pkgdata_DATA = \
+ zvol_ENOSPC.cfg
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/cleanup.ksh
new file mode 100755
index 000000000000..c9250d4e53e9
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+verify_runnable "global"
+
+ismounted $TESTDIR $NEWFS_DEFAULT_FS
+(( $? == 0 )) && log_must umount -f $TESTDIR
+
+[[ -e $TESTDIR ]] && rm -rf $TESTDIR
+
+default_zvol_cleanup
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.ksh
new file mode 100755
index 000000000000..dcdfc86d4e7b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/setup.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 2007 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/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg
+
+verify_runnable "global"
+
+DISK=${DISKS%% *}
+if is_mpath_device $DISK; then
+ delete_partitions
+fi
+
+default_zvol_setup $DISK $VOLSIZE $BLOCKSIZE
+
+log_must new_fs ${ZVOL_RDEVDIR}/$TESTPOOL/$TESTVOL
+
+log_must mkdir $TESTDIR
+log_must mount ${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL $TESTDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg
new file mode 100644
index 000000000000..8a99225ba9ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC.cfg
@@ -0,0 +1,41 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+export DISKSARRAY=$DISKS
+
+if is_linux; then
+ set_slice_prefix
+ set_device_dir
+fi
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_pos.ksh
new file mode 100755
index 000000000000..f19fa9df3bf4
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_ENOSPC/zvol_ENOSPC_001_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 2007 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/zvol/zvol.cfg
+
+#
+# DESCRIPTION:
+# A zvol volume will return ENOSPC when the underlying pool runs out of
+# space.
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Create a zvol volume
+# 3. Create a ufs file system ontop of the zvol
+# 4. Mount the ufs file system
+# 5. Fill volume until ENOSPC is returned
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ rm -rf $TESTDIR/*
+}
+
+log_assert "A zvol volume will return ENOSPC when the underlying pool " \
+ "runs out of space."
+
+log_onexit cleanup
+
+typeset -i fn=0
+typeset -i retval=0
+
+BLOCKSZ=$(( 1024 * 1024 ))
+NUM_WRITES=40
+
+while (( 1 )); do
+ file_write -o create -f $TESTDIR/testfile$$.$fn \
+ -b $BLOCKSZ -c $NUM_WRITES
+ retval=$?
+ if (( $retval != 0 )); then
+ break
+ fi
+
+ (( fn = fn + 1 ))
+done
+
+(( $retval != $ENOSPC )) &&
+ log_fail "ENOSPC was not returned, $retval was received instead"
+
+log_pass "ENOSPC was returned as expected"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/Makefile.am b/tests/zfs-tests/tests/functional/zvol/zvol_cli/Makefile.am
new file mode 100644
index 000000000000..c6b15684f45e
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/Makefile.am
@@ -0,0 +1,10 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/zvol/zvol_cli
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zvol_cli_001_pos.ksh \
+ zvol_cli_002_pos.ksh \
+ zvol_cli_003_neg.ksh
+
+dist_pkgdata_DATA = \
+ zvol_cli.cfg
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/cleanup.ksh
new file mode 100755
index 000000000000..79836c2e5d18
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+verify_runnable "global"
+
+default_zvol_cleanup
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh
new file mode 100755
index 000000000000..c24933df2fbc
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/setup.ksh
@@ -0,0 +1,45 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_cli/zvol_cli.cfg
+
+verify_runnable "global"
+
+DISK=${DISKS%% *}
+if is_mpath_device $DISK; then
+ delete_partitions
+fi
+
+default_zvol_setup $DISK $VOLSIZE
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg
new file mode 100644
index 000000000000..8a99225ba9ec
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli.cfg
@@ -0,0 +1,41 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "global"
+
+export DISK_ARRAY_NUM=$(echo ${DISKS} | nawk '{print NF}')
+export DISKSARRAY=$DISKS
+
+if is_linux; then
+ set_slice_prefix
+ set_device_dir
+fi
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_001_pos.ksh
new file mode 100755
index 000000000000..847443ac0e95
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_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 2007 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
+
+#
+# DESCRIPTION:
+# Executing well-formed 'zfs list' commands should return success
+#
+# STRATEGY:
+# 1. Create an array of valid options.
+# 2. Execute each element in the array.
+# 3. Verify success is returned.
+#
+
+verify_runnable "global"
+
+TESTVOL='testvol'
+
+set -A args "list" "list -r" \
+ "list $TESTPOOL/$TESTVOL" "list -r $TESTPOOL/$TESTVOL" \
+ "list -H $TESTPOOL/$TESTVOL" "list -Hr $TESTPOOL/$TESTVOL" \
+ "list -rH $TESTPOOL/$TESTVOL" "list -o name $TESTPOOL/$TESTVOL" \
+ "list -r -o name $TESTPOOL/$TESTVOL" "list -H -o name $TESTPOOL/$TESTVOL" \
+ "list -rH -o name $TESTPOOL/$TESTVOL"
+
+log_assert "Executing well-formed 'zfs list' commands should return success"
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_must eval "zfs ${args[i]} > /dev/null"
+ ((i = i + 1))
+done
+
+log_pass "Executing zfs list on volume works as expected"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_pos.ksh
new file mode 100755
index 000000000000..e5b69239f566
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Creating a volume with a 50 letter name should work.
+#
+# STRATEGY:
+# 1. Using a very long name, create a zvol
+# 2. Verify volume exists
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $TESTPOOL/$LONGVOLNAME && \
+ zfs destroy $TESTPOOL/$LONGVOLNAME
+}
+
+log_onexit cleanup
+
+log_assert "Creating a volume a 50 letter name should work."
+
+LONGVOLNAME="volumename50charslong_0123456789012345678901234567"
+
+log_must zfs create -V $VOLSIZE $TESTPOOL/$LONGVOLNAME
+
+datasetexists $TESTPOOL/$LONGVOLNAME || \
+ log_fail "Couldn't find long volume name"
+
+log_pass "Created a 50-letter zvol volume name"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_neg.ksh
new file mode 100755
index 000000000000..779a0baaa091
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_cli/zvol_cli_003_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Try each ZFS volume 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 "global"
+
+set -A args "" "create -V" "create -V $TESTPOOL" \
+ "create -V $TESTPOOL/$TESTVOL@" "create -V blah" "destroy"
+
+log_assert "Try each ZFS volume sub-command without parameters to make sure" \
+ " it returns an error."
+
+typeset -i i=0
+while (( $i < ${#args[*]} )); do
+ log_mustnot zfs ${args[i]}
+ (( i = i + 1 ))
+done
+
+log_pass "Badly formed ZFS volume sub-commands fail as expected."
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_common.shlib b/tests/zfs-tests/tests/functional/zvol/zvol_common.shlib
new file mode 100644
index 000000000000..342700228764
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_common.shlib
@@ -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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol.cfg
+
+#
+# Create a simple zvol volume
+#
+# Where disk_device: is the name of the disk to be used
+# volume_size: is the size of the volume, e.g. 2G
+# block_size: is the block size of the volume
+#
+function default_zvol_setup # disk_device volume_size block_size
+{
+ typeset disk=$1
+ typeset size=$2
+ typeset blocksize=$3
+ typeset savedumpdev
+ typeset -i output
+ typeset create_args
+
+ create_pool $TESTPOOL "$disk"
+
+ if [ -n "$blocksize" ]; then
+ create_args="-b $blocksize"
+ fi
+
+ log_must zfs create $create_args -V $size $TESTPOOL/$TESTVOL
+ block_device_wait
+}
+
+#
+# Destroy the default zvol which was setup using
+# default_zvol_setup().
+#
+function default_zvol_cleanup
+{
+ if datasetexists $TESTPOOL/$TESTVOL ; then
+ log_must zfs destroy $TESTPOOL/$TESTVOL
+ fi
+
+ destroy_pool $TESTPOOL
+}
+
+function get_dumpdevice
+{
+ typeset ret=$(dumpadm | grep "Dump device:" | awk '{print $3}')
+ echo $ret
+}
+
+function set_dumpsize
+{
+ typeset volume=$1
+
+ if [[ -z $volume ]] ; then
+ log_note "No volume specified."
+ return 1
+ fi
+
+ log_must zfs set volsize=64m $volume
+
+ output=$(dumpadm -d /dev/zvol/dsk/$volume 2>&1 | \
+ tail -1 | awk '{print $3}')
+
+ if [[ -n $output ]]; then
+ (( output = output / 1024 / 1024 ))
+ (( output = output + output / 5 ))
+ log_must zfs set volsize=${output}m $volume
+ fi
+
+ return 0
+}
+
+function safe_dumpadm
+{
+ typeset device=$1
+
+ if [[ -z $device || $device == "none" ]] ; then
+ log_note "No dump device volume specified."
+ return 1
+ fi
+ if [[ $device == "${ZVOL_DEVDIR}/"* ]] ; then
+ typeset volume=${device#${ZVOL_DEVDIR}/}
+ set_dumpsize $volume
+ log_must dumpadm -d $device
+ else
+ log_must swapadd
+ if ! is_swap_inuse $device ; then
+ log_must swap -a $device
+ fi
+ log_must dumpadm -d swap
+ fi
+}
+
+function is_zvol_dumpified
+{
+ typeset volume=$1
+
+ if [[ -z $volume ]] ; then
+ log_note "No volume specified."
+ return 1
+ fi
+
+ zdb -dddd $volume 2 | grep "dumpsize" > /dev/null 2>&1
+ return $?
+}
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/Makefile.am b/tests/zfs-tests/tests/functional/zvol/zvol_misc/Makefile.am
new file mode 100644
index 000000000000..024007a41826
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/Makefile.am
@@ -0,0 +1,19 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/zvol/zvol_misc
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zvol_misc_001_neg.ksh \
+ zvol_misc_002_pos.ksh \
+ zvol_misc_003_neg.ksh \
+ zvol_misc_004_pos.ksh \
+ zvol_misc_005_neg.ksh \
+ zvol_misc_006_pos.ksh \
+ zvol_misc_hierarchy.ksh \
+ zvol_misc_rename_inuse.ksh \
+ zvol_misc_snapdev.ksh \
+ zvol_misc_volmode.ksh \
+ zvol_misc_zil.ksh
+
+dist_pkgdata_DATA = \
+ zvol_misc_common.kshlib
+
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh
new file mode 100755
index 000000000000..7714530ff4cb
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/cleanup.ksh
@@ -0,0 +1,41 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+verify_runnable "global"
+
+default_zvol_cleanup
+
+[[ -d $TESTDIR ]] && rm -rf $TESTDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh
new file mode 100755
index 000000000000..6b2cc821792c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/setup.ksh
@@ -0,0 +1,41 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+verify_runnable "global"
+
+default_zvol_setup $DISK $VOLSIZE
+
+log_must mkdir $TESTDIR
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh
new file mode 100755
index 000000000000..25325ddda694
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_001_neg.ksh
@@ -0,0 +1,72 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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.
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Verify that using a zvol as a dump device works.
+#
+# STRATEGY:
+# 1. Create a ZFS volume
+# 2. Use dumpadm add the volume as dump device
+# 3. Verify the return code as expected.
+#
+
+verify_runnable "global"
+
+if ! is_physical_device $DISKS; then
+ log_unsupported "This directory cannot be run on raw files."
+fi
+
+volsize=$(zfs get -H -o value volsize $TESTPOOL/$TESTVOL)
+
+function cleanup
+{
+ typeset dumpdev=$(get_dumpdevice)
+
+ if [[ $dumpdev != $savedumpdev ]] ; then
+ safe_dumpadm $savedumpdev
+ fi
+ zfs set volsize=$volsize $TESTPOOL/$TESTVOL
+}
+
+log_assert "Verify that a ZFS volume can act as dump device."
+log_onexit cleanup
+
+voldev=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+savedumpdev=$(get_dumpdevice)
+
+safe_dumpadm $voldev
+
+log_pass "Verify that a ZFS volume can act as dump device."
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_002_pos.ksh
new file mode 100755
index 000000000000..72446ee986fe
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# Verify that ZFS volume snapshot could be fscked
+#
+# STRATEGY:
+# 1. Create a ZFS volume
+# 2. Copy some files and create snapshot
+# 3. Verify fsck on the snapshot is OK
+#
+
+verify_runnable "global"
+
+volsize=$(zfs get -H -o value volsize $TESTPOOL/$TESTVOL)
+
+function cleanup
+{
+ snapexists $TESTPOOL/$TESTVOL@snap && \
+ zfs destroy $TESTPOOL/$TESTVOL@snap
+
+ ismounted $TESTDIR $NEWFS_DEFAULT_FS
+ (( $? == 0 )) && log_must umount $TESTDIR
+
+ zfs set volsize=$volsize $TESTPOOL/$TESTVOL
+}
+
+log_assert "Verify that ZFS volume snapshot could be fscked"
+log_onexit cleanup
+
+TESTVOL='testvol'
+BLOCKSZ=$(( 1024 * 1024 ))
+NUM_WRITES=40
+
+log_must zfs set volsize=128m $TESTPOOL/$TESTVOL
+
+log_must new_fs ${ZVOL_RDEVDIR}/$TESTPOOL/$TESTVOL
+
+log_must mount ${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL $TESTDIR
+
+typeset -i fn=0
+typeset -i retval=0
+
+while (( 1 )); do
+ file_write -o create -f $TESTDIR/testfile$$.$fn \
+ -b $BLOCKSZ -c $NUM_WRITES
+ retval=$?
+ if (( $retval != 0 )); then
+ break
+ fi
+ (( fn = fn + 1 ))
+done
+
+if is_linux || is_freebsd ; then
+ log_must sync
+else
+ log_must lockfs -f $TESTDIR
+fi
+
+log_must zfs set snapdev=visible $TESTPOOL/$TESTVOL
+log_must zfs snapshot $TESTPOOL/$TESTVOL@snap
+block_device_wait
+
+fsck -n ${ZVOL_RDEVDIR}/$TESTPOOL/$TESTVOL@snap >/dev/null 2>&1
+retval=$?
+
+if [ $retval -ne 0 ] ; then
+ if is_linux ; then
+ # Linux's fsck returns a different code for this test depending
+ # on the version:
+ #
+ # e2fsprogs-1.43.3 (Fedora 25 and older): returns 4
+ # e2fsprogs-1.43.4 (Fedora 26): returns 8
+ #
+ if [ $retval -ne 4 -a $retval -ne 8 ] ; then
+ log_fail "fsck exited with wrong value $retval"
+ fi
+ else
+ if [ $retval -ne 39 ] ; then
+ log_fail "fsck exited with wrong value $retval"
+ fi
+ fi
+fi
+
+log_pass "Verify that ZFS volume snapshot could be fscked"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_neg.ksh
new file mode 100755
index 000000000000..2b8e5099312b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_003_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Verify creating a storage pool or running newfs on a zvol used as a
+# dump device is denied.
+#
+# STRATEGY:
+# 1. Create a ZFS volume
+# 2. Use dumpadm to set the volume as dump device
+# 3. Verify creating a pool & running newfs on the zvol returns an error.
+#
+
+verify_runnable "global"
+
+if ! is_physical_device $DISKS; then
+ log_unsupported "This directory cannot be run on raw files."
+fi
+
+volsize=$(zfs get -H -o value volsize $TESTPOOL/$TESTVOL)
+
+function cleanup
+{
+ typeset dumpdev=$(get_dumpdevice)
+ if [[ $dumpdev != $savedumpdev ]] ; then
+ safe_dumpadm $savedumpdev
+ fi
+
+ if poolexists $TESTPOOL1 ; then
+ destroy_pool $TESTPOOL1
+ fi
+ zfs set volsize=$volsize $TESTPOOL/$TESTVOL
+}
+
+log_assert "Verify zpool creation and newfs on dump zvol is denied."
+log_onexit cleanup
+
+voldev=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+savedumpdev=$(get_dumpdevice)
+
+safe_dumpadm $voldev
+
+unset NOINUSE_CHECK
+log_mustnot eval "new_fs $voldev > /dev/null 2>&1"
+
+log_mustnot zpool create $TESTPOOL1 $voldev
+
+log_pass "Verify zpool creation and newfs on dump zvol is denied."
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_pos.ksh
new file mode 100755
index 000000000000..697887368377
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_004_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 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Verify the ability to take snapshots of zvols used as dump or swap.
+#
+# STRATEGY:
+# 1. Create a ZFS volume
+# 2. Set the volume as dump or swap
+# 3. Verify creating a snapshot of the zvol succeeds.
+#
+
+verify_runnable "global"
+
+if ! is_physical_device $DISKS; then
+ log_unsupported "This directory cannot be run on raw files."
+fi
+
+volsize=$(zfs get -H -o value volsize $TESTPOOL/$TESTVOL)
+
+function cleanup
+{
+ typeset dumpdev=$(get_dumpdevice)
+ if [[ $dumpdev != $savedumpdev ]] ; then
+ safe_dumpadm $savedumpdev
+ fi
+
+ swap -l | grep -w $voldev > /dev/null 2>&1
+ if (( $? == 0 )); then
+ log_must swap -d $voldev
+ fi
+
+ typeset snap
+ for snap in snap0 snap1 ; do
+ if datasetexists $TESTPOOL/$TESTVOL@$snap ; then
+ log_must zfs destroy $TESTPOOL/$TESTVOL@$snap
+ fi
+ done
+ zfs set volsize=$volsize $TESTPOOL/$TESTVOL
+}
+
+function verify_snapshot
+{
+ typeset volume=$1
+
+ log_must zfs snapshot $volume@snap0
+ log_must zfs snapshot $volume@snap1
+ log_must datasetexists $volume@snap0 $volume@snap1
+
+ log_must zfs destroy $volume@snap1
+ log_must zfs snapshot $volume@snap1
+
+ log_mustnot zfs rollback -r $volume@snap0
+ log_must datasetexists $volume@snap0
+
+ log_must zfs destroy -r $volume@snap0
+}
+
+log_assert "Verify the ability to take snapshots of zvols used as dump or swap."
+log_onexit cleanup
+
+voldev=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+savedumpdev=$(get_dumpdevice)
+
+# create snapshot over dump zvol
+safe_dumpadm $voldev
+log_must is_zvol_dumpified $TESTPOOL/$TESTVOL
+
+verify_snapshot $TESTPOOL/$TESTVOL
+
+safe_dumpadm $savedumpdev
+log_mustnot is_zvol_dumpified $TESTPOOL/$TESTVOL
+
+# create snapshot over swap zvol
+
+log_must swap -a $voldev
+log_mustnot is_zvol_dumpified $TESTPOOL/$TESTVOL
+
+verify_snapshot $TESTPOOL/$TESTVOL
+
+log_must swap -d $voldev
+log_mustnot is_zvol_dumpified $TESTPOOL/$TESTVOL
+
+log_pass "Creating snapshots from dump/swap zvols succeeds."
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_neg.ksh
new file mode 100755
index 000000000000..48dfe6d9386c
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_005_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) 2013, 2016 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Verify a device cannot be dump and swap at the same time.
+#
+# STRATEGY:
+# 1. Create a ZFS volume
+# 2. Set it as swap device.
+# 3. Verify dumpadm with this zvol will fail.
+#
+
+verify_runnable "global"
+
+if ! is_physical_device $DISKS; then
+ log_unsupported "This directory cannot be run on raw files."
+fi
+
+volsize=$(zfs get -H -o value volsize $TESTPOOL/$TESTVOL)
+
+function cleanup
+{
+ swap -l | grep $voldev > /dev/null 2>&1
+ if (( $? == 0 )) ; then
+ log_must swap -d $voldev
+ fi
+
+ typeset dumpdev=$(get_dumpdevice)
+ if [[ $dumpdev != $savedumpdev ]] ; then
+ safe_dumpadm $savedumpdev
+ fi
+ zfs set volsize=$volsize $TESTPOOL/$TESTVOL
+}
+
+log_assert "Verify a device cannot be dump and swap at the same time."
+log_onexit cleanup
+
+voldev=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+savedumpdev=$(get_dumpdevice)
+
+# If device in swap list, it cannot be dump device
+log_must swap -a $voldev
+log_mustnot dumpadm -d $voldev
+log_must swap -d $voldev
+
+# If device has dedicated as dump device, it cannot add into swap list
+safe_dumpadm $voldev
+log_mustnot swap -a $voldev
+
+log_pass "A device cannot be dump and swap at the same time."
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_pos.ksh
new file mode 100755
index 000000000000..08726a7c37e6
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_006_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) 2013, 2016 by Delphix. All rights reserved.
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# ZFS volume as dump device, it should always have 128k volblocksize
+#
+# STRATEGY:
+# 1. Create a ZFS volume
+# 2. Use dumpadm set the volume as dump device
+# 3. Verify the volume's volblocksize=128k
+#
+
+verify_runnable "global"
+
+if ! is_physical_device $DISKS; then
+ log_unsupported "This directory cannot be run on raw files."
+fi
+
+volsize=$(zfs get -H -o value volsize $TESTPOOL/$TESTVOL)
+
+function cleanup
+{
+ typeset dumpdev=$(get_dumpdevice)
+ if [[ $dumpdev != $savedumpdev ]] ; then
+ safe_dumpadm $savedumpdev
+ fi
+ zfs set volsize=$volsize $TESTPOOL/$TESTVOL
+}
+
+log_assert "zfs volume as dumpdevice should have 128k volblocksize"
+log_onexit cleanup
+
+voldev=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+savedumpdev=$(get_dumpdevice)
+
+typeset oblksize=$(zfs get -H -o value volblocksize $TESTPOOL/$TESTVOL)
+log_note "original $TESTPOOL/$TESTVOL volblocksize=$oblksize"
+
+safe_dumpadm $voldev
+
+typeset blksize=$(zfs get -H -o value volblocksize $TESTPOOL/$TESTVOL)
+
+if [[ $blksize != "128K" ]]; then
+ log_fail "ZFS volume $TESTPOOL/$TESTVOL volblocksize=$blksize"
+fi
+
+log_pass "zfs volume as dumpdevice should have 128k volblocksize"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
new file mode 100644
index 000000000000..3ee09a151b12
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
@@ -0,0 +1,143 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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_set/zfs_set_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# Wait for udev to settle, completely.
+# This is quite discomforting, but there's a race condition here
+# (Amazon 2015.09 x86_64 Release (TEST) is good at triggering this) where the
+# kernel tries to remove zvol device nodes while they're open by [blkid],
+# [zvol_id] or other udev related processes.
+# Calling 'udevadm settle' is not enough: wait for those processes "manually".
+#
+function udev_wait
+{
+ sleep 1
+ is_linux || return 0
+ udevadm trigger --action=change
+ udevadm settle
+ for i in {1..3}; do
+ blkid="$(pgrep blkid | wc -l)"
+ zvol_id="$(pgrep zvol_id | wc -l)"
+ [[ "0" == "$zvol_id" && "0" == "$blkid" ]] && return
+ udevadm settle
+ done
+ log_fail "Wait timeout reached for udev_wait"
+}
+
+#
+# Clean up udev status
+# This is also a problem on "Amazon 2015.09 x86_64 Release (TEST)" where udev,
+# sometimes, does not clean up /dev/zvol symlinks correctly for removed ZVOLs.
+# Prune those links manually, then tell udev to forget them.
+#
+function udev_cleanup
+{
+ is_linux || return 0
+ log_note "Pruning broken ZVOL symlinks ..."
+
+ udevadm settle
+ # find all dangling links and delete them
+ find -L "${ZVOL_DEVDIR}" -type l -print -delete
+ # purge those links from udev database
+ udevadm info --cleanup-db
+}
+
+#
+# Verify $device exists and is a block device
+#
+function blockdev_exists # device
+{
+ typeset device="$1"
+
+ # we wait here instead of doing it in a wrapper around 'zfs set snapdev'
+ # because there are other commands (zfs snap, zfs inherit, zfs destroy)
+ # that can affect device nodes
+ for i in {1..3}; do
+ udev_wait
+ is_disk_device "$device" && return 0
+ done
+ log_fail "$device does not exist as a block device"
+}
+
+#
+# Verify $device does not exist
+#
+function blockdev_missing # device
+{
+ typeset device="$1"
+
+ # we wait here instead of doing it in a wrapper around 'zfs set snapdev'
+ # because there are other commands (zfs snap, zfs inherit, zfs destroy)
+ # that can affect device nodes
+ for i in {1..3}; do
+ udev_wait
+ [[ ! -e "$device" ]] && return 0
+ done
+ log_fail "$device exists when not expected"
+}
+
+#
+# Verify $property on $dataset is inherited by $parent and is set to $value
+#
+function verify_inherited # property value dataset parent
+{
+ typeset property="$1"
+ typeset value="$2"
+ typeset dataset="$3"
+ typeset parent="$4"
+
+ typeset val=$(get_prop "$property" "$dataset")
+ typeset src=$(get_source "$property" "$dataset")
+ if [[ "$val" != "$value" || "$src" != "inherited from $parent" ]]; then
+ log_fail "Dataset $dataset did not inherit $property properly:"\
+ "expected=$value, value=$val, source=$src."
+ fi
+}
+
+#
+# Create a small partition on $device, then verify if we can access it
+#
+function verify_partition # device
+{
+ typeset device="$1"
+
+ if ! is_disk_device "$device"; then
+ log_fail "$device is not a block device"
+ fi
+ # create a small dummy partition
+ set_partition 0 "" 1m $device
+ # verify we can access the partition on the device
+ devname="$(readlink -f "$device")"
+ if is_linux || is_freebsd; then
+ is_disk_device "$devname""p1"
+ else
+ is_disk_device "$devname""s0"
+ fi
+ return $?
+}
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_hierarchy.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_hierarchy.ksh
new file mode 100755
index 000000000000..1431f0b1f1f0
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_hierarchy.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 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+# ZVOLs cannot have children datasets: verify zfs commands respect this
+# hierarchy rule.
+#
+# STRATEGY:
+# 1. Create a filesystem and a ZVOL
+# 2. Verify 'zfs recv' will not (force-)receive a ZVOL over the root dataset
+# 3. Verify 'zfs recv' cannot receive a ZVOL overwriting datasets with children
+# 4. Verify 'zfs recv' cannot receive datasets below a ZVOL
+# 5. Verify 'zfs create' cannot create datasets under a ZVOL
+# 6. Verify 'zfs rename' cannot move datasets under a ZVOL
+#
+
+verify_runnable "both"
+
+function cleanup
+{
+ destroy_pool "$poolname"
+ log_must rm -f "$vdevfile" "$streamfile_fs" "$streamfile_zvol"
+}
+
+log_assert "ZVOLs cannot have children datasets: verify zfs commands respect "\
+ "this hierarchy rule"
+log_onexit cleanup
+
+poolname="$TESTPOOL-zvol_hierarchy"
+vdevfile="$TEST_BASE_DIR/vdevfile.$$"
+streamfile_fs="$TEST_BASE_DIR/streamfile_fs.$$"
+streamfile_zvol="$TEST_BASE_DIR/streamfile_zvol.$$"
+
+# 1. Create filesystems and ZVOLs
+# 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 "$poolname/sendfs"
+log_must zfs create -V 1M -s "$poolname/sendvol"
+log_must zfs snapshot "$poolname/sendfs@snap"
+log_must zfs snapshot "$poolname/sendvol@snap"
+log_must eval "zfs send $poolname/sendfs@snap > $streamfile_fs"
+log_must eval "zfs send $poolname/sendvol@snap > $streamfile_zvol"
+
+# 2. Verify 'zfs recv' will not (force-)receive a ZVOL over the root dataset
+log_mustnot eval "zfs receive -F $poolname < $streamfile_zvol"
+
+# 3. Verify 'zfs recv' cannot receive a ZVOL overwriting datasets with children
+log_must zfs create "$poolname/fs"
+log_must zfs create "$poolname/fs/subfs"
+log_mustnot eval "zfs receive -F $poolname/fs < $streamfile_zvol"
+log_must zfs destroy "$poolname/fs/subfs"
+log_must eval "zfs receive -F $poolname/fs < $streamfile_zvol"
+
+# 4. Verify 'zfs recv' cannot receive datasets below a ZVOL
+log_must zfs create -V 1M -s "$poolname/volume"
+log_mustnot eval "zfs receive $poolname/volume/subfs < $streamfile_fs"
+log_mustnot eval "zfs receive $poolname/volume/subvol < $streamfile_zvol"
+
+# 5. Verify 'zfs create' cannot create datasets under a ZVOL
+log_must zfs create -V 1M -s "$poolname/createvol"
+log_mustnot zfs create "$poolname/createvol/fs"
+log_mustnot zfs create -V 1M -s "$poolname/createvol/vol"
+
+# 6. Verify 'zfs rename' cannot move datasets under a ZVOL
+log_must zfs create "$poolname/movefs"
+log_must zfs create -V 1M -s "$poolname/movevol"
+log_must zfs create -V 1M -s "$poolname/renamevol"
+log_mustnot zfs rename "$poolname/fs" "$poolname/renamevol/fs"
+log_mustnot zfs rename "$poolname/vol" "$poolname/renamevol/vol"
+
+log_pass "ZVOLs cannot have children datasets and zfs commands enforce this "\
+ "rule"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_rename_inuse.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_rename_inuse.ksh
new file mode 100755
index 000000000000..c4ea23c48d16
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_rename_inuse.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 2019, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zfs rename' works on a ZVOL already in use as block device
+#
+# STRATEGY:
+# 1. Create a ZVOL
+# 2. Create a filesystem on the ZVOL device and mount it
+# 3. Rename the ZVOL dataset
+# 4. Receive a send stream with the same name as the old ZVOL dataset and verify
+# we don't trigger any issue like the one reported in #6263
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must umount "$MNTPFS"
+ log_must rmdir "$MNTPFS"
+ for ds in "$SENDFS" "$ZVOL" "$ZVOL-renamed"; do
+ destroy_dataset "$ds" '-rf'
+ done
+ udev_wait
+}
+
+log_assert "Verify 'zfs rename' works on a ZVOL already in use as block device"
+log_onexit cleanup
+
+ZVOL="$TESTPOOL/vol.$$"
+ZDEV="$ZVOL_DEVDIR/$ZVOL"
+MNTPFS="$TESTDIR/zvol_inuse_rename"
+SENDFS="$TESTPOOL/sendfs.$$"
+
+# 1. Create a ZVOL
+log_must zfs create -V $VOLSIZE "$ZVOL"
+
+# 2. Create a filesystem on the ZVOL device and mount it
+udev_wait
+log_must eval "new_fs $ZDEV >/dev/null 2>&1"
+log_must mkdir "$MNTPFS"
+log_must mount "$ZDEV" "$MNTPFS"
+
+# 3. Rename the ZVOL dataset
+log_must zfs rename "$ZVOL" "$ZVOL-renamed"
+
+# 4. Receive a send stream with the same name as the old ZVOL dataset and verify
+# we don't trigger any issue like the one reported in #6263
+log_must zfs create "$SENDFS"
+log_must zfs snap "$SENDFS@snap"
+log_must eval "zfs send $SENDFS@snap | zfs recv $ZVOL"
+
+log_pass "Renaming in use ZVOL works successfully"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh
new file mode 100755
index 000000000000..8d95bfa39374
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_snapdev.ksh
@@ -0,0 +1,121 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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_set/zfs_set_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify that ZFS volume property "snapdev" works as intended.
+#
+# STRATEGY:
+# 1. Verify "snapdev" property does not accept invalid values
+# 2. Verify "snapdev" adds and removes device nodes when updated
+# 3. Verify "snapdev" is inherited correctly
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $VOLFS && log_must zfs destroy -r $VOLFS
+ datasetexists $ZVOL && log_must zfs destroy -r $ZVOL
+ log_must zfs inherit snapdev $TESTPOOL
+ block_device_wait
+ udev_cleanup
+}
+
+log_assert "Verify that ZFS volume property 'snapdev' works as expected."
+log_onexit cleanup
+
+VOLFS="$TESTPOOL/volfs"
+ZVOL="$TESTPOOL/vol"
+SNAP="$ZVOL@snap"
+SNAPDEV="${ZVOL_DEVDIR}/$SNAP"
+SUBZVOL="$VOLFS/subvol"
+SUBSNAP="$SUBZVOL@snap"
+SUBSNAPDEV="${ZVOL_DEVDIR}/$SUBSNAP"
+
+log_must zfs create -o mountpoint=none $VOLFS
+log_must zfs create -V $VOLSIZE -s $ZVOL
+log_must zfs create -V $VOLSIZE -s $SUBZVOL
+
+# 1. Verify "snapdev" property does not accept invalid values
+typeset badvals=("off" "on" "1" "nope" "-")
+for badval in ${badvals[@]}
+do
+ log_mustnot zfs set snapdev="$badval" $ZVOL
+done
+
+# 2. Verify "snapdev" adds and removes device nodes when updated
+# 2.1 First create a snapshot then change snapdev property
+log_must zfs snapshot $SNAP
+log_must zfs set snapdev=visible $ZVOL
+blockdev_exists $SNAPDEV
+log_must zfs set snapdev=hidden $ZVOL
+blockdev_missing $SNAPDEV
+log_must zfs destroy $SNAP
+# 2.2 First set snapdev property then create a snapshot
+log_must zfs set snapdev=visible $ZVOL
+log_must zfs snapshot $SNAP
+blockdev_exists $SNAPDEV
+log_must zfs destroy $SNAP
+blockdev_missing $SNAPDEV
+# 2.3 Verify setting to the same value multiple times does not lead to issues
+log_must zfs snapshot $SNAP
+log_must zfs set snapdev=visible $ZVOL
+blockdev_exists $SNAPDEV
+log_must zfs set snapdev=visible $ZVOL
+blockdev_exists $SNAPDEV
+log_must zfs set snapdev=hidden $ZVOL
+blockdev_missing $SNAPDEV
+log_must zfs set snapdev=hidden $ZVOL
+blockdev_missing $SNAPDEV
+log_must zfs destroy $SNAP
+
+# 3. Verify "snapdev" is inherited correctly
+# 3.1 Check snapdev=visible case
+log_must zfs snapshot $SNAP
+log_must zfs inherit snapdev $ZVOL
+log_must zfs set snapdev=visible $TESTPOOL
+verify_inherited 'snapdev' 'visible' $ZVOL $TESTPOOL
+blockdev_exists $SNAPDEV
+# 3.2 Check snapdev=hidden case
+log_must zfs set snapdev=hidden $TESTPOOL
+verify_inherited 'snapdev' 'hidden' $ZVOL $TESTPOOL
+blockdev_missing $SNAPDEV
+# 3.3 Check inheritance on multiple levels
+log_must zfs snapshot $SUBSNAP
+log_must zfs inherit snapdev $SUBZVOL
+log_must zfs set snapdev=hidden $VOLFS
+log_must zfs set snapdev=visible $TESTPOOL
+verify_inherited 'snapdev' 'hidden' $SUBZVOL $VOLFS
+blockdev_missing $SUBSNAPDEV
+blockdev_exists $SNAPDEV
+
+log_pass "ZFS volume property 'snapdev' works as expected"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh
new file mode 100755
index 000000000000..7451bf8b7a73
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_volmode.ksh
@@ -0,0 +1,242 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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_set/zfs_set_common.kshlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify that ZFS volume property "volmode" works as intended.
+#
+# STRATEGY:
+# 1. Verify "volmode" property does not accept invalid values
+# 2. Verify "volmode=none" hides ZVOL device nodes
+# 3. Verify "volmode=full" exposes a fully functional device
+# 4. Verify "volmode=dev" hides partition info on the device
+# 5. Verify "volmode=default" behaves accordingly to "volmode" module parameter
+# 6. Verify "volmode" property is inherited correctly
+# 7. Verify "volmode" behaves correctly at import time
+# 8. Verify "volmode" behaves accordingly to zvol_inhibit_dev (Linux only)
+#
+# NOTE: changing volmode may need to remove minors, which could be open, so call
+# udev_wait() before we "zfs set volmode=<value>".
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $VOLFS && log_must_busy zfs destroy -r $VOLFS
+ datasetexists $ZVOL && log_must_busy zfs destroy -r $ZVOL
+ log_must zfs inherit volmode $TESTPOOL
+ udev_wait
+ sysctl_inhibit_dev 0
+ sysctl_volmode 1
+ udev_cleanup
+}
+
+#
+# Set zvol_inhibit_dev tunable to $value
+#
+function sysctl_inhibit_dev # value
+{
+ typeset value="$1"
+
+ if is_linux; then
+ log_note "Setting zvol_inhibit_dev tunable to $value"
+ log_must set_tunable32 VOL_INHIBIT_DEV $value
+ fi
+}
+
+#
+# Set volmode tunable to $value
+#
+function sysctl_volmode # value
+{
+ typeset value="$1"
+
+ log_note "Setting volmode tunable to $value"
+ log_must set_tunable32 VOL_MODE $value
+}
+
+#
+# Exercise open and close, read and write operations
+#
+function test_io # dev
+{
+ typeset dev=$1
+
+ log_must dd if=/dev/zero of=$dev count=1
+ log_must dd if=$dev of=/dev/null count=1
+}
+
+log_assert "Verify that ZFS volume property 'volmode' works as intended"
+log_onexit cleanup
+
+VOLFS="$TESTPOOL/volfs"
+ZVOL="$TESTPOOL/vol"
+ZDEV="${ZVOL_DEVDIR}/$ZVOL"
+SUBZVOL="$VOLFS/subvol"
+SUBZDEV="${ZVOL_DEVDIR}/$SUBZVOL"
+
+log_must zfs create -o mountpoint=none $VOLFS
+log_must zfs create -V $VOLSIZE -s $SUBZVOL
+log_must zfs create -V $VOLSIZE -s $ZVOL
+udev_wait
+test_io $ZDEV
+test_io $SUBZDEV
+
+# 1. Verify "volmode" property does not accept invalid values
+typeset badvals=("off" "on" "1" "nope" "-")
+for badval in ${badvals[@]}
+do
+ log_mustnot zfs set volmode="$badval" $ZVOL
+done
+
+# 2. Verify "volmode=none" hides ZVOL device nodes
+log_must zfs set volmode=none $ZVOL
+blockdev_missing $ZDEV
+log_must_busy zfs destroy $ZVOL
+
+# 3. Verify "volmode=full" exposes a fully functional device
+log_must zfs create -V $VOLSIZE -s $ZVOL
+udev_wait
+log_must zfs set volmode=full $ZVOL
+blockdev_exists $ZDEV
+test_io $ZDEV
+log_must verify_partition $ZDEV
+udev_wait
+# 3.1 Verify "volmode=geom" is an alias for "volmode=full"
+log_must zfs set volmode=geom $ZVOL
+blockdev_exists $ZDEV
+if [[ "$(get_prop 'volmode' $ZVOL)" != "full" ]]; then
+ log_fail " Volmode value 'geom' is not an alias for 'full'"
+fi
+udev_wait
+log_must_busy zfs destroy $ZVOL
+
+# 4. Verify "volmode=dev" hides partition info on the device
+log_must zfs create -V $VOLSIZE -s $ZVOL
+udev_wait
+log_must zfs set volmode=dev $ZVOL
+blockdev_exists $ZDEV
+test_io $ZDEV
+log_mustnot verify_partition $ZDEV
+udev_wait
+log_must_busy zfs destroy $ZVOL
+
+# 5. Verify "volmode=default" behaves accordingly to "volmode" module parameter
+# 5.1 Verify sysctl "volmode=full"
+sysctl_volmode 1
+log_must zfs create -V $VOLSIZE -s $ZVOL
+udev_wait
+log_must zfs set volmode=default $ZVOL
+blockdev_exists $ZDEV
+log_must verify_partition $ZDEV
+udev_wait
+log_must_busy zfs destroy $ZVOL
+# 5.2 Verify sysctl "volmode=dev"
+sysctl_volmode 2
+log_must zfs create -V $VOLSIZE -s $ZVOL
+udev_wait
+log_must zfs set volmode=default $ZVOL
+blockdev_exists $ZDEV
+log_mustnot verify_partition $ZDEV
+udev_wait
+log_must_busy zfs destroy $ZVOL
+# 5.2 Verify sysctl "volmode=none"
+sysctl_volmode 3
+log_must zfs create -V $VOLSIZE -s $ZVOL
+udev_wait
+log_must zfs set volmode=default $ZVOL
+blockdev_missing $ZDEV
+
+# 6. Verify "volmode" property is inherited correctly
+log_must zfs inherit volmode $ZVOL
+# 6.1 Check volmode=full case
+log_must zfs set volmode=full $TESTPOOL
+verify_inherited 'volmode' 'full' $ZVOL $TESTPOOL
+blockdev_exists $ZDEV
+# 6.2 Check volmode=none case
+log_must zfs set volmode=none $TESTPOOL
+verify_inherited 'volmode' 'none' $ZVOL $TESTPOOL
+blockdev_missing $ZDEV
+# 6.3 Check volmode=dev case
+log_must zfs set volmode=dev $TESTPOOL
+verify_inherited 'volmode' 'dev' $ZVOL $TESTPOOL
+blockdev_exists $ZDEV
+# 6.4 Check volmode=default case
+sysctl_volmode 1
+log_must zfs set volmode=default $TESTPOOL
+verify_inherited 'volmode' 'default' $ZVOL $TESTPOOL
+blockdev_exists $ZDEV
+# 6.5 Check inheritance on multiple levels
+log_must zfs inherit volmode $SUBZVOL
+udev_wait
+log_must zfs set volmode=none $VOLFS
+udev_wait
+log_must zfs set volmode=full $TESTPOOL
+verify_inherited 'volmode' 'none' $SUBZVOL $VOLFS
+blockdev_missing $SUBZDEV
+blockdev_exists $ZDEV
+
+# 7. Verify "volmode" behaves correctly at import time
+log_must zpool export $TESTPOOL
+blockdev_missing $ZDEV
+blockdev_missing $SUBZDEV
+log_must zpool import $TESTPOOL
+blockdev_exists $ZDEV
+blockdev_missing $SUBZDEV
+log_must_busy zfs destroy $ZVOL
+log_must_busy zfs destroy $SUBZVOL
+
+# 8. Verify "volmode" behaves accordingly to zvol_inhibit_dev (Linux only)
+if is_linux; then
+ sysctl_inhibit_dev 1
+ # 7.1 Verify device nodes not are not created with "volmode=full"
+ sysctl_volmode 1
+ log_must zfs create -V $VOLSIZE -s $ZVOL
+ blockdev_missing $ZDEV
+ log_must zfs set volmode=full $ZVOL
+ blockdev_missing $ZDEV
+ log_must_busy zfs destroy $ZVOL
+ # 7.1 Verify device nodes not are not created with "volmode=dev"
+ sysctl_volmode 2
+ log_must zfs create -V $VOLSIZE -s $ZVOL
+ blockdev_missing $ZDEV
+ log_must zfs set volmode=dev $ZVOL
+ blockdev_missing $ZDEV
+ log_must_busy zfs destroy $ZVOL
+ # 7.1 Verify device nodes not are not created with "volmode=none"
+ sysctl_volmode 3
+ log_must zfs create -V $VOLSIZE -s $ZVOL
+ blockdev_missing $ZDEV
+ log_must zfs set volmode=none $ZVOL
+ blockdev_missing $ZDEV
+fi
+
+log_pass "Verify that ZFS volume property 'volmode' works as intended"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.ksh
new file mode 100755
index 000000000000..b8989f478727
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_zil.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 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib
+
+#
+# DESCRIPTION:
+# Verify ZIL functionality on ZVOLs
+#
+# STRATEGY:
+# 1. Create a ZVOLs with various combination of "logbias" and "sync" values
+# 2. Write data to ZVOL device node
+# 3. Verify we don't trigger any issue like the one reported in #6238
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ datasetexists $ZVOL && log_must_busy zfs destroy $ZVOL
+ udev_wait
+}
+
+log_assert "Verify ZIL functionality on ZVOLs"
+log_onexit cleanup
+
+ZVOL="$TESTPOOL/vol"
+ZDEV="$ZVOL_DEVDIR/$ZVOL"
+typeset -a logbias_prop_vals=('latency' 'throughput')
+typeset -a sync_prop_vals=('standard' 'always' 'disabled')
+
+for logbias in ${logbias_prop_vals[@]}; do
+ for sync in ${sync_prop_vals[@]}; do
+ # 1. Create a ZVOL with logbias=throughput and sync=always
+ log_must zfs create -V $VOLSIZE -b 128K -o sync=$sync \
+ -o logbias=$logbias $ZVOL
+
+ # 2. Write data to its device node
+ for i in {1..50}; do
+ dd if=/dev/zero of=$ZDEV bs=8k count=1 &
+ done
+
+ # 3. Verify we don't trigger any issue
+ log_must wait
+ log_must_busy zfs destroy $ZVOL
+ done
+done
+
+log_pass "ZIL functionality works on ZVOLs"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/Makefile.am b/tests/zfs-tests/tests/functional/zvol/zvol_swap/Makefile.am
new file mode 100644
index 000000000000..480c0048cfd8
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/Makefile.am
@@ -0,0 +1,13 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/zvol/zvol_swap
+dist_pkgdata_SCRIPTS = \
+ cleanup.ksh \
+ setup.ksh \
+ zvol_swap_001_pos.ksh \
+ zvol_swap_002_pos.ksh \
+ zvol_swap_003_pos.ksh \
+ zvol_swap_004_pos.ksh \
+ zvol_swap_005_pos.ksh \
+ zvol_swap_006_pos.ksh
+
+dist_pkgdata_DATA = \
+ zvol_swap.cfg
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.ksh
new file mode 100755
index 000000000000..70574fcfe705
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/cleanup.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 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/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_swap/zvol_swap.cfg
+
+verify_runnable "global"
+
+if is_linux; then
+ log_must swapon -a
+elif is_freebsd; then
+ swapon -a || true
+else
+ log_must swapadd
+fi
+
+for swapdev in $SAVESWAPDEVS
+do
+ if ! is_swap_inuse $swapdev ; then
+ log_must swap_setup $swapdev >/dev/null 2>&1
+ fi
+done
+
+voldev=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+if is_swap_inuse $voldev ; then
+ log_must swap_cleanup $voldev
+fi
+
+default_zvol_cleanup
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/setup.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/setup.ksh
new file mode 100755
index 000000000000..2ec8c72c67de
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_swap/zvol_swap.cfg
+
+verify_runnable "global"
+
+for i in $SAVESWAPDEVS ; do
+ log_note "Executing: swap_cleanup $i"
+ swap_cleanup $i >/dev/null 2>&1
+ if [[ $? != 0 ]]; then
+ log_untested "Unable to delete swap device $i because of" \
+ "insufficient RAM"
+ fi
+done
+
+default_zvol_setup $DISK $VOLSIZE
+
+log_pass
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg
new file mode 100644
index 000000000000..2ea8a4c72703
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap.cfg
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL 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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/tests/functional/zvol/zvol.cfg
+
+#
+# Remember swap devices
+#
+if is_linux; then
+ SAVESWAPDEVS=$(swapon -s | nawk '(NR != 1) {print $1}')
+else
+ SAVESWAPDEVS=$(swap -l | nawk '(NR != 1) {print $1}')
+fi
+
+export BLOCKSZ=$(( 1024 * 1024 ))
+export NUM_WRITES=40
+export SAVESWAPDEVS
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_001_pos.ksh
new file mode 100755
index 000000000000..854859aa6f1b
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_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 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/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_swap/zvol_swap.cfg
+
+#
+# DESCRIPTION:
+# Verify that a zvol can be used as a swap device
+#
+# STRATEGY:
+# 1. Create a pool
+# 2. Create a zvol volume
+# 3. Use zvol as swap space
+# 4. Create a file under /var/tmp
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ rm -rf $TEMPFILE
+
+ if is_swap_inuse $voldev ; then
+ log_must swap_cleanup $voldev
+ fi
+}
+
+log_assert "Verify that a zvol can be used as a swap device"
+
+log_onexit cleanup
+
+voldev=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+log_note "Add zvol volume as swap space"
+log_must swap_setup $voldev
+
+log_note "Create a file under /var/tmp"
+log_must file_write -o create -f $TEMPFILE \
+ -b $BLOCKSZ -c $NUM_WRITES -d $DATA
+
+[[ ! -f $TEMPFILE ]] && log_fail "Unable to create file under /var/tmp"
+
+filesize=`ls -l $TEMPFILE | awk '{print $5}'`
+tf_size=$(( BLOCKSZ * NUM_WRITES ))
+(( $tf_size != $filesize )) &&
+ log_fail "testfile is ($filesize bytes), expected ($tf_size bytes)"
+
+log_pass "Successfully added a zvol to swap area."
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_pos.ksh
new file mode 100755
index 000000000000..6106f7ee7d33
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_002_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) 2013, 2016 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# Add a swap zvol, and consume most (not all) of the space. This test
+# used to fill up swap, which can hang the system.
+#
+# STRATEGY:
+# 1. Create a new zvol and add it as swap
+# 2. Fill //var/tmp with 80% the size of the zvol
+# 5. Remove the new zvol, and restore original swap devices
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ rm -rf $TEMPFILE
+
+ if is_swap_inuse $swapdev ; then
+ log_must swap_cleanup $swapdev
+ fi
+}
+
+log_assert "Using a zvol as swap space, fill /var/tmp to 80%."
+
+log_onexit cleanup
+
+vol=$TESTPOOL/$TESTVOL
+swapdev=${ZVOL_DEVDIR}/$vol
+log_must swap_setup $swapdev
+
+# Get 80% of the number of 512 blocks in the zvol
+typeset -i count blks volsize=$(get_prop volsize $vol)
+((blks = (volsize / 512) * 80 / 100))
+# Use 'blks' to determine a count for dd based on a 1M block size.
+((count = blks / 2048))
+
+log_note "Fill 80% of swap"
+log_must dd if=/dev/urandom of=$TEMPFILE bs=1048576 count=$count
+log_must rm -f $TEMPFILE
+log_must swap_cleanup $swapdev
+
+log_pass "Using a zvol as swap space, fill /var/tmp to 80%."
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_pos.ksh
new file mode 100755
index 000000000000..aafdb7a49fac
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_003_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 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/zvol/zvol_common.shlib
+. $STF_SUITE/tests/functional/zvol/zvol_swap/zvol_swap.cfg
+
+#
+# DESCRIPTION:
+# Verify that a zvol device can be used as a swap device
+# through /etc/vfstab configuration.
+#
+# STRATEGY:
+# 1. Modify /etc/vfstab to add the test zvol as swap device.
+# 2. Use /sbin/swapadd to add zvol as swap device through /etc/vfstab
+# 3. Create a file under /tmp and verify the file
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ [[ -f $TESTDIR/$TESTFILE ]] && log_must rm -f $TESTDIR/$TESTFILE
+ [[ -f $NEW_VFSTAB_FILE ]] && log_must rm -f $NEW_VFSTAB_FILE
+ [[ -f $PREV_VFSTAB_FILE ]] && \
+ log_must mv $PREV_VFSTAB_FILE $VFSTAB_FILE
+ [[ -f $PREV_VFSTAB_FILE ]] && rm -f $PREV_VFSTAB_FILE
+
+ log_must swapadd $VFSTAB_FILE
+
+ if is_swap_inuse $voldev ; then
+ log_must swap -d $voldev
+ fi
+
+}
+
+log_assert "Verify that a zvol device can be used as a swap device" \
+ "through /etc/vfstab configuration."
+
+log_onexit cleanup
+
+voldev=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL
+VFSTAB_FILE=/etc/vfstab
+NEW_VFSTAB_FILE=$TEST_BASE_DIR/zvol_vfstab.$$
+PREV_VFSTAB_FILE=$TEST_BASE_DIR/zvol_vfstab.PREV.$$
+
+[[ -f $NEW_VFSTAB_FILE ]] && cp /dev/null $NEW_VFSTAB_FILE
+
+awk '{if ($4 != "swap") print $1}' /etc/vfstab > $NEW_VFSTAB_FILE
+echo "$voldev\t-\t-\tswap\t-\tno\t-" >> $NEW_VFSTAB_FILE
+
+# Copy off the original vfstab, and run swapadd on the newly constructed one.
+log_must cp $VFSTAB_FILE $PREV_VFSTAB_FILE
+log_must cp $NEW_VFSTAB_FILE $VFSTAB_FILE
+log_must swapadd $VFSTAB_FILE
+
+log_must file_write -o create -f $TESTDIR/$TESTFILE \
+ -b $BLOCKSZ -c $NUM_WRITES -d $DATA
+
+[[ ! -f $TESTDIR/$TESTFILE ]] &&
+ log_fail "Unable to create file under $TESTDIR"
+
+filesize=`ls -l $TESTDIR/$TESTFILE | awk '{print $5}'`
+tf_size=$((BLOCKSZ * NUM_WRITES))
+(($tf_size != $filesize)) && \
+ log_fail "testfile is ($filesize bytes), expected ($tf_size bytes)"
+
+log_pass "Successfully added a zvol to swap area through /etc/vfstab."
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_pos.ksh
new file mode 100755
index 000000000000..be72576707d2
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_004_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 2007 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/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# When a swap zvol is added its volsize does not change.
+#
+# STRATEGY:
+# 1. Determine what 1/4 arc_c_max is.
+# 2. Create a zvols in a variety of sizes.
+# 3. Add them as swap, and verify the volsize is not changed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ is_swap_inuse $swapname && log_must swap_cleanup $swapname
+ datasetexists $vol && log_must zfs destroy $vol
+}
+
+log_assert "For an added swap zvol, (2G <= volsize <= 16G)"
+
+log_onexit cleanup
+
+for vbs in 8192 16384 32768 65536 131072; do
+ for multiplier in 32 16384 131072; do
+ ((volsize = vbs * multiplier))
+ vol="$TESTPOOL/vol_$volsize"
+ swapname="${ZVOL_DEVDIR}/$vol"
+
+ # Create a sparse volume to test larger sizes
+ log_must zfs create -s -b $vbs -V $volsize $vol
+ block_device_wait
+ log_must swap_setup $swapname
+
+ new_volsize=$(get_prop volsize $vol)
+ [[ $volsize -eq $new_volsize ]] || log_fail "$volsize $new_volsize"
+
+ log_must swap_cleanup $swapname
+ log_must_busy zfs destroy $vol
+ done
+done
+
+log_pass "For an added swap zvol, (2G <= volsize <= 16G)"
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_pos.ksh
new file mode 100755
index 000000000000..b22bfdb16507
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_005_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 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/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# swaplow + swaplen must be less than or equal to the volume size.
+#
+# STRATEGY:
+# 1. Get test system page size and test volume size.
+# 2. Random get swaplow and swaplen.
+# 3. Verify swap -a should succeed when swaplow + swaplen <= volume size.
+#
+
+verify_runnable "global"
+
+assertion="Verify the sum of swaplow and swaplen is less or equal to volsize"
+log_assert $assertion
+
+typeset vol=$TESTPOOL/$TESTVOL
+typeset swapname="${ZVOL_DEVDIR}/$vol"
+typeset -i pageblocks volblocks max_swaplow
+#
+# Both swaplow and swaplen are the desired length of
+# the swap area in 512-byte blocks.
+#
+((pageblocks = $(getconf PAGESIZE) / 512))
+((volblocks = $(get_prop volsize $vol) / 512))
+((max_swaplow = (volblocks - (pageblocks * 2))))
+
+for i in {0..10}; do
+ swaplow=$(range_shuffle ${pageblocks} ${max_swaplow} | head -n 1)
+ ((maxlen = max_swaplow - swaplow))
+ swaplen=$(range_shuffle ${pageblocks} ${maxlen} | head -n 1)
+ log_must swap -a $swapname $swaplow $swaplen
+ log_must swap -d $swapname $swaplow
+done
+
+log_pass $assertion
diff --git a/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos.ksh b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_006_pos.ksh
new file mode 100755
index 000000000000..5788a8643487
--- /dev/null
+++ b/tests/zfs-tests/tests/functional/zvol/zvol_swap/zvol_swap_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 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/zvol/zvol_common.shlib
+
+#
+# DESCRIPTION:
+# A volume can be added as several segments, but overlapping segments
+# are not allowed.
+#
+# STRATEGY:
+# 1. Figure out three groups swaplow and swaplen.
+# 2. Verify different volume segments can be added correctly.
+# 3. Verify overlapping swap volume are not allowed.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ typeset -i i=0
+
+ while ((count > 0)); do
+ log_must swap -d $swapname ${swap_opt[$i]}
+
+ ((i += 2))
+ ((count -= 1))
+ done
+}
+
+log_assert "Verify volume can be add as several segments, but overlapping " \
+ "are not allowed."
+log_onexit cleanup
+
+# swap -a won't allow the use of multiple segments of the same volume unless
+# libdiskmgmt is disabled with the environment variable below.
+typeset -x NOINUSE_CHECK=1
+
+typeset vol=$TESTPOOL/$TESTVOL
+typeset -i pageblocks volblocks
+((pageblocks = $(getconf PAGESIZE) / 512))
+((volblocks = $(get_prop volsize $vol) / 512))
+
+log_note "Verify volume can be add as several segments."
+
+#
+# swaplow swaplen
+set -A swap_opt $((pageblocks)) \
+ $((RANDOM % (50 * pageblocks) + 2 * pageblocks)) \
+ $((volblocks / 3)) \
+ $((RANDOM % (50 * pageblocks) + 2 * pageblocks)) \
+ $((volblocks / 2)) \
+ $((RANDOM % (50 * pageblocks) + 2 * pageblocks)) \
+ $(((volblocks*2) / 3)) \
+ $((RANDOM % (50 * pageblocks) + 2 * pageblocks))
+
+swapname=${ZVOL_DEVDIR}/$vol
+typeset -i i=0 count=0
+
+if is_swap_inuse $swapname ; then
+ log_must swap -d $swapname
+fi
+
+while ((i < ${#swap_opt[@]})); do
+ log_must swap -a $swapname ${swap_opt[$i]} ${swap_opt[((i+1))]}
+
+ ((i += 2))
+ ((count += 1))
+done
+
+log_note "Verify overlapping swap volume are not allowed"
+i=0
+while ((i < ${#swap_opt[@]})); do
+ log_mustnot swap -a $swapname ${swap_opt[$i]}
+
+ ((i += 2))
+done
+
+log_pass "Verify volume can be added as several segments passed."
diff --git a/tests/zfs-tests/tests/perf/Makefile.am b/tests/zfs-tests/tests/perf/Makefile.am
new file mode 100644
index 000000000000..294b136b3854
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/Makefile.am
@@ -0,0 +1,9 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/perf
+dist_pkgdata_DATA = \
+ nfs-sample.cfg \
+ perf.shlib
+
+SUBDIRS = \
+ fio \
+ regression \
+ scripts
diff --git a/tests/zfs-tests/tests/perf/fio/Makefile.am b/tests/zfs-tests/tests/perf/fio/Makefile.am
new file mode 100644
index 000000000000..e9f854d9edff
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/Makefile.am
@@ -0,0 +1,10 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/perf/fio
+dist_pkgdata_DATA = \
+ mkfiles.fio \
+ random_reads.fio \
+ random_readwrite.fio \
+ random_readwrite_fixed.fio \
+ random_writes.fio \
+ sequential_reads.fio \
+ sequential_writes.fio \
+ sequential_readwrite.fio
diff --git a/tests/zfs-tests/tests/perf/fio/mkfiles.fio b/tests/zfs-tests/tests/perf/fio/mkfiles.fio
new file mode 100644
index 000000000000..36ec22d49295
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/mkfiles.fio
@@ -0,0 +1,33 @@
+#
+# 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.
+# Copyright (c) 2020, Kjeld Schouten-Lebbing. All rights reserved.
+#
+
+[global]
+filename_format=file$jobnum
+group_reporting=1
+fallocate=0
+ioengine=psync
+bs=1024k
+rw=write
+thread=1
+directory=${DIRECTORY}
+numjobs=${NUMJOBS}
+filesize=${FILE_SIZE}
+randseed=${PERF_RANDSEED}
+buffer_compress_percentage=${PERF_COMPPERCENT}
+buffer_pattern=0xdeadbeef
+buffer_compress_chunk=${PERF_COMPCHUNK}
+
+[job]
diff --git a/tests/zfs-tests/tests/perf/fio/random_reads.fio b/tests/zfs-tests/tests/perf/fio/random_reads.fio
new file mode 100644
index 000000000000..e6e7034e0acb
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/random_reads.fio
@@ -0,0 +1,32 @@
+#
+# 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, 2016 by Delphix. All rights reserved.
+#
+
+[global]
+filename_format=file$jobnum
+group_reporting=1
+fallocate=0
+overwrite=0
+thread=1
+rw=randread
+time_based=1
+directory=${DIRECTORY}
+runtime=${RUNTIME}
+bs=${BLOCKSIZE}
+ioengine=psync
+sync=${SYNC_TYPE}
+direct=${DIRECT}
+numjobs=${NUMJOBS}
+
+[job]
diff --git a/tests/zfs-tests/tests/perf/fio/random_readwrite.fio b/tests/zfs-tests/tests/perf/fio/random_readwrite.fio
new file mode 100644
index 000000000000..f8eb6dbdfe4f
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/random_readwrite.fio
@@ -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 (c) 2015, 2016, Delphix. All rights reserved.
+# Copyright (c) 2020, Kjeld Schouten-Lebbing. All rights reserved.
+#
+
+[global]
+filename_format=file$jobnum
+nrfiles=16
+group_reporting=1
+fallocate=0
+overwrite=0
+thread=1
+rw=randrw
+rwmixread=80
+time_based=1
+directory=${DIRECTORY}
+runtime=${RUNTIME}
+bssplit=4k/50:8k/30:128k/10:1m/10
+ioengine=psync
+sync=${SYNC_TYPE}
+direct=${DIRECT}
+numjobs=${NUMJOBS}
+randseed=${RANDSEED}
+buffer_compress_percentage=${COMPPERCENT}
+buffer_pattern=0xdeadbeef
+buffer_compress_chunk=${COMPCHUNK}
+
+[job]
diff --git a/tests/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio b/tests/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio
new file mode 100644
index 000000000000..e83b48076d0d
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/random_readwrite_fixed.fio
@@ -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 (c) 2015, 2016, Delphix. All rights reserved.
+# Copyright (c) 2020, Kjeld Schouten-Lebbing. All rights reserved.
+#
+
+[global]
+filename_format=file$jobnum
+nrfiles=16
+group_reporting=1
+fallocate=0
+overwrite=0
+thread=1
+rw=randrw
+rwmixread=70
+time_based=1
+directory=${DIRECTORY}
+runtime=${RUNTIME}
+bs=${BLOCKSIZE}
+ioengine=psync
+sync=${SYNC_TYPE}
+direct=${DIRECT}
+numjobs=${NUMJOBS}
+randseed=${RANDSEED}
+buffer_compress_percentage=${COMPPERCENT}
+buffer_pattern=0xdeadbeef
+buffer_compress_chunk=${COMPCHUNK}
+
+[job]
diff --git a/tests/zfs-tests/tests/perf/fio/random_writes.fio b/tests/zfs-tests/tests/perf/fio/random_writes.fio
new file mode 100644
index 000000000000..3b84b199438f
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/random_writes.fio
@@ -0,0 +1,37 @@
+#
+# 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, 2016, Delphix. All rights reserved.
+# Copyright (c) 2020, Kjeld Schouten-Lebbing. All rights reserved.
+#
+
+[global]
+filename_format=file$jobnum
+group_reporting=1
+fallocate=0
+thread=1
+rw=randwrite
+time_based=1
+directory=${DIRECTORY}
+runtime=${RUNTIME}
+bs=${BLOCKSIZE}
+ioengine=psync
+sync=${SYNC_TYPE}
+direct=${DIRECT}
+numjobs=${NUMJOBS}
+filesize=${FILESIZE}
+randseed=${RANDSEED}
+buffer_compress_percentage=${COMPPERCENT}
+buffer_pattern=0xdeadbeef
+buffer_compress_chunk=${COMPCHUNK}
+
+[job]
diff --git a/tests/zfs-tests/tests/perf/fio/sequential_reads.fio b/tests/zfs-tests/tests/perf/fio/sequential_reads.fio
new file mode 100644
index 000000000000..b4b45e084135
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/sequential_reads.fio
@@ -0,0 +1,32 @@
+#
+# 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, 2016 by Delphix. All rights reserved.
+#
+
+[global]
+filename_format=file$jobnum
+group_reporting=1
+fallocate=0
+overwrite=0
+thread=1
+rw=read
+time_based=1
+directory=${DIRECTORY}
+runtime=${RUNTIME}
+bs=${BLOCKSIZE}
+ioengine=psync
+sync=${SYNC_TYPE}
+direct=${DIRECT}
+numjobs=${NUMJOBS}
+
+[job]
diff --git a/tests/zfs-tests/tests/perf/fio/sequential_readwrite.fio b/tests/zfs-tests/tests/perf/fio/sequential_readwrite.fio
new file mode 100644
index 000000000000..2037ba2f67c5
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/sequential_readwrite.fio
@@ -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 (c) 2015, 2016, Delphix. All rights reserved.
+# Copyright (c) 2020, Kjeld Schouten-Lebbing. All rights reserved.
+#
+
+[global]
+filename_format=file$jobnum
+nrfiles=16
+group_reporting=1
+fallocate=0
+overwrite=0
+thread=1
+rw=readwrite
+rwmixread=80
+time_based=1
+directory=${DIRECTORY}
+runtime=${RUNTIME}
+bssplit=4k/50:8k/30:128k/10:1m/10
+ioengine=psync
+sync=${SYNC_TYPE}
+direct=${DIRECT}
+numjobs=${NUMJOBS}
+randseed=${RANDSEED}
+buffer_compress_percentage=${COMPPERCENT}
+buffer_pattern=0xdeadbeef
+buffer_compress_chunk=${COMPCHUNK}
+
+[job]
diff --git a/tests/zfs-tests/tests/perf/fio/sequential_writes.fio b/tests/zfs-tests/tests/perf/fio/sequential_writes.fio
new file mode 100644
index 000000000000..4582c818815a
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/fio/sequential_writes.fio
@@ -0,0 +1,37 @@
+#
+# 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, 2016, Delphix. All rights reserved.
+# Copyright (c) 2020, Kjeld Schouten-Lebbing. All rights reserved.
+#
+
+[global]
+filename_format=file$jobnum
+group_reporting=1
+fallocate=0
+thread=1
+rw=write
+time_based=1
+directory=${DIRECTORY}
+runtime=${RUNTIME}
+bs=${BLOCKSIZE}
+ioengine=psync
+sync=${SYNC_TYPE}
+direct=${DIRECT}
+numjobs=${NUMJOBS}
+filesize=${FILESIZE}
+randseed=${RANDSEED}
+buffer_compress_percentage=${COMPPERCENT}
+buffer_pattern=0xdeadbeef
+buffer_compress_chunk=${COMPCHUNK}
+
+[job]
diff --git a/tests/zfs-tests/tests/perf/nfs-sample.cfg b/tests/zfs-tests/tests/perf/nfs-sample.cfg
new file mode 100644
index 000000000000..f7ac2dae3500
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/nfs-sample.cfg
@@ -0,0 +1,46 @@
+#
+# 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.
+#
+
+#
+# This file is a sample NFS configuration for the performance tests. To use the
+# performance tests over NFS you must have:
+# - a client machine with fio and sudo installed
+# - passwordless SSH set up from this host
+# for delphix and root users to the client
+# - passwordless sudo for the user on the client
+#
+
+
+# The IP address for the server
+export NFS_SERVER=127.0.0.1
+
+# The IP address for the client
+export NFS_CLIENT=127.0.0.1
+
+# The mountpoint to use inside the client
+export NFS_MOUNT=/var/tmp/nfs
+
+# The user to run the tests as on the client
+export NFS_USER=delphix
+
+# Common NFS client mount options
+export NFS_OPTIONS="-o rw,nosuid,bg,hard,rsize=1048576,wsize=1048576,"
+NFS_OPTIONS+="nointr,timeo=600,proto=tcp,actimeo=0,port=2049"
+
+# illumos NFS client mount options
+# export NFS_OPTIONS="$NFS_OPTIONS,vers=3"
+
+# Linux NFS client mount options
+export NFS_OPTIONS="-t nfs $NFS_OPTIONS,noacl,nfsvers=3"
diff --git a/tests/zfs-tests/tests/perf/perf.shlib b/tests/zfs-tests/tests/perf/perf.shlib
new file mode 100644
index 000000000000..6addd46610c2
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/perf.shlib
@@ -0,0 +1,575 @@
+#
+# 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, 2016 by Delphix. All rights reserved.
+# Copyright (c) 2016, Intel Corporation.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+# If neither is specified, do a nightly run.
+[[ -z $PERF_REGRESSION_WEEKLY ]] && export PERF_REGRESSION_NIGHTLY=1
+
+# Default runtime for each type of test run.
+export PERF_RUNTIME_WEEKLY=$((30 * 60))
+export PERF_RUNTIME_NIGHTLY=$((10 * 60))
+
+# Default to JSON for fio output
+export PERF_FIO_FORMAT=${PERF_FIO_FORMAT:-'json'}
+
+# Default fs creation options
+export PERF_FS_OPTS=${PERF_FS_OPTS:-'-o recsize=8k -o compress=lz4' \
+ ' -o checksum=sha256 -o redundant_metadata=most'}
+
+function get_sync_str
+{
+ typeset sync=$1
+ typeset sync_str=''
+
+ [[ $sync -eq 0 ]] && sync_str='async'
+ [[ $sync -eq 1 ]] && sync_str='sync'
+ echo $sync_str
+}
+
+function get_suffix
+{
+ typeset threads=$1
+ typeset sync=$2
+ typeset iosize=$3
+
+ typeset sync_str=$(get_sync_str $sync)
+ typeset filesystems=$(get_nfilesystems)
+
+ typeset suffix="$sync_str.$iosize-ios"
+ suffix="$suffix.$threads-threads.$filesystems-filesystems"
+ echo $suffix
+}
+
+function do_fio_run_impl
+{
+ typeset script=$1
+ typeset do_recreate=$2
+ typeset clear_cache=$3
+
+ typeset threads=$4
+ typeset threads_per_fs=$5
+ typeset sync=$6
+ typeset iosize=$7
+
+ typeset sync_str=$(get_sync_str $sync)
+ log_note "Running with $threads $sync_str threads, $iosize ios"
+
+ if [[ -n $threads_per_fs && $threads_per_fs -ne 0 ]]; then
+ log_must test $do_recreate
+ verify_threads_per_fs $threads $threads_per_fs
+ fi
+
+ if $do_recreate; then
+ recreate_perf_pool
+
+ #
+ # A value of zero for "threads_per_fs" is "special", and
+ # means a single filesystem should be used, regardless
+ # of the number of threads.
+ #
+ if [[ -n $threads_per_fs && $threads_per_fs -ne 0 ]]; then
+ populate_perf_filesystems $((threads / threads_per_fs))
+ else
+ populate_perf_filesystems 1
+ fi
+ fi
+
+ if $clear_cache; then
+ # Clear the ARC
+ zpool export $PERFPOOL
+ zpool import $PERFPOOL
+ fi
+
+ if [[ -n $ZINJECT_DELAYS ]]; then
+ apply_zinject_delays
+ else
+ log_note "No per-device commands to execute."
+ fi
+
+ #
+ # Allow this to be overridden by the individual test case. This
+ # can be used to run the FIO job against something other than
+ # the default filesystem (e.g. against a clone).
+ #
+ export DIRECTORY=$(get_directory)
+ log_note "DIRECTORY: " $DIRECTORY
+
+ export RUNTIME=$PERF_RUNTIME
+ export RANDSEED=$PERF_RANDSEED
+ export COMPPERCENT=$PERF_COMPPERCENT
+ export COMPCHUNK=$PERF_COMPCHUNK
+ export FILESIZE=$((TOTAL_SIZE / threads))
+ export NUMJOBS=$threads
+ export SYNC_TYPE=$sync
+ export BLOCKSIZE=$iosize
+ sync
+
+ # When running locally, we want to keep the default behavior of
+ # DIRECT == 0, so only set it when we're running over NFS to
+ # disable client cache for reads.
+ if [[ $NFS -eq 1 ]]; then
+ export DIRECT=1
+ do_setup_nfs $script
+ else
+ export DIRECT=0
+ fi
+
+ # This will be part of the output filename.
+ typeset suffix=$(get_suffix $threads $sync $iosize)
+
+ # Start the data collection
+ do_collect_scripts $suffix
+
+ # Define output file
+ typeset logbase="$(get_perf_output_dir)/$(basename \
+ $SUDO_COMMAND)"
+ typeset outfile="$logbase.fio.$suffix"
+
+ # Start the load
+ if [[ $NFS -eq 1 ]]; then
+ log_must ssh -t $NFS_USER@$NFS_CLIENT "
+ fio --output-format=${PERF_FIO_FORMAT} \
+ --output /tmp/fio.out /tmp/test.fio
+ "
+ log_must scp $NFS_USER@$NFS_CLIENT:/tmp/fio.out $outfile
+ log_must ssh -t $NFS_USER@$NFS_CLIENT "sudo -S umount $NFS_MOUNT"
+ else
+ log_must fio --output-format=${PERF_FIO_FORMAT} \
+ --output $outfile $FIO_SCRIPTS/$script
+ fi
+}
+
+#
+# This function will run fio in a loop, according to the .fio file passed
+# in and a number of environment variables. The following variables can be
+# set before launching zfstest to override the defaults.
+#
+# PERF_RUNTIME: The time in seconds each fio invocation should run.
+# PERF_RUNTYPE: A human readable tag that appears in logs. The defaults are
+# nightly and weekly.
+# PERF_NTHREADS: A list of how many threads each fio invocation will use.
+# PERF_SYNC_TYPES: Whether to use (O_SYNC) or not. 1 is sync IO, 0 is async IO.
+# PERF_IOSIZES: A list of blocksizes in which each fio invocation will do IO.
+# PERF_COLLECT_SCRIPTS: A comma delimited list of 'command args, logfile_tag'
+# pairs that will be added to the scripts specified in each test.
+#
+function do_fio_run
+{
+ typeset script=$1
+ typeset do_recreate=$2
+ typeset clear_cache=$3
+ typeset threads threads_per_fs sync iosize
+
+ for threads in $PERF_NTHREADS; do
+ for threads_per_fs in $PERF_NTHREADS_PER_FS; do
+ for sync in $PERF_SYNC_TYPES; do
+ for iosize in $PERF_IOSIZES; do
+ do_fio_run_impl \
+ $script \
+ $do_recreate \
+ $clear_cache \
+ $threads \
+ $threads_per_fs \
+ $sync \
+ $iosize
+ done
+ done
+ done
+ done
+}
+
+# This function sets NFS mount on the client and make sure all correct
+# permissions are in place
+#
+function do_setup_nfs
+{
+ typeset script=$1
+ zfs set sharenfs=on $TESTFS
+ log_must chmod -R 777 /$TESTFS
+
+ ssh -t $NFS_USER@$NFS_CLIENT "mkdir -m 777 -p $NFS_MOUNT"
+ ssh -t $NFS_USER@$NFS_CLIENT "sudo -S umount $NFS_MOUNT"
+ log_must ssh -t $NFS_USER@$NFS_CLIENT "
+ sudo -S mount $NFS_OPTIONS $NFS_SERVER:/$TESTFS $NFS_MOUNT
+ "
+ #
+ # The variables in the fio script are only available in our current
+ # shell session, so we have to evaluate them here before copying
+ # the resulting script over to the target machine.
+ #
+ export jobnum='$jobnum'
+ while read line; do
+ eval echo "$line"
+ done < $FIO_SCRIPTS/$script > /tmp/test.fio
+ log_must sed -i -e "s%directory.*%directory=$NFS_MOUNT%" /tmp/test.fio
+ log_must scp /tmp/test.fio $NFS_USER@$NFS_CLIENT:/tmp
+ log_must rm /tmp/test.fio
+}
+
+#
+# This function iterates through the value pairs in $PERF_COLLECT_SCRIPTS.
+# The script at index N is launched in the background, with its output
+# redirected to a logfile containing the tag specified at index N + 1.
+#
+function do_collect_scripts
+{
+ typeset suffix=$1
+
+ [[ -n $collect_scripts ]] || log_fail "No data collection scripts."
+ [[ -n $PERF_RUNTIME ]] || log_fail "No runtime specified."
+
+ # Add in user supplied scripts and logfiles, if any.
+ typeset oIFS=$IFS
+ IFS=','
+ for item in $PERF_COLLECT_SCRIPTS; do
+ collect_scripts+=($(echo $item | sed 's/^ *//g'))
+ done
+ IFS=$oIFS
+
+ typeset idx=0
+ while [[ $idx -lt "${#collect_scripts[@]}" ]]; do
+ typeset logbase="$(get_perf_output_dir)/$(basename \
+ $SUDO_COMMAND)"
+ typeset outfile="$logbase.${collect_scripts[$idx + 1]}.$suffix"
+
+ timeout $PERF_RUNTIME ${collect_scripts[$idx]} >$outfile 2>&1 &
+ ((idx += 2))
+ done
+
+ # Need to explicitly return 0 because timeout(1) will kill
+ # a child process and cause us to return non-zero.
+ return 0
+}
+
+# Find a place to deposit performance data collected while under load.
+function get_perf_output_dir
+{
+ typeset dir="$(pwd)/perf_data"
+ [[ -d $dir ]] || mkdir -p $dir
+
+ echo $dir
+}
+
+function apply_zinject_delays
+{
+ typeset idx=0
+ while [[ $idx -lt "${#ZINJECT_DELAYS[@]}" ]]; do
+ [[ -n ${ZINJECT_DELAYS[$idx]} ]] || \
+ log_must "No zinject delay found at index: $idx"
+
+ for disk in $DISKS; do
+ log_must zinject \
+ -d $disk -D ${ZINJECT_DELAYS[$idx]} $PERFPOOL
+ done
+
+ ((idx += 1))
+ done
+}
+
+function clear_zinject_delays
+{
+ log_must zinject -c all
+}
+
+#
+# Destroy and create the pool used for performance tests.
+#
+function recreate_perf_pool
+{
+ [[ -n $PERFPOOL ]] || log_fail "The \$PERFPOOL variable isn't set."
+
+ #
+ # In case there's been some "leaked" zinject delays, or if the
+ # performance test injected some delays itself, we clear all
+ # delays before attempting to destroy the pool. Each delay
+ # places a hold on the pool, so the destroy will fail if there
+ # are any outstanding delays.
+ #
+ clear_zinject_delays
+
+ #
+ # This function handles the case where the pool already exists,
+ # and will destroy the previous pool and recreate a new pool.
+ #
+ create_pool $PERFPOOL $DISKS
+}
+
+function verify_threads_per_fs
+{
+ typeset threads=$1
+ typeset threads_per_fs=$2
+
+ log_must test -n $threads
+ log_must test -n $threads_per_fs
+
+ #
+ # A value of "0" is treated as a "special value", and it is
+ # interpreted to mean all threads will run using a single
+ # filesystem.
+ #
+ [[ $threads_per_fs -eq 0 ]] && return
+
+ #
+ # The number of threads per filesystem must be a value greater
+ # than or equal to zero; since we just verified the value isn't
+ # 0 above, then it must be greater than zero here.
+ #
+ log_must test $threads_per_fs -ge 0
+
+ #
+ # This restriction can be lifted later if needed, but for now,
+ # we restrict the number of threads per filesystem to a value
+ # that evenly divides the thread count. This way, the threads
+ # will be evenly distributed over all the filesystems.
+ #
+ log_must test $((threads % threads_per_fs)) -eq 0
+}
+
+function populate_perf_filesystems
+{
+ typeset nfilesystems=${1:-1}
+
+ export TESTFS=""
+ for i in $(seq 1 $nfilesystems); do
+ typeset dataset="$PERFPOOL/fs$i"
+ create_dataset $dataset $PERF_FS_OPTS
+ if [[ -z "$TESTFS" ]]; then
+ TESTFS="$dataset"
+ else
+ TESTFS="$TESTFS $dataset"
+ fi
+ done
+}
+
+function get_nfilesystems
+{
+ typeset filesystems=( $TESTFS )
+ echo ${#filesystems[@]}
+}
+
+function get_directory
+{
+ typeset filesystems=( $TESTFS )
+ typeset directory=
+
+ typeset idx=0
+ while [[ $idx -lt "${#filesystems[@]}" ]]; do
+ mountpoint=$(get_prop mountpoint "${filesystems[$idx]}")
+
+ if [[ -n $directory ]]; then
+ directory=$directory:$mountpoint
+ else
+ directory=$mountpoint
+ fi
+
+ ((idx += 1))
+ done
+
+ echo $directory
+}
+
+function get_min_arc_size
+{
+ typeset -l min_arc_size
+
+ if is_freebsd; then
+ min_arc_size=$(sysctl -n kstat.zfs.misc.arcstats.c_min)
+ elif is_illumos; then
+ min_arc_size=$(dtrace -qn 'BEGIN {
+ printf("%u\n", `arc_stats.arcstat_c_min.value.ui64);
+ exit(0);
+ }')
+ elif is_linux; then
+ min_arc_size=`awk '$1 == "c_min" { print $3 }' \
+ /proc/spl/kstat/zfs/arcstats`
+ fi
+
+ [[ $? -eq 0 ]] || log_fail "get_min_arc_size failed"
+
+ echo $min_arc_size
+}
+
+function get_max_arc_size
+{
+ typeset -l max_arc_size
+
+ if is_freebsd; then
+ max_arc_size=$(sysctl -n kstat.zfs.misc.arcstats.c_max)
+ elif is_illumos; then
+ max_arc_size=$(dtrace -qn 'BEGIN {
+ printf("%u\n", `arc_stats.arcstat_c_max.value.ui64);
+ exit(0);
+ }')
+ elif is_linux; then
+ max_arc_size=`awk '$1 == "c_max" { print $3 }' \
+ /proc/spl/kstat/zfs/arcstats`
+ fi
+
+ [[ $? -eq 0 ]] || log_fail "get_max_arc_size failed"
+
+ echo $max_arc_size
+}
+
+function get_max_dbuf_cache_size
+{
+ typeset -l max_dbuf_cache_size
+
+ if is_illumos; then
+ max_dbuf_cache_size=$(dtrace -qn 'BEGIN {
+ printf("%u\n", `dbuf_cache_max_bytes);
+ exit(0);
+ }')
+ else
+ max_dbuf_cache_size=$(get_tunable DBUF_CACHE_MAX_BYTES)
+ fi
+
+ [[ $? -eq 0 ]] || log_fail "get_max_dbuf_cache_size failed"
+
+ echo $max_dbuf_cache_size
+}
+
+# Create a file with some information about how this system is configured.
+function get_system_config
+{
+ typeset config=$PERF_DATA_DIR/$1
+
+ echo "{" >>$config
+ if is_linux; then
+ echo " \"ncpus\": \"$(nproc --all)\"," >>$config
+ echo " \"physmem\": \"$(free -b | \
+ awk '$1 == "Mem:" { print $2 }')\"," >>$config
+ echo " \"c_max\": \"$(get_max_arc_size)\"," >>$config
+ echo " \"hostname\": \"$(uname -n)\"," >>$config
+ echo " \"kernel version\": \"$(uname -sr)\"," >>$config
+ else
+ dtrace -qn 'BEGIN{
+ printf(" \"ncpus\": %d,\n", `ncpus);
+ printf(" \"physmem\": %u,\n", `physmem * `_pagesize);
+ printf(" \"c_max\": %u,\n", `arc_stats.arcstat_c_max.value.ui64);
+ printf(" \"kmem_flags\": \"0x%x\",", `kmem_flags);
+ exit(0)}' >>$config
+ echo " \"hostname\": \"$(uname -n)\"," >>$config
+ echo " \"kernel version\": \"$(uname -v)\"," >>$config
+ fi
+ if is_linux; then
+ lsblk -dino NAME,SIZE | awk 'BEGIN {
+ printf(" \"disks\": {\n"); first = 1}
+ {disk = $1} {size = $2;
+ if (first != 1) {printf(",\n")} else {first = 0}
+ printf(" \"%s\": \"%s\"", disk, size)}
+ END {printf("\n },\n")}' >>$config
+
+ zfs_tunables="/sys/module/zfs/parameters"
+
+ printf " \"tunables\": {\n" >>$config
+ for tunable in \
+ zfs_arc_max \
+ zfs_arc_meta_limit \
+ zfs_arc_sys_free \
+ zfs_dirty_data_max \
+ zfs_flags \
+ zfs_prefetch_disable \
+ zfs_txg_timeout \
+ zfs_vdev_aggregation_limit \
+ zfs_vdev_async_read_max_active \
+ zfs_vdev_async_write_max_active \
+ zfs_vdev_sync_read_max_active \
+ zfs_vdev_sync_write_max_active \
+ zio_slow_io_ms
+ do
+ if [ "$tunable" != "zfs_arc_max" ]
+ then
+ printf ",\n" >>$config
+ fi
+ printf " \"$tunable\": \"$(<$zfs_tunables/$tunable)\"" \
+ >>$config
+ done
+ printf "\n }\n" >>$config
+ else
+ iostat -En | awk 'BEGIN {
+ printf(" \"disks\": {\n"); first = 1}
+ /^c/ {disk = $1}
+ /^Size: [^0]/ {size = $2;
+ if (first != 1) {printf(",\n")} else {first = 0}
+ printf(" \"%s\": \"%s\"", disk, size)}
+ END {printf("\n },\n")}' >>$config
+
+ sed -n 's/^set \(.*\)[ ]=[ ]\(.*\)/\1=\2/p' /etc/system | \
+ awk -F= 'BEGIN {printf(" \"system\": {\n"); first = 1}
+ {if (first != 1) {printf(",\n")} else {first = 0};
+ printf(" \"%s\": %s", $1, $2)}
+ END {printf("\n }\n")}' >>$config
+ fi
+ echo "}" >>$config
+}
+
+function num_jobs_by_cpu
+{
+ if is_linux; then
+ typeset ncpu=$($NPROC --all)
+ else
+ typeset ncpu=$(psrinfo | $WC -l)
+ fi
+ typeset num_jobs=$ncpu
+
+ [[ $ncpu -gt 8 ]] && num_jobs=$(echo "$ncpu * 3 / 4" | bc)
+
+ echo $num_jobs
+}
+
+#
+# On illumos this looks like: ":sd3:sd4:sd1:sd2:"
+#
+function pool_to_lun_list
+{
+ typeset pool=$1
+ typeset ctd ctds devname lun
+ typeset lun_list=':'
+
+ if is_illumos; then
+ ctds=$(zpool list -v $pool |
+ awk '/c[0-9]*t[0-9a-fA-F]*d[0-9]*/ {print $1}')
+
+ for ctd in $ctds; do
+ # Get the device name as it appears in /etc/path_to_inst
+ devname=$(readlink -f /dev/dsk/${ctd}s0 | sed -n \
+ 's/\/devices\([^:]*\):.*/\1/p')
+ # Add a string composed of the driver name and instance
+ # number to the list for comparison with dev_statname.
+ lun=$(sed 's/"//g' /etc/path_to_inst | grep \
+ $devname | awk '{print $3$2}')
+ lun_list="$lun_list$lun:"
+ done
+ elif is_freebsd; then
+ lun_list+=$(zpool list -HLv $pool | \
+ awk '/a?da[0-9]+|md[0-9]+|mfid[0-9]+|nda[0-9]+|nvd[0-9]+|vtbd[0-9]+/
+ { printf "%s:", $1 }')
+ elif is_linux; then
+ ctds=$(zpool list -HLv $pool | \
+ awk '/sd[a-z]*|loop[0-9]*|dm-[0-9]*/ {print $1}')
+
+ for ctd in $ctds; do
+ lun_list="$lun_list$ctd:"
+ done
+ fi
+ echo $lun_list
+}
+
+# Create a perf_data directory to hold performance statistics and
+# configuration information.
+export PERF_DATA_DIR=$(get_perf_output_dir)
+[[ -f $PERF_DATA_DIR/config.json ]] || get_system_config config.json
diff --git a/tests/zfs-tests/tests/perf/regression/Makefile.am b/tests/zfs-tests/tests/perf/regression/Makefile.am
new file mode 100644
index 000000000000..124e0936aa99
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/Makefile.am
@@ -0,0 +1,13 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/perf/regression
+dist_pkgdata_SCRIPTS = \
+ random_reads.ksh \
+ random_readwrite.ksh \
+ random_readwrite_fixed.ksh \
+ random_writes.ksh \
+ random_writes_zil.ksh \
+ sequential_reads_arc_cached_clone.ksh \
+ sequential_reads_arc_cached.ksh \
+ sequential_reads_dbuf_cached.ksh \
+ sequential_reads.ksh \
+ sequential_writes.ksh \
+ setup.ksh
diff --git a/tests/zfs-tests/tests/perf/regression/random_reads.ksh b/tests/zfs-tests/tests/perf/regression/random_reads.ksh
new file mode 100755
index 000000000000..e6d207e22747
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/random_reads.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) 2015, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the random_reads job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# The files to read from are created prior to the first fio run, and used
+# for all fio runs. The ARC is cleared with `zinject -a` prior to each run
+# so reads will go to disk.
+#
+# Thread/Concurrency settings:
+# PERF_NTHREADS defines the number of files created in the test filesystem,
+# as well as the number of threads that will simultaneously drive IO to
+# those files. The settings chosen are from measurements in the
+# PerfAutoESX/ZFSPerfESX Environments, selected at concurrency levels that
+# are at peak throughput but lowest latency. Higher concurrency introduces
+# queue time latency and would reduce the impact of code-induced performance
+# regressions.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
+export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'}
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'16 32'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k'}
+fi
+
+# Layout the files to be used by the read tests. Create as many files as the
+# largest number of threads. An fio run with fewer threads will use a subset
+# of the available files.
+export NUMJOBS=$(get_max $PERF_NTHREADS)
+export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
+export DIRECTORY=$(get_directory)
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ )
+fi
+
+log_note "Random reads with $PERF_RUNTYPE settings"
+do_fio_run random_reads.fio false true
+log_pass "Measure IO stats during random read load"
diff --git a/tests/zfs-tests/tests/perf/regression/random_readwrite.ksh b/tests/zfs-tests/tests/perf/regression/random_readwrite.ksh
new file mode 100755
index 000000000000..573e9c7d4c58
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/random_readwrite.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) 2015, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the random_readwrite job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# The files to read and write from are created prior to the first fio run,
+# and used for all fio runs. The ARC is cleared with `zinject -a` prior to
+# each run so reads will go to disk.
+#
+# Thread/Concurrency settings:
+# PERF_NTHREADS defines the number of files created in the test filesystem,
+# as well as the number of threads that will simultaneously drive IO to
+# those files. The settings chosen are from measurements in the
+# PerfAutoESX/ZFSPerfESX Environments, selected at concurrency levels that
+# are at peak throughput but lowest latency. Higher concurrency introduces
+# queue time latency and would reduce the impact of code-induced performance
+# regressions.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
+export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'4 8 16 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'}
+ export PERF_IOSIZES='' # bssplit used instead
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'32 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES='' # bssplit used instead
+fi
+
+# Layout the files to be used by the readwrite tests. Create as many files
+# as the largest number of threads. An fio run with fewer threads will use
+# a subset of the available files.
+export NUMJOBS=$(get_max $PERF_NTHREADS)
+export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
+export DIRECTORY=$(get_directory)
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ )
+fi
+
+log_note "Random reads and writes with $PERF_RUNTYPE settings"
+do_fio_run random_readwrite.fio false true
+log_pass "Measure IO stats during random read and write load"
diff --git a/tests/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh b/tests/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh
new file mode 100755
index 000000000000..78af5213a3d3
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/random_readwrite_fixed.ksh
@@ -0,0 +1,106 @@
+#!/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, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the random_readwrite_fixed job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# The files to read and write from are created prior to the first fio run,
+# and used for all fio runs. The ARC is cleared with `zinject -a` prior to
+# each run so reads will go to disk.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random read write load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
+export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'}
+ export PERF_IOSIZES='8k 64k'
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES='8k'
+fi
+
+# Layout the files to be used by the readwrite tests. Create as many files
+# as the largest number of threads. An fio run with fewer threads will use
+# a subset of the available files.
+export NUMJOBS=$(get_max $PERF_NTHREADS)
+export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
+export DIRECTORY=$(get_directory)
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "kstat zfs:0 1" "kstat"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "dtrace -s $PERF_SCRIPTS/profile.d" "profile"
+ )
+fi
+
+log_note "Random reads and writes with $PERF_RUNTYPE settings"
+do_fio_run random_readwrite_fixed.fio false true
+log_pass "Measure IO stats during random read and write load"
diff --git a/tests/zfs-tests/tests/perf/regression/random_writes.ksh b/tests/zfs-tests/tests/perf/regression/random_writes.ksh
new file mode 100755
index 000000000000..dca013cbae0c
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/random_writes.ksh
@@ -0,0 +1,105 @@
+#!/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, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the random_writes job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# Prior to each fio run the dataset is recreated, and fio writes new files
+# into an otherwise empty pool.
+#
+# Thread/Concurrency settings:
+# PERF_NTHREADS defines the number of files created in the test filesystem,
+# as well as the number of threads that will simultaneously drive IO to
+# those files. The settings chosen are from measurements in the
+# PerfAutoESX/ZFSPerfESX Environments, selected at concurrency levels that
+# are at peak throughput but lowest latency. Higher concurrency introduces
+# queue time latency and would reduce the impact of code-induced performance
+# regressions.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
+export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'1 4 8 16 32 64 128'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 256k'}
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'32 128'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k'}
+fi
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ )
+fi
+
+log_note "Random writes with $PERF_RUNTYPE settings"
+do_fio_run random_writes.fio true false
+log_pass "Measure IO stats during random write load"
diff --git a/tests/zfs-tests/tests/perf/regression/random_writes_zil.ksh b/tests/zfs-tests/tests/perf/regression/random_writes_zil.ksh
new file mode 100755
index 000000000000..5d4fd77a7458
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/random_writes_zil.ksh
@@ -0,0 +1,100 @@
+#!/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, 2020 by Delphix. All rights reserved.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+
+ #
+ # We're using many filesystems depending on the number of
+ # threads for each test, and there's no good way to get a list
+ # of all the filesystems that should be destroyed on cleanup
+ # (i.e. the list of filesystems used for the last test ran).
+ # Thus, we simply recreate the pool as a way to destroy all
+ # filesystems and leave a fresh pool behind.
+ #
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random write load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+
+# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
+export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
+
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'1 2 4 8 16 32 64 128'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0 1'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k'}
+
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'1 4 16 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0 1'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k'}
+fi
+
+# Until the performance tests over NFS can deal with multiple file systems,
+# force the use of only one file system when testing over NFS.
+[[ $NFS -eq 1 ]] && PERF_NTHREADS_PER_FS='0'
+
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "kstat zfs:0 1" "kstat"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "dtrace -s $PERF_SCRIPTS/zil.d $PERFPOOL 1" "zil"
+ "dtrace -s $PERF_SCRIPTS/profile.d" "profile"
+ "dtrace -s $PERF_SCRIPTS/offcpu-profile.d" "offcpu-profile"
+ )
+fi
+log_note "ZIL specific random write workload with $PERF_RUNTYPE settings"
+do_fio_run random_writes.fio true false
+log_pass "Measure IO stats during ZIL specific random write workload"
diff --git a/tests/zfs-tests/tests/perf/regression/sequential_reads.ksh b/tests/zfs-tests/tests/perf/regression/sequential_reads.ksh
new file mode 100755
index 000000000000..e5cf6278391c
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/sequential_reads.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) 2015, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the sequential_reads job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# The files to read from are created prior to the first fio run, and used
+# for all fio runs. The ARC is cleared with `zinject -a` prior to each run
+# so reads will go to disk.
+#
+# Thread/Concurrency settings:
+# PERF_NTHREADS defines the number of files created in the test filesystem,
+# as well as the number of threads that will simultaneously drive IO to
+# those files. The settings chosen are from measurements in the
+# PerfAutoESX/ZFSPerfESX Environments, selected at concurrency levels that
+# are at peak throughput but lowest latency. Higher concurrency introduces
+# queue time latency and would reduce the impact of code-induced performance
+# regressions.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
+export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'}
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'8 16'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'128k 1m'}
+fi
+
+# Layout the files to be used by the read tests. Create as many files as the
+# largest number of threads. An fio run with fewer threads will use a subset
+# of the available files.
+export NUMJOBS=$(get_max $PERF_NTHREADS)
+export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
+export DIRECTORY=$(get_directory)
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ )
+fi
+
+log_note "Sequential reads with $PERF_RUNTYPE settings"
+do_fio_run sequential_reads.fio false true
+log_pass "Measure IO stats during sequential read load"
diff --git a/tests/zfs-tests/tests/perf/regression/sequential_reads_arc_cached.ksh b/tests/zfs-tests/tests/perf/regression/sequential_reads_arc_cached.ksh
new file mode 100755
index 000000000000..d44e37f3eaaf
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/sequential_reads_arc_cached.ksh
@@ -0,0 +1,106 @@
+#!/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, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the sequential_reads job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# The files to read from are created prior to the first fio run, and used
+# for all fio runs. The ARC is not cleared to ensure that all data is cached.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Make sure the working set can be cached in the arc. Aim for 1/2 of arc.
+export TOTAL_SIZE=$(($(get_max_arc_size) / 2))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'}
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'128k 1m'}
+fi
+
+# Layout the files to be used by the read tests. Create as many files as the
+# largest number of threads. An fio run with fewer threads will use a subset
+# of the available files.
+export NUMJOBS=$(get_max $PERF_NTHREADS)
+export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
+export DIRECTORY=$(get_directory)
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ )
+fi
+
+log_note "Sequential cached reads with $PERF_RUNTYPE settings"
+do_fio_run sequential_reads.fio false false
+log_pass "Measure IO stats during sequential cached read load"
diff --git a/tests/zfs-tests/tests/perf/regression/sequential_reads_arc_cached_clone.ksh b/tests/zfs-tests/tests/perf/regression/sequential_reads_arc_cached_clone.ksh
new file mode 100755
index 000000000000..1b3ee85ec55a
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/sequential_reads_arc_cached_clone.ksh
@@ -0,0 +1,132 @@
+#!/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, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the sequential_reads job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# The files to read from are created prior to the first fio run, and used
+# for all fio runs. This test will exercise cached read performance from
+# a clone filesystem. The data is initially cached in the ARC and then
+# a snapshot and clone are created. All the performance runs are then
+# initiated against the clone filesystem to exercise the performance of
+# reads when the ARC has to create another buffer from a different dataset.
+# It will also exercise the need to evict the duplicate buffer once the last
+# reference on that buffer is released.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Make sure the working set can be cached in the arc. Aim for 1/2 of arc.
+export TOTAL_SIZE=$(($(get_max_arc_size) / 2))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'}
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'64 128'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'128k 1m'}
+fi
+
+# Layout the files to be used by the read tests. Create as many files as the
+# largest number of threads. An fio run with fewer threads will use a subset
+# of the available files.
+export NUMJOBS=$(get_max $PERF_NTHREADS)
+export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
+export DIRECTORY=$(get_directory)
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+
+#
+# Only a single filesystem is used by this test. To be defensive, we
+# double check that TESTFS only contains a single filesystem. We
+# wouldn't want to assume this was the case, and have it actually
+# contain multiple filesystem (causing cascading failures later).
+#
+log_must test $(get_nfilesystems) -eq 1
+
+log_note "Creating snapshot, $TESTSNAP, of $TESTFS"
+create_snapshot $TESTFS $TESTSNAP
+log_note "Creating clone, $PERFPOOL/$TESTCLONE, from $TESTFS@$TESTSNAP"
+create_clone $TESTFS@$TESTSNAP $PERFPOOL/$TESTCLONE
+
+#
+# We want to run FIO against the clone we created above, and not the
+# clone's originating filesystem. Thus, we override the default behavior
+# and explicitly set TESTFS to the clone.
+#
+export TESTFS=$PERFPOOL/$TESTCLONE
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "$PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ )
+fi
+
+log_note "Sequential cached reads from $DIRECTORY with $PERF_RUNTYPE settings"
+do_fio_run sequential_reads.fio false false
+log_pass "Measure IO stats during sequential cached read load"
diff --git a/tests/zfs-tests/tests/perf/regression/sequential_reads_dbuf_cached.ksh b/tests/zfs-tests/tests/perf/regression/sequential_reads_dbuf_cached.ksh
new file mode 100755
index 000000000000..888136fec93c
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/sequential_reads_dbuf_cached.ksh
@@ -0,0 +1,112 @@
+#!/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) 2016, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the sequential_reads job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# The files to read from are created prior to the first fio run, and used
+# for all fio runs. The ARC is not cleared to ensure that all data is cached.
+#
+# This is basically a copy of the sequential_reads_cached test case, but with
+# a smaller dataset so that we can fit everything into the decompressed, linear
+# space in the dbuf cache.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during sequential read load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Ensure the working set can be cached in the dbuf cache.
+export TOTAL_SIZE=$(($(get_max_dbuf_cache_size) * 3 / 4))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'8 16 32 64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 128k'}
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'64'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'64k'}
+fi
+
+# Layout the files to be used by the read tests. Create as many files as the
+# largest number of threads. An fio run with fewer threads will use a subset
+# of the available files.
+export NUMJOBS=$(get_max $PERF_NTHREADS)
+export FILE_SIZE=$((TOTAL_SIZE / NUMJOBS))
+export DIRECTORY=$(get_directory)
+log_must fio $FIO_SCRIPTS/mkfiles.fio
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "$PERF_SCRIPTS/prefetch_io.sh $PERFPOOL 1" "prefetch"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "kstat zfs:0 1" "kstat"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ "dtrace -Cs $PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "dtrace -Cs $PERF_SCRIPTS/prefetch_io.d $PERFPOOL 1" "prefetch"
+ "dtrace -s $PERF_SCRIPTS/profile.d" "profile"
+ )
+fi
+
+log_note "Sequential cached reads with $PERF_RUNTYPE settings"
+do_fio_run sequential_reads.fio false false
+log_pass "Measure IO stats during sequential cached read load"
diff --git a/tests/zfs-tests/tests/perf/regression/sequential_writes.ksh b/tests/zfs-tests/tests/perf/regression/sequential_writes.ksh
new file mode 100755
index 000000000000..b4f466c4f65c
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/sequential_writes.ksh
@@ -0,0 +1,105 @@
+#!/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, 2020 by Delphix. All rights reserved.
+#
+
+#
+# Description:
+# Trigger fio runs using the sequential_writes job file. The number of runs and
+# data collected is determined by the PERF_* variables. See do_fio_run for
+# details about these variables.
+#
+# Prior to each fio run the dataset is recreated, and fio writes new files
+# into an otherwise empty pool.
+#
+# Thread/Concurrency settings:
+# PERF_NTHREADS defines the number of files created in the test filesystem,
+# as well as the number of threads that will simultaneously drive IO to
+# those files. The settings chosen are from measurements in the
+# PerfAutoESX/ZFSPerfESX Environments, selected at concurrency levels that
+# are at peak throughput but lowest latency. Higher concurrency introduces
+# queue time latency and would reduce the impact of code-induced performance
+# regressions.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/perf/perf.shlib
+
+function cleanup
+{
+ # kill fio and iostat
+ pkill fio
+ pkill iostat
+ recreate_perf_pool
+}
+
+trap "log_fail \"Measure IO stats during random read load\"" SIGTERM
+log_onexit cleanup
+
+recreate_perf_pool
+populate_perf_filesystems
+
+# Aim to fill the pool to 50% capacity while accounting for a 3x compressratio.
+export TOTAL_SIZE=$(($(get_prop avail $PERFPOOL) * 3 / 2))
+
+# Variables for use by fio.
+if [[ -n $PERF_REGRESSION_WEEKLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_WEEKLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'weekly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'1 4 8 16 32 64 128'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'0 1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k 64k 256k'}
+elif [[ -n $PERF_REGRESSION_NIGHTLY ]]; then
+ export PERF_RUNTIME=${PERF_RUNTIME:-$PERF_RUNTIME_NIGHTLY}
+ export PERF_RANDSEED=${PERF_RANDSEED:-'1234'}
+ export PERF_COMPPERCENT=${PERF_COMPPERCENT:-'66'}
+ export PERF_COMPCHUNK=${PERF_COMPCHUNK:-'4096'}
+ export PERF_RUNTYPE=${PERF_RUNTYPE:-'nightly'}
+ export PERF_NTHREADS=${PERF_NTHREADS:-'16 32'}
+ export PERF_NTHREADS_PER_FS=${PERF_NTHREADS_PER_FS:-'0'}
+ export PERF_SYNC_TYPES=${PERF_SYNC_TYPES:-'1'}
+ export PERF_IOSIZES=${PERF_IOSIZES:-'8k 128k 1m'}
+fi
+
+# Set up the scripts and output files that will log performance data.
+lun_list=$(pool_to_lun_list $PERFPOOL)
+log_note "Collecting backend IO stats with lun list $lun_list"
+if is_linux; then
+ typeset perf_record_cmd="perf record -F 99 -a -g -q \
+ -o /dev/stdout -- sleep ${PERF_RUNTIME}"
+
+ export collect_scripts=(
+ "zpool iostat -lpvyL $PERFPOOL 1" "zpool.iostat"
+ "vmstat -t 1" "vmstat"
+ "mpstat -P ALL 1" "mpstat"
+ "iostat -tdxyz 1" "iostat"
+ "$perf_record_cmd" "perf"
+ )
+else
+ export collect_scripts=(
+ "$PERF_SCRIPTS/io.d $PERFPOOL $lun_list 1" "io"
+ "vmstat -T d 1" "vmstat"
+ "mpstat -T d 1" "mpstat"
+ "iostat -T d -xcnz 1" "iostat"
+ )
+fi
+
+log_note "Sequential writes with $PERF_RUNTYPE settings"
+do_fio_run sequential_writes.fio true false
+log_pass "Measure IO stats during sequential write load"
diff --git a/tests/zfs-tests/tests/perf/regression/setup.ksh b/tests/zfs-tests/tests/perf/regression/setup.ksh
new file mode 100755
index 000000000000..1544f637d8d9
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/regression/setup.ksh
@@ -0,0 +1,23 @@
+#!/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
+
+verify_runnable "global"
+verify_disk_count "$DISKS" 3
+
+log_pass
diff --git a/tests/zfs-tests/tests/perf/scripts/Makefile.am b/tests/zfs-tests/tests/perf/scripts/Makefile.am
new file mode 100644
index 000000000000..f0d45e1fbdcc
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/scripts/Makefile.am
@@ -0,0 +1,2 @@
+pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/perf/scripts
+dist_pkgdata_SCRIPTS = prefetch_io.sh
diff --git a/tests/zfs-tests/tests/perf/scripts/prefetch_io.sh b/tests/zfs-tests/tests/perf/scripts/prefetch_io.sh
new file mode 100755
index 000000000000..b8d8ae8859da
--- /dev/null
+++ b/tests/zfs-tests/tests/perf/scripts/prefetch_io.sh
@@ -0,0 +1,82 @@
+#!/usr/bin/env bash
+
+#
+# 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 Intel, Corp.
+#
+
+#
+# Linux platform placeholder for collecting prefetch I/O stats
+# TBD if we can add additional kstats to achieve the desired results
+#
+
+zfs_kstats="/proc/spl/kstat/zfs"
+
+function get_prefetch_ios
+{
+ typeset -l data_misses=`awk '$1 == "prefetch_data_misses" \
+ { print $3 }' $zfs_kstats/arcstats`
+ typeset -l metadata_misses=`awk '$1 == "prefetch_metadata_misses" \
+ { print $3 }' $zfs_kstats/arcstats`
+ typeset -l total_misses=$(( $data_misses + $metadata_misses ))
+
+ echo $total_misses
+}
+
+function get_prefetched_demand_reads
+{
+ typeset -l demand_reads=`awk '$1 == "demand_hit_predictive_prefetch" \
+ { print $3 }' $zfs_kstats/arcstats`
+
+ echo $demand_reads
+}
+
+function get_async_upgrade_sync
+{
+ typeset -l sync_wait=`awk '$1 == "async_upgrade_sync" \
+ { print $3 }' $zfs_kstats/arcstats`
+
+ echo $sync_wait
+}
+
+if [ $# -ne 2 ]
+then
+ echo "Usage: `basename $0` <poolname> interval" >&2
+ exit 1
+fi
+
+poolname=$1
+interval=$2
+prefetch_ios=$(get_prefetch_ios)
+prefetched_demand_reads=$(get_prefetched_demand_reads)
+async_upgrade_sync=$(get_async_upgrade_sync)
+
+while true
+do
+ new_prefetch_ios=$(get_prefetch_ios)
+ printf "%u\n%-24s\t%u\n" $(date +%s) "prefetch_ios" \
+ $(( $new_prefetch_ios - $prefetch_ios ))
+ prefetch_ios=$new_prefetch_ios
+
+ new_prefetched_demand_reads=$(get_prefetched_demand_reads)
+ printf "%-24s\t%u\n" "prefetched_demand_reads" \
+ $(( $new_prefetched_demand_reads - $prefetched_demand_reads ))
+ prefetched_demand_reads=$new_prefetched_demand_reads
+
+ new_async_upgrade_sync=$(get_async_upgrade_sync)
+ printf "%-24s\t%u\n" "async_upgrade_sync" \
+ $(( $new_async_upgrade_sync - $async_upgrade_sync ))
+ async_upgrade_sync=$new_async_upgrade_sync
+
+ sleep $interval
+done
diff --git a/tests/zfs-tests/tests/stress/Makefile.am b/tests/zfs-tests/tests/stress/Makefile.am
new file mode 100644
index 000000000000..741f85085609
--- /dev/null
+++ b/tests/zfs-tests/tests/stress/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS =