1# vim: filetype=sh 2# 3# CDDL HEADER START 4# 5# The contents of this file are subject to the terms of the 6# Common Development and Distribution License (the "License"). 7# You may not use this file except in compliance with the License. 8# 9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10# or http://www.opensolaris.org/os/licensing. 11# See the License for the specific language governing permissions 12# and limitations under the License. 13# 14# When distributing Covered Code, include this CDDL HEADER in each 15# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16# If applicable, add the following below this CDDL HEADER, with the 17# fields enclosed by brackets "[]" replaced with your own identifying 18# information: Portions Copyright [yyyy] [name of copyright owner] 19# 20# CDDL HEADER END 21# 22 23# 24# Copyright 2009 Sun Microsystems, Inc. All rights reserved. 25# Use is subject to license terms. 26# 27# ident "@(#)reservation.kshlib 1.3 09/01/12 SMI" 28# 29 30# 31# Function to set the reservation property of a dataset to 32# 'none' and verify that it is correctly set using both the 33# "normal" 'zfs get reservation' and the '-p' option which 34# gives a numerical value. 35# 36function zero_reservation 37{ 38 typeset resv_val 39 dataset=$1 40 41 log_must $ZFS set reservation=none $dataset 42 log_must $ZFS set refreservation=none $dataset 43 44 resv_val=`$ZFS get -H refreservation $dataset | awk '{print $3}'` 45 if [[ $? -ne 0 ]]; then 46 log_fail "Unable to get reservation prop on $dataset" 47 elif [[ $resv_val != "none" ]]; then 48 log_fail "Reservation not 'none' ($resv_val) as expected" 49 fi 50 51 52 resv_val=`$ZFS get -pH refreservation $dataset | awk '{print $3}'` 53 if [[ $? -ne 0 ]]; then 54 log_fail "Unable to get reservation prop on $dataset" 55 elif [[ $resv_val -ne 0 ]]; then 56 log_fail "Reservation not 0 ($resv_val) as expected" 57 fi 58 59 return 0 60} 61 62# 63# Utility function to see if two values are within a certain specified 64# limit of each other. Used primarily to check that a dataset's parent 65# is correctly accounting for space used/available. Need this function as 66# currently there is some slop in the way space is accounted (i.e. can't 67# do a direct comparison). 68# 69function within_limits 70{ 71 typeset -l valA=$1 72 typeset -l valB=$2 73 typeset -l delta=$3 74 75 if (( valA <= valB )); then 76 if (( (valB - valA) <= delta )); then 77 return 0 78 fi 79 elif (( valB <= valA )); then 80 if (( (valA - valB) <= delta )); then 81 return 0 82 fi 83 fi 84 85 return 1 86} 87 88# 89# Function to create and mount multiple filesystems. The filesystem 90# will be named according to the name specified with a suffix value 91# taken from the loop counter. 92# 93function create_multiple_fs # num_fs base_fs_name base_mnt_name 94{ 95 typeset -i iter=0 96 typeset -i count=$1 97 typeset FS_NAME=$2 98 typeset MNT_NAME=$3 99 100 while (( $iter < $count )); do 101 log_must $ZFS create ${FS_NAME}$iter 102 log_must $ZFS set mountpoint=${MNT_NAME}$iter ${FS_NAME}$iter 103 (( iter = iter + 1 )) 104 done 105} 106 107# 108# This function compute the largest volume size which is multiple of volume 109# block size (default 8K) and not greater than the largest expected volsize. 110# 111# $1 The largest expected volume size. 112# $2 The volume block size 113# 114function floor_volsize #<largest_volsize> [volblksize] 115{ 116 typeset -l largest_volsize=$1 117 typeset -l volblksize=${2:-8192} 118 119 if (( largest_volsize < volblksize )); then 120 log_fail "The largest_volsize must be greater than volblksize." 121 fi 122 typeset -l real_volsize 123 typeset -l n 124 125 (( n = largest_volsize / volblksize )) 126 (( largest_volsize = volblksize * n )) 127 128 print $largest_volsize 129} 130 131# 132# Simple function to get the expected reservation for a ZVOL given the 133# volume size, block size, and number of copies. 134# 135# NB: This routine must be kept in sync with the ZFS library function 136# libzfs_dataset.c:zvol_volsize_to_reservation(). Refer to that function 137# for the logic behind the calculations. 138# 139function zvol_volsize_to_reservation 140{ 141 typeset resv_val 142 typeset nblocks 143 typeset numdb 144 typeset volsize=$1 145 typeset volblocksize=$2 146 typeset ncopies=$3 147 typeset ncopies_bp 148 typeset DN_MAX_INDBLKSHIFT=17 149 typeset SPA_BLKPTRSHIFT=7 150 typeset SPA_DVAS_PER_BP=3 151 typeset DVAS_PER_BP 152 typeset DNODES_PER_LEVEL_SHIFT 153 typeset DNODES_PER_LEVEL 154 typeset DN_MAX_INDBLKS 155 156 (( DNODES_PER_LEVEL_SHIFT = DN_MAX_INDBLKSHIFT - SPA_BLKPTRSHIFT )) 157 (( DNODES_PER_LEVEL = 1 << DNODES_PER_LEVEL_SHIFT )) 158 (( DN_MAX_INDBLKS = 1 << DN_MAX_INDBLKSHIFT )) 159 160 resv_val=$volsize 161 (( nblocks = volsize / volblocksize )) 162 numdb=7 163 while (( nblocks > 1 )); do 164 (( nblocks = nblocks + DNODES_PER_LEVEL - 1 )) 165 (( nblocks = nblocks / DNODES_PER_LEVEL )) 166 (( numdb = numdb + nblocks )) 167 done 168 (( ncopies_bp = ncopies + 1 )) 169 DVAS_PER_BP=$(min $SPA_DVAS_PER_BP $ncopies_bp) 170 (( numdb = numdb * DVAS_PER_BP )) 171 (( resv_val = volsize * ncopies )) 172 (( numdb = numdb * DN_MAX_INDBLKS )) 173 (( resv_val = resv_val + numdb )) 174 175 $ECHO $resv_val 176 return 0 177} 178 179