1#!/bin/ksh -p
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
15#
16
17. $STF_SUITE/include/libtest.shlib
18. $STF_SUITE/tests/functional/cli_root/zpool_split/zpool_split.cfg
19. $STF_SUITE/include/math.shlib
20
21#
22# DESCRIPTION:
23# 'zpool split' should only work on mirrors. Every other VDEV layout is not
24# supported.
25#
26# STRATEGY:
27# Create pools with various VDEV layouts and verify only mirrors can be split
28#
29
30verify_runnable "both"
31
32function cleanup
33{
34	destroy_pool $TESTPOOL
35	destroy_pool $TESTPOOL2
36	rm -fd $FILEDEV_PREFIX* $altroot
37}
38
39#
40# Given a vdev type generate a pool configuration which can be immediately
41# used as "zpool create $poolname $config" or "zpool add $poolname $config".
42# Supported vdev types are:
43#  "d" - single disk
44#  "t" - stripe
45#  "m" - mirror
46# "m3" - 3-way mirror
47# "z1" - raidz1
48# "z2" - raidz2
49# "z3" - raidz3
50#  "s" - spare
51#  "l" - log
52# "ll" - mirrored log
53#  "c" - cache
54#  "sc" - special class
55#
56function pool_config # <vdev-type>
57{
58	typeset config=""
59	typeset -A disks
60	disks[d]="d1"
61	disks[t]="t1 t2"
62	disks[m]="m1 m2"
63	disks[m3]="m1 m2 m3"
64	disks[z1]="z1 z2"
65	disks[z2]="z1 z2 z3"
66	disks[z3]="z1 z2 z3 z4"
67	disks[s]="s1"
68	disks[l]="l1"
69	disks[ll]="l1 l2"
70	disks[c]="c1"
71	disks[sc]="sc1 sc2"
72	case $1 in
73	d|t) # single disk or stripe
74		vdev='' ;;
75	m|m3) # 2-way or 3-way mirror
76		vdev='mirror';;
77	z1) # raidz1
78		vdev='raidz1';;
79	z2) # raidz2
80		vdev='raidz2';;
81	z3) # raidz3
82		vdev='raidz3';;
83	s) # spare
84		vdev='spare';;
85	l) # log
86		vdev='log';;
87	ll) # mirrored log
88		vdev='log mirror';;
89	c) # cache
90		vdev='cache';;
91	sc) # mirrored special class
92		vdev='special mirror';;
93	*)
94		log_fail "setup_pool: unsupported vdev type '$1'"
95	esac
96	config="$vdev"
97	for tok in ${disks[$1]}; do
98		filedev="$FILEDEV_PREFIX-$tok"
99		# if $filedev exists we are requesting the same vdev type twice
100		# in a row (eg. pool of striped mirrors): add a random suffix.
101		while [[ -f $filedev ]]; do
102			filedev="$filedev.$RANDOM"
103		done
104		truncate -s $SPA_MINDEVSIZE "$filedev"
105		config="$config $filedev"
106	done
107	echo "$config"
108}
109
110log_assert "'zpool split' should work only on mirror VDEVs"
111log_onexit cleanup
112
113# "good" and "bad" pool layouts
114# first token is always used with "zpool create"
115# second to last tokens, if any, are used with "zpool add"
116typeset -a goodconfs=("m" "m l" "m s" "m c" "m m" "m3" "m3 m3" "m m3 l s c" "m m sc")
117typeset -a badconfs=("d" "z1" "z2" "z3" "m d" "m3 d" "m z1" "m z2" "m z3")
118typeset FILEDEV_PREFIX="$TEST_BASE_DIR/filedev"
119typeset altroot="$TESTDIR/altroot-$TESTPOOL2"
120
121# Create pools with various VDEV layouts and verify only mirrors can be split
122for config in "${goodconfs[@]}"
123do
124	create_config="${config%% *}"
125	add_config="$(awk '{$1=""; print $0}' <<< $config)"
126	log_must zpool create $TESTPOOL $(pool_config $create_config)
127	for vdev in $add_config; do
128		log_must zpool add -f $TESTPOOL $(pool_config $vdev)
129	done
130	log_must zpool split -R $altroot $TESTPOOL $TESTPOOL2
131	log_must poolexists $TESTPOOL2
132	log_must test "$(get_pool_prop 'altroot' $TESTPOOL2)" == "$altroot"
133	cleanup
134done
135
136# Every other pool layout should *not* be splittable
137for config in "${badconfs[@]}"
138do
139	create_config="${config%% *}"
140	add_config="$(awk '{$1=""; print $0}' <<< $config)"
141	log_must zpool create $TESTPOOL $(pool_config $create_config)
142	for vdev in $add_config; do
143		log_must zpool add -f $TESTPOOL $(pool_config $vdev)
144	done
145	log_mustnot zpool split -R $altroot $TESTPOOL $TESTPOOL2
146	log_mustnot poolexists $TESTPOOL2
147	cleanup
148done
149
150log_pass "'zpool split' works only on mirror VDEVs"
151