7194 Reservation tests do not properly calculate reservation size
[unleashed.git] / usr / src / test / zfs-tests / tests / functional / reservation / reservation.shlib
blobd0a9b384ecbbe48899dd3077b6f7f48a00cb0e38
2 # CDDL HEADER START
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.
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.
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]
19 # CDDL HEADER END
23 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 # Use is subject to license terms.
28 # Copyright (c) 2013, 2016 by Delphix. All rights reserved.
31 . $STF_SUITE/tests/functional/reservation/reservation.cfg
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.
39 function zero_reservation
41         typeset resv_val
42         dataset=$1
44         log_must $ZFS set reservation=none $dataset
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
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
61         return 0
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).
71 function within_limits
73         typeset -l valA=$1
74         typeset -l valB=$2
75         typeset -l delta=$3
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
87         return 1
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.
95 function create_multiple_fs # num_fs base_fs_name base_mnt_name
97         typeset -i iter=0
98         typeset -i count=$1
99         typeset FS_NAME=$2
100         typeset MNT_NAME=$3
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
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.
113 # $1 The largest expected volume size.
114 # $2 The volume block size
116 function floor_volsize #<largest_volsize> [volblksize]
118         typeset -l largest_volsize=$1
119         typeset -l volblksize=${2:-8192}
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
127         ((n = largest_volsize / volblksize))
128         ((largest_volsize = volblksize * n))
130         print $largest_volsize
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.
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.
142 function volsize_to_reservation
144         typeset vol=$1
145         typeset -i volsize=$2
147         typeset -i DN_MAX_INDBLKSHIFT=17
148         typeset -i SPA_BLKPTRSHIFT=7
149         typeset -i SPA_DVAS_PER_BP=3
151         typeset -i DNODES_PER_LEVEL_SHIFT=$((DN_MAX_INDBLKSHIFT - \
152             SPA_BLKPTRSHIFT))
153         typeset -i DNODES_PER_LEVEL=$((1 << $DNODES_PER_LEVEL_SHIFT))
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))
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
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
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().
186 function largest_volsize_from_pool
188         typeset pool=$1
189         typeset -i poolsize=$(get_prop available $pool)
190         typeset -i volsize=$poolsize
191         typeset -i nvolsize
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