|
root / base / usr / src / test / zfs-tests / tests / longevity
longevity Plain Text 278 lines 7.0 KB
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright (c) 2017 by Delphix. All rights reserved.
#

include $(SRC)/Makefile.master

ROOTOPTPKG = $(ROOT)/opt/zfs-tests
TARGETDIR = $(ROOTOPTPKG)/tests/longevity

include $(SRC)/test/zfs-tests/Makefile.com
#!/usr/bin/ksh -p

#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source.  A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#

#
# Copyright (c) 2017 by Delphix. All rights reserved.
#

. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/pool_checkpoint/pool_checkpoint.kshlib

#
# DESCRIPTION:
#	Ensure that all levels of reserved slop space are
#	followed by ZFS.
#
# STRATEGY:
#	1. Create testpool with two filesystems
#	2. On the first filesystem create a big file that holds
#	   a large portion of the pool's space. Then overwrite it
#	   in such a way that if we free it after taking a
#	   checkpoint it will append a lot of small entries to
#	   the checkpoint's space map
#	3. Checkpoint the pool
#	4. On the second filesystem, create a file and keep writing
#	   to it until we hit the first level of reserved space
#	   (128M)
#	5. Then start adding properties to second filesystem until
#	   we hit the second level of reserved space (64M)
#	6. Destroy the first filesystem and wait until the async
#	   destroys of this operation hit the last level of
#	   reserved space (32M)
#	7. Attempt to destroy the second filesystem (should fail)
#	8. Discard the checkpoint
#

DISK="$(echo $DISKS | cut -d' ' -f1)"
DISKFS=$TESTPOOL/disks

NESTEDPOOL=nestedpool

FILEDISKSIZE=4g
FILEDISKLOCATION=/$DISKFS
FILEDISK=$FILEDISKLOCATION/dsk1

FS0=$NESTEDPOOL/fs0
FS1=$NESTEDPOOL/fs1

FS0FILE=/$FS0/file
FS1FILE=/$FS1/file

CKPOINTEDFILEBLOCKS=3200
NUMOVERWRITTENBLOCKS=$(($CKPOINTEDFILEBLOCKS * 1024 * 1024 / 512 / 2))

verify_runnable "global"

function test_cleanup
{
	log_must set_tunable64 zfs_async_block_max_blocks \
	    $(print "%llu" 0xffffffffffffffff)
	poolexists $NESTEDPOOL && destroy_pool $NESTEDPOOL
	log_must zpool destroy $TESTPOOL
}

function wait_until_extra_reserved
{
	#
	# Loop until we get from gigabytes to megabytes
	#
	size_range=$(zpool list | awk '{print $1,$4}' | \
	    grep $NESTEDPOOL | awk '{print $2}' | grep G)
	while [ "" != "$size_range" ]; do
		sleep 5
		size_range=$(zpool list | awk '{print $1,$4}' | \
		    grep $NESTEDPOOL | awk '{print $2}' | grep G)
	done


	#
	# Loop until we hit the 32M limit
	#
	free=$(zpool list | awk '{print $1,$4}' | \
	    grep $NESTEDPOOL | awk '{print $2}' | cut -d"M" -f1 | \
	    cut -d"." -f1)
	while (( free > 32 )); do
		sleep 5
		free=$(zpool list | awk '{print $1,$4}' | \
		    grep $NESTEDPOOL | awk '{print $2}' | cut -d"M" -f1 | \
		    cut -d"." -f1)
	done

	#
	# Even though we may have hit the 32M limit we
	# still need to wait to ensure that we are at
	# the stable state where async destroys are suspended.
	#
	sleep 300
}

log_must zpool create $TESTPOOL $DISK
log_onexit test_cleanup

log_must zfs create $DISKFS

log_must mkfile -n $FILEDISKSIZE $FILEDISK
log_must zpool create $NESTEDPOOL $FILEDISK
log_must zfs create -o recordsize=512 $FS0
log_must zfs create -o recordsize=512 $FS1


#
# Create a ~3.2G file and ensure it is
# synced to disk
#
log_must dd if=/dev/zero of=$FS0FILE bs=1M count=$CKPOINTEDFILEBLOCKS
log_must sync

# for debugging purposes
log_must zpool list $NESTEDPOOL

#
# Overwrite every second block of the file.
# The idea is to make long space map regions
# where we have subsequent entries that cycle
# between marked as ALLOCATED and FREE. This
# way we attempt to keep the space maps long
# and fragmented.
#
# So later, when there is a checkpoint and we
# destroy the filesystem, all of these entries
# should be copied over to the checkpoint's
# space map increasing capacity beyond the
# extra reserved slop space.
#
log_must dd if=/dev/zero of=$FS0FILE bs=512 ostride=2 \
    count=$NUMOVERWRITTENBLOCKS conv=notrunc

# for debugging purposes
log_must zpool list $NESTEDPOOL

log_must zpool checkpoint $NESTEDPOOL

#
# Keep writing to the pool until we get to
# the first slop space limit.
#
log_mustnot dd if=/dev/zero of=$FS1FILE bs=512

# for debugging purposes
log_must zpool list $NESTEDPOOL

#
# Keep adding properties to our second
# filesystem until we hit we hit the
# second slop space limit.
#
for i in {1..100}
do
	#
	# We use this nested loop logic to fit more
	# properties in one zfs command and reducing
	# the overhead caused by the number of times
	# we wait for a txg to sync (e.g. equal to the
	# number of times we execute zfs(8))
	#
	PROPERTIES=""
	for j in {1..100}
	do
		PROPVAL=$(dd if=/dev/urandom bs=6000 count=1 | base64 -w 0)
		PROP="user:prop-$i-$j=$PROPVAL"
		PROPERTIES="$PROPERTIES $PROP"
	done
	zfs set $PROPERTIES  $FS1 || break
	log_note "- setting properties: iteration $i out of 100 -"
done

for k in {1..100}
do
	#
	# In case we broke out of the loop above because we
	# couldn't fit 100 props in the space left, make sure
	# to fill up the space that's left by setting one property
	# at a time
	#
	PROPVAL=$(dd if=/dev/urandom bs=6000 count=1 | base64 -w 0)
	PROP="user:prop-extra-$k=$PROPVAL"
	zfs set $PROP $FS1 || break
done

# for debugging purposes
log_must zpool list $NESTEDPOOL

#
# By the time we are done with the loop above
# we should be getting ENOSPC for trying to add
# new properties. As a sanity check though, try
# again (this time with log_mustnot).
#
log_mustnot zfs set user:proptest="should fail!" $FS0
log_mustnot zfs set user:proptest="should fail!" $FS1

# for debugging purposes
log_must zpool list $NESTEDPOOL

#
# We are about to destroy the first filesystem,
# but we want to do so in a way that generates
# as many entries as possible in the vdev's
# checkpoint space map. Thus, we reduce the
# amount of checkpointed blocks that we "free"
# every txg.
#
log_must set_tunable64 zfs_async_block_max_blocks 10000

log_must zfs destroy $FS0

#
# Keep looping until we hit that point where
# we are at the last slop space limit (32.0M)
# and async destroys are suspended.
#
wait_until_extra_reserved

# for debugging purposes
log_must zpool list $NESTEDPOOL

#
# At this point we shouldn't be allowed to
# destroy anything.
#
log_mustnot zfs destroy $FS1

#
# The only operations that should be allowed
# is discarding the checkpoint.
#
log_must zpool checkpoint -d $NESTEDPOOL

wait_discard_finish $NESTEDPOOL

#
# Now that we have space again, we should be
# able to destroy that filesystem.
#
log_must zfs destroy $FS1

log_pass "All levels of slop space work as expected."