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# 28# Function to set the reservation property of a dataset to 29# 'none' and verify that it is correctly set using both the 30# "normal" 'zfs get reservation' and the '-p' option which 31# gives a numerical value. 32# 33function zero_reservation 34{ 35 typeset resv_val 36 dataset=$1 37 38 log_must $ZFS set reservation=none $dataset 39 log_must $ZFS set refreservation=none $dataset 40 41 resv_val=`$ZFS get -H refreservation $dataset | awk '{print $3}'` 42 if [[ $? -ne 0 ]]; then 43 log_fail "Unable to get reservation prop on $dataset" 44 elif [[ $resv_val != "none" ]]; then 45 log_fail "Reservation not 'none' ($resv_val) as expected" 46 fi 47 48 49 resv_val=`$ZFS get -pH refreservation $dataset | awk '{print $3}'` 50 if [[ $? -ne 0 ]]; then 51 log_fail "Unable to get reservation prop on $dataset" 52 elif [[ $resv_val -ne 0 ]]; then 53 log_fail "Reservation not 0 ($resv_val) as expected" 54 fi 55 56 return 0 57} 58 59# 60# Utility function to see if two values are within a certain specified 61# limit of each other. Used primarily to check that a dataset's parent 62# is correctly accounting for space used/available. Need this function as 63# currently there is some slop in the way space is accounted (i.e. can't 64# do a direct comparison). 65# 66function within_limits 67{ 68 typeset -l valA=$1 69 typeset -l valB=$2 70 typeset -l delta=$3 71 72 if (( valA <= valB )); then 73 if (( (valB - valA) <= delta )); then 74 return 0 75 fi 76 elif (( valB <= valA )); then 77 if (( (valA - valB) <= delta )); then 78 return 0 79 fi 80 fi 81 82 return 1 83} 84 85# 86# Function to create and mount multiple filesystems. The filesystem 87# will be named according to the name specified with a suffix value 88# taken from the loop counter. 89# 90function create_multiple_fs # num_fs base_fs_name base_mnt_name 91{ 92 typeset -i iter=0 93 typeset -i count=$1 94 typeset FS_NAME=$2 95 typeset MNT_NAME=$3 96 97 while (( $iter < $count )); do 98 log_must $ZFS create ${FS_NAME}$iter 99 log_must $ZFS set mountpoint=${MNT_NAME}$iter ${FS_NAME}$iter 100 (( iter = iter + 1 )) 101 done 102} 103 104# 105# This function compute the largest volume size which is multiple of volume 106# block size (default 8K) and not greater than the largest expected volsize. 107# 108# $1 The largest expected volume size. 109# $2 The volume block size 110# 111function floor_volsize #<largest_volsize> [volblksize] 112{ 113 typeset -l largest_volsize=$1 114 typeset -l volblksize=${2:-8192} 115 116 if (( largest_volsize < volblksize )); then 117 log_fail "The largest_volsize must be greater than volblksize." 118 fi 119 typeset -l real_volsize 120 typeset -l n 121 122 (( n = largest_volsize / volblksize )) 123 (( largest_volsize = volblksize * n )) 124 125 print $largest_volsize 126} 127 128# 129# Simple function to get the expected reservation for a ZVOL given the 130# volume size, block size, and number of copies. 131# 132# NB: This routine must be kept in sync with the ZFS library function 133# libzfs_dataset.c:zvol_volsize_to_reservation(). Refer to that function 134# for the logic behind the calculations. 135# 136function zvol_volsize_to_reservation 137{ 138 typeset resv_val 139 typeset nblocks 140 typeset numdb 141 typeset volsize=$1 142 typeset volblocksize=$2 143 typeset ncopies=$3 144 typeset ncopies_bp 145 typeset DN_MAX_INDBLKSHIFT=17 146 typeset SPA_BLKPTRSHIFT=7 147 typeset SPA_DVAS_PER_BP=3 148 typeset DVAS_PER_BP 149 typeset DNODES_PER_LEVEL_SHIFT 150 typeset DNODES_PER_LEVEL 151 typeset DN_MAX_INDBLKS 152 153 (( DNODES_PER_LEVEL_SHIFT = DN_MAX_INDBLKSHIFT - SPA_BLKPTRSHIFT )) 154 (( DNODES_PER_LEVEL = 1 << DNODES_PER_LEVEL_SHIFT )) 155 (( DN_MAX_INDBLKS = 1 << DN_MAX_INDBLKSHIFT )) 156 157 resv_val=$volsize 158 (( nblocks = volsize / volblocksize )) 159 numdb=7 160 while (( nblocks > 1 )); do 161 (( nblocks = nblocks + DNODES_PER_LEVEL - 1 )) 162 (( nblocks = nblocks / DNODES_PER_LEVEL )) 163 (( numdb = numdb + nblocks )) 164 done 165 (( ncopies_bp = ncopies + 1 )) 166 DVAS_PER_BP=$(min $SPA_DVAS_PER_BP $ncopies_bp) 167 (( numdb = numdb * DVAS_PER_BP )) 168 (( resv_val = volsize * ncopies )) 169 (( numdb = numdb * DN_MAX_INDBLKS )) 170 (( resv_val = resv_val + numdb )) 171 172 $ECHO $resv_val 173 return 0 174} 175 176