1 # 2 # CDDL HEADER START 3 # 4 # The contents of this file are subject to the terms of the 5 # Common Development and Distribution License (the "License"). 6 # You may not use this file except in compliance with the License. 7 # 8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 # or http://www.opensolaris.org/os/licensing. 10 # See the License for the specific language governing permissions 11 # and limitations under the License. 12 # 13 # When distributing Covered Code, include this CDDL HEADER in each 14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 # If applicable, add the following below this CDDL HEADER, with the 16 # fields enclosed by brackets "[]" replaced with your own identifying 17 # information: Portions Copyright [yyyy] [name of copyright owner] 18 # 19 # CDDL HEADER END 20 # 21 22 # 23 # Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 # Use is subject to license terms. 25 # 26 27 # 28 # Copyright (c) 2013 by Delphix. All rights reserved. 29 # 30 31 . $STF_SUITE/tests/functional/reservation/reservation.cfg 32 33 # 34 # Function to set the reservation property of a dataset to 35 # 'none' and verify that it is correctly set using both the 36 # "normal" 'zfs get reservation' and the '-p' option which 37 # gives a numerical value. 38 # 39 function zero_reservation 40 { 41 typeset resv_val 42 dataset=$1 43 44 log_must $ZFS set reservation=none $dataset 45 46 resv_val=`$ZFS get -H reservation $dataset | awk '{print $3}'` 47 if [[ $? -ne 0 ]]; then 48 log_fail "Unable to get reservation prop on $dataset" 49 elif [[ $resv_val != "none" ]]; then 50 log_fail "Reservation not 'none' ($resv_val) as expected" 51 fi 52 53 54 resv_val=`$ZFS get -pH reservation $dataset | awk '{print $3}'` 55 if [[ $? -ne 0 ]]; then 56 log_fail "Unable to get reservation prop on $dataset" 57 elif [[ $resv_val -ne 0 ]]; then 58 log_fail "Reservation not 0 ($resv_val) as expected" 59 fi 60 61 return 0 62 } 63 64 # 65 # Utility function to see if two values are within a certain specified 66 # limit of each other. Used primarily to check that a dataset's parent 67 # is correctly accounting for space used/available. Need this function as 68 # currently there is some slop in the way space is accounted (i.e. can't 69 # do a direct comparison). 70 # 71 function within_limits 72 { 73 typeset -l valA=$1 74 typeset -l valB=$2 75 typeset -l delta=$3 76 77 if ((valA <= valB)); then 78 if (((valB - valA) <= delta)); then 79 return 0 80 fi 81 elif ((valB <= valA)); then 82 if (((valA - valB) <= delta)); then 83 return 0 84 fi 85 fi 86 87 return 1 88 } 89 90 # 91 # Function to create and mount multiple filesystems. The filesystem 92 # will be named according to the name specified with a suffix value 93 # taken from the loop counter. 94 # 95 function create_multiple_fs # num_fs base_fs_name base_mnt_name 96 { 97 typeset -i iter=0 98 typeset -i count=$1 99 typeset FS_NAME=$2 100 typeset MNT_NAME=$3 101 102 while (($iter < $count)); do 103 log_must $ZFS create ${FS_NAME}$iter 104 log_must $ZFS set mountpoint=${MNT_NAME}$iter ${FS_NAME}$iter 105 ((iter = iter + 1)) 106 done 107 } 108 109 # 110 # This function compute the largest volume size which is multiple of volume 111 # block size (default 8K) and not greater than the largest expected volsize. 112 # 113 # $1 The largest expected volume size. 114 # $2 The volume block size 115 # 116 function floor_volsize #<largest_volsize> [volblksize] 117 { 118 typeset -l largest_volsize=$1 119 typeset -l volblksize=${2:-8192} 120 121 if ((largest_volsize < volblksize)); then 122 log_fail "The largest_volsize must be greater than volblksize." 123 fi 124 typeset -l real_volsize 125 typeset -l n 126 127 ((n = largest_volsize / volblksize)) 128 ((largest_volsize = volblksize * n)) 129 130 print $largest_volsize 131 } 132 133 # 134 # This function is a copy of a function by the same name in libzfs_dataset.c 135 # Its purpose is to reserve additional space for volume metadata so volumes 136 # don't unexpectedly run out of room. 137 # 138 # Note: This function can be used to do an estimate for a volume that has not 139 # yet been created. In this case, $vol is not a volume, but rather a pool in 140 # which a volume is going to be created. In this case, use default properties. 141 # 142 function volsize_to_reservation 143 { 144 typeset vol=$1 145 typeset -i volsize=$2 146 147 typeset -i DN_MAX_INDBLKSHIFT=14 148 typeset -i SPA_BLKPTRSHIFT=7 149 typeset -i SPA_DVAS_PER_BP=3 150 151 typeset -i DNODES_PER_LEVEL_SHIFT=$((DN_MAX_INDBLKSHIFT - \ 152 SPA_BLKPTRSHIFT)) 153 typeset -i DNODES_PER_LEVEL=$((1 << $DNODES_PER_LEVEL_SHIFT)) 154 155 if ds_is_volume $vol; then 156 typeset -i ncopies=$(get_prop copies $vol) 157 typeset -i volblocksize=$(get_prop volblocksize $vol) 158 else 159 typeset -i ncopies=1 160 typeset -i volblocksize=8192 161 fi 162 typeset -i nblocks=$((volsize / volblocksize)) 163 164 typeset -i numdb=7 165 while ((nblocks > 1)); do 166 ((nblocks += DNODES_PER_LEVEL - 1)) 167 ((nblocks /= DNODES_PER_LEVEL)) 168 ((numdb += nblocks)) 169 done 170 171 ((numdb *= SPA_DVAS_PER_BP < ncopies + 1 ? SPA_DVAS_PER_BP : \ 172 ncopies + 1)) 173 ((volsize *= ncopies)) 174 ((numdb *= 1 << DN_MAX_INDBLKSHIFT)) 175 ((volsize += numdb)) 176 echo $volsize 177 } 178 179 # 180 # This function takes a pool name as an argument, and returns the largest (give 181 # or take some slop) -V value that can be used to create a volume in that pool. 182 # This is necessary because during volume creation, a reservation is created 183 # that will be larger than the value specified with -V, and potentially larger 184 # than the available space in the pool. See volsize_to_reservation(). 185 # 186 function largest_volsize_from_pool 187 { 188 typeset pool=$1 189 typeset -i poolsize=$(get_prop available $pool) 190 typeset -i volsize=$poolsize 191 typeset -i nvolsize 192 193 while :; do 194 # knock 50M off the volsize each time through 195 ((volsize -= 50 * 1024 * 1024)) 196 nvolsize=$(volsize_to_reservation $pool $volsize) 197 nvolsize=$(floor_volsize $nvolsize) 198 ((nvolsize < poolsize)) && break 199 done 200 echo $volsize 201 }