xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_clone/zfs_clone_010_pos.ksh (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1#!/bin/ksh
2# SPDX-License-Identifier: CDDL-1.0
3#
4# CDDL HEADER START
5#
6# This file and its contents are supplied under the terms of the
7# Common Development and Distribution License ("CDDL"), version 1.0.
8# You may only use this file in accordance with the terms of version
9# 1.0 of the CDDL.
10
11# A full copy of the text of the CDDL should have accompanied this
12# source.  A copy of the CDDL is also available via the Internet at
13# http://www.illumos.org/license/CDDL.
14#
15# CDDL HEADER END
16#
17
18#
19# Copyright (c) 2012, 2016 by Delphix. All rights reserved.
20#
21
22. $STF_SUITE/include/libtest.shlib
23
24#
25# DESCRIPTION:
26#	Verify 'zfs list -t all -o name,origin,clones' prints the correct
27#	clone information
28#
29# STRATEGY:
30#	1. Create datasets
31#	2. Create recursive snapshots and their clones
32#	3. Verify zfs clones property displays right information for different
33#	   cases
34#
35
36verify_runnable "both"
37
38function local_cleanup
39{
40	typeset -i i=1
41	for ds in $datasets; do
42                datasetexists $ds/$TESTCLONE.$i && \
43		    destroy_dataset $ds/$TESTCLONE.$i -rf
44                datasetexists $ds && destroy_dataset $ds -Rf
45		((i=i+1))
46	done
47}
48
49# Set up filesystem with clones
50function setup_ds
51{
52	typeset -i i=1
53	# create nested datasets
54	log_must zfs create -p $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3
55
56	# verify dataset creation
57	for ds in $datasets; do
58		datasetexists $ds || log_fail "Create $ds dataset fail."
59	done
60
61	# create recursive nested snapshot
62	log_must zfs snapshot -r $TESTPOOL/$TESTFS1@snap
63	for ds in $datasets; do
64		datasetexists $ds@snap || \
65		    log_fail "Create $ds@snap snapshot fail."
66	done
67	for ds in $datasets; do
68		for fs in $datasets; do
69			log_must zfs clone $ds@snap $fs/$TESTCLONE.$i
70		done
71		((i=i+1))
72	done
73}
74
75# Verify clone list
76function verify_clones
77{
78	typeset -i no_clones=$1
79	typeset unexpected=$2
80	typeset clone_snap=$3
81	typeset -i i=1
82	for ds in $datasets; do
83		if [[ -n $clone_snap ]]; then
84			clone_snap=/$TESTCLONE.$i
85		fi
86		snapshot=$(echo "$names" | grep $ds$clone_snap@snap)
87		actual_clone=$(zfs list -t all -o clones $snapshot | tail -1)
88		save=$IFS
89		IFS=','
90		typeset -a clones=()
91		for token in $actual_clone; do
92			clones=( "${clones[@]}" "$token" )
93		done
94		IFS=$save
95		[[ ${#clones[*]} -ne $no_clones ]] && \
96		    log_fail "$snapshot has unexpected number of clones" \
97		        " ${#clones[*]}"
98		expected_clone=""
99		unexpected_clone=""
100		if [[ $unexpected -eq 1 ]]; then
101			for fs in $datasets; do
102				if [[ $fs == $ds ]]; then
103					if [[ -z $clone_snap ]]; then
104						unexpected_clone=$fs/$TESTCLONE.$i
105						(for match in ${clones[@]};do
106						[[ $match != $unexpected_clone ]] && \
107						    exit 0; done) || log_fail \
108					            "Unexpected clones of the snapshot"
109					else
110						expected_clone=$fs
111						unexpected_clone=$fs/$TESTCLONE.$i
112						(for match in ${clones[@]};do
113						[[ $match == $expected_clone ]] && \
114						    [[ $match != $unexpected_clone ]] \
115						    && exit 0; done) || log_fail \
116						    "Unexpected clones of the snapshot"
117					fi
118				else
119					expected_clone=$fs/$TESTCLONE.$i
120					(for match in ${clones[@]};do
121					[[ $match == $expected_clone ]] && \
122					    exit 0; done) || log_fail \
123					    "Unexpected clones of the snapshot"
124				fi
125			done
126		else
127			for fs in $datasets; do
128				expected_clone=$fs/$TESTCLONE.$i
129				(for match in ${clones[@]};do
130				[[ $match == $expected_clone ]] && exit 0; \
131				    done) || log_fail "Unexpected clones" \
132				    " of the snapshot"
133			done
134		fi
135		((i=i+1))
136	done
137}
138
139
140log_onexit local_cleanup
141datasets="$TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS2
142    $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3"
143
144typeset -a d_clones
145typeset -a deferred_snaps
146typeset -i i
147log_must setup_ds
148
149log_note "Verify zfs clone property for multiple clones"
150names=$(zfs list -rt all -o name $TESTPOOL)
151log_must verify_clones 3 0
152
153log_note "verify clone property for clone deletion"
154i=1
155for ds in $datasets; do
156	log_must zfs destroy $ds/$TESTCLONE.$i
157	((i=i+1))
158done
159names=$(zfs list -rt all -o name $TESTPOOL)
160log_must verify_clones 2 1
161
162log_must local_cleanup
163log_must setup_ds
164
165log_note "verify zfs deferred destroy on clones property"
166names=$(zfs list -rt all -o name $TESTPOOL)
167for ds in $datasets; do
168	log_must zfs destroy -d $ds@snap
169	deferred_snaps=( "${deferred_snaps[@]}" "$ds@snap" )
170done
171log_must verify_clones 3 0
172
173log_note "verify zfs deferred destroy by destroying clones on clones property"
174d_clones=()
175i=1
176for ds in $datasets; do
177	for fs in $datasets; do
178		log_must zfs destroy $fs/$TESTCLONE.$i
179		d_clones=( "${d_clones[@]}" "$fs/$TESTCLONE.$i" )
180	done
181	((i=i+1))
182done
183names=$(zfs list -rtall -o name $TESTPOOL)
184for snap in ${deferred_snaps[@]}; do
185	status=$(echo "$names" | grep $snap)
186	[[ -z $status ]] || \
187	    log_fail "$snap exist after deferred destroy"
188done
189for dclone in ${d_clones[@]}; do
190	log_note "D CLONE = $dclone"
191	status=$(echo "$names" | grep $dclone)
192	[[ -z $status ]] || \
193	    log_fail "$dclone exist after deferred destroy"
194done
195
196log_must local_cleanup
197log_must setup_ds
198log_note "verify clone property for zfs promote"
199i=1
200for ds in $datasets; do
201	log_must zfs promote $ds/$TESTCLONE.$i
202	((i=i+1))
203done
204names=$(zfs list -rt all -o name,clones $TESTPOOL)
205log_must verify_clones 3 1 $TESTCLONE
206for ds in $datasets; do
207	log_must zfs promote $ds
208done
209log_must local_cleanup
210
211log_note "verify clone list truncated correctly"
212fs=$TESTPOOL/$TESTFS1
213xs=""; for i in {1..200}; do xs+="x"; done
214maxproplen=8192
215log_must zfs create $fs
216log_must zfs snapshot $fs@snap
217for (( i = 1; i <= (maxproplen / 200 + 1); i++ )); do
218	log_must zfs clone ${fs}@snap ${fs}/${TESTCLONE}${xs}.${i}
219done
220clone_list=$(zfs list -o clones $fs@snap)
221char_count=$(echo "$clone_list" | tail -1 | wc -c)
222[[ $char_count -eq $maxproplen ]] || \
223    log_fail "Clone list not truncated correctly. Unexpected character count" \
224        "$char_count"
225
226log_pass "'zfs list -o name,origin,clones prints the correct clone information."
227