1#!/bin/ksh -p
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 https://opensource.org/licenses/CDDL-1.0.
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 (c) 2007, Sun Microsystems Inc. All rights reserved.
25# Copyright (c) 2013, 2016, Delphix. All rights reserved.
26# Copyright (c) 2019, Kjeld Schouten-Lebbing. All Rights Reserved.
27# Use is subject to license terms.
28#
29
30. $STF_SUITE/include/properties.shlib
31. $STF_SUITE/include/libtest.shlib
32
33#
34# DESCRIPTION:
35# With 'compression' set, a file with non-power-of-2 blocksize storage space
36# can be freed as will normally.
37#
38# STRATEGY:
39#	1. Set 'compression' or 'compress' to on or lzjb
40#	2. Set different recordsize with ZFS filesystem
41#	3. Repeatedly using 'randfree_file' to create a file and then free its
42#	   storage space with different range, the system should work normally.
43#
44
45verify_runnable "both"
46
47function cleanup
48{
49	rm -f $TESTDIR/*
50}
51
52function create_free_testing #<file size> <file>
53{
54	typeset -i fsz=$1
55	typeset file=$2
56	typeset -i start=0
57	typeset -i len=0
58	typeset -i dist=0
59
60	for start in 0 `expr $RANDOM % $fsz`
61	do
62		(( dist = fsz - start ))
63		for len in `expr $RANDOM % $dist` $dist \
64			`expr $start + $dist`; do
65
66			# Zero length results in EINVAL for fallocate(2).
67			if is_linux; then
68				if (( len == 0 )); then
69					continue
70				fi
71			fi
72
73			log_must randfree_file -l fsz -s $start \
74				-n $len $file
75			[[ -e $file ]] && \
76				log_must rm -f $file
77		done
78	done
79}
80
81
82log_assert "Creating non-power-of-2 blocksize file and freeing the file \
83	storage space at will should work normally with compression setting"
84log_onexit cleanup
85
86fs=$TESTPOOL/$TESTFS
87single_blk_file=$TESTDIR/singleblkfile.$$
88multi_blk_file=$TESTDIR/multiblkfile.$$
89typeset -i blksize=512
90typeset -i fsize=0
91typeset -i avail=0
92typeset -i blknum=0
93
94for propname in "compression" "compress"
95do
96	for value in "${compress_prop_vals[@]:1}"
97	do
98		log_must zfs set compression=$value $fs
99		real_val=$(get_prop $propname $fs)
100		if [[ $value == "gzip-6" ]]; then
101			value="gzip"
102		fi
103		[[ $real_val != $value ]] && \
104			log_fail "Set property $propname=$value failed."
105
106		(( blksize = 512 ))
107		while (( blksize <= 131072 )); do
108			log_must zfs set recordsize=$blksize $fs
109
110			# doing single block testing
111			(( fsize = $RANDOM ))
112			if (( fsize > blksize )); then
113				(( fsize = fsize % blksize ))
114			fi
115			if (( (fsize % 2) == 0 )); then
116				#make sure fsize is non-power-of-2
117				(( fsize = fsize + 1 ))
118			fi
119			create_free_testing $fsize $single_blk_file
120
121			# doing multiple blocks testing
122			avail=$(get_prop available $fs)
123			(( blknum = avail / blksize ))
124			# we just test <10 multi-blocks to limit testing time
125			(( blknum = blknum % 9 ))
126			while (( blknum < 2 )); do
127				(( blknum = blknum + $RANDOM % 9 ))
128			done
129			if (( (blknum % 2) == 0 )); then
130				(( blknum = blknum + 1 )) # keep blknum as odd
131			fi
132			(( fsize = blknum * blksize ))
133			create_free_testing $fsize $multi_blk_file
134
135			(( blksize = blksize * 2 ))
136		done
137	done
138done
139
140log_pass "Creating and freeing non-power-of-2 blocksize file work as expected."
141