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