]>
Commit | Line | Data |
---|---|---|
6bb24f4d BB |
1 | # |
2 | # CDDL HEADER START | |
3 | # | |
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. | |
7 | # | |
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. | |
12 | # | |
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] | |
18 | # | |
19 | # CDDL HEADER END | |
20 | # | |
21 | ||
22 | # | |
23 | # Copyright 2009 Sun Microsystems, Inc. All rights reserved. | |
24 | # Use is subject to license terms. | |
25 | # | |
26 | ||
27 | # | |
28 | # Copyright (c) 2013, 2015 by Delphix. All rights reserved. | |
29 | # | |
30 | ||
31 | . $STF_SUITE/include/libtest.shlib | |
32 | . $STF_SUITE/tests/functional/rsend/rsend.cfg | |
33 | ||
34 | # | |
35 | # Set up test model which includes various datasets | |
36 | # | |
37 | # @final | |
38 | # @snapB | |
39 | # @init | |
40 | # | | |
41 | # ______ pclone | |
42 | # | / | |
43 | # |@psnap | |
44 | # || @final | |
45 | # ||@final @final @snapC | |
46 | # ||@snapC @snapC @snapB | |
47 | # ||@snapA @snapB @snapA | |
48 | # ||@init @init @init | |
49 | # ||| | | | |
50 | # $pool -------- $FS ------- fs1 ------- fs2 | |
51 | # \ \\_____ \ | | |
52 | # vol vol \____ \ @fsnap | |
53 | # | | \ \ \ | |
54 | # @init @vsnap | ------------ fclone | |
55 | # @snapA @init \ | | | |
56 | # @final @snapB \ | @init | |
57 | # @snapC vclone @snapA | |
58 | # @final | @final | |
59 | # @init | |
60 | # @snapC | |
61 | # @final | |
62 | # | |
63 | # $1 pool name | |
64 | # | |
65 | function setup_test_model | |
66 | { | |
67 | typeset pool=$1 | |
68 | ||
69 | log_must $ZFS create -p $pool/$FS/fs1/fs2 | |
70 | ||
71 | log_must $ZFS snapshot $pool@psnap | |
72 | log_must $ZFS clone $pool@psnap $pool/pclone | |
73 | ||
74 | if is_global_zone ; then | |
75 | log_must $ZFS create -V 16M $pool/vol | |
76 | log_must $ZFS create -V 16M $pool/$FS/vol | |
47dfff3b | 77 | block_device_wait |
6bb24f4d BB |
78 | |
79 | log_must $ZFS snapshot $pool/$FS/vol@vsnap | |
80 | log_must $ZFS clone $pool/$FS/vol@vsnap $pool/$FS/vclone | |
47dfff3b | 81 | block_device_wait |
6bb24f4d BB |
82 | fi |
83 | ||
84 | log_must snapshot_tree $pool/$FS/fs1/fs2@fsnap | |
85 | log_must $ZFS clone $pool/$FS/fs1/fs2@fsnap $pool/$FS/fs1/fclone | |
86 | log_must $ZFS snapshot -r $pool@init | |
87 | ||
88 | log_must snapshot_tree $pool@snapA | |
89 | log_must snapshot_tree $pool@snapC | |
90 | log_must snapshot_tree $pool/pclone@snapB | |
91 | log_must snapshot_tree $pool/$FS@snapB | |
92 | log_must snapshot_tree $pool/$FS@snapC | |
93 | log_must snapshot_tree $pool/$FS/fs1@snapA | |
94 | log_must snapshot_tree $pool/$FS/fs1@snapB | |
95 | log_must snapshot_tree $pool/$FS/fs1@snapC | |
96 | log_must snapshot_tree $pool/$FS/fs1/fclone@snapA | |
97 | ||
98 | if is_global_zone ; then | |
99 | log_must $ZFS snapshot $pool/vol@snapA | |
100 | log_must $ZFS snapshot $pool/$FS/vol@snapB | |
101 | log_must $ZFS snapshot $pool/$FS/vol@snapC | |
102 | log_must $ZFS snapshot $pool/$FS/vclone@snapC | |
103 | fi | |
104 | ||
105 | log_must $ZFS snapshot -r $pool@final | |
106 | ||
107 | return 0 | |
108 | } | |
109 | ||
110 | # | |
111 | # Cleanup the BACKDIR and given pool content and all the sub datasets | |
112 | # | |
113 | # $1 pool name | |
114 | # | |
115 | function cleanup_pool | |
116 | { | |
117 | typeset pool=$1 | |
118 | log_must $RM -rf $BACKDIR/* | |
119 | ||
120 | if is_global_zone ; then | |
121 | log_must $ZFS destroy -Rf $pool | |
122 | else | |
123 | typeset list=$($ZFS list -H -r -t filesystem,snapshot,volume -o name $pool) | |
124 | for ds in $list ; do | |
125 | if [[ $ds != $pool ]] ; then | |
126 | if datasetexists $ds ; then | |
127 | log_must $ZFS destroy -Rf $ds | |
128 | fi | |
129 | fi | |
130 | done | |
131 | fi | |
132 | ||
133 | typeset mntpnt=$(get_prop mountpoint $pool) | |
134 | if ! ismounted $pool ; then | |
135 | # Make sure mountpoint directory is empty | |
136 | if [[ -d $mntpnt ]]; then | |
137 | log_must $RM -rf $mntpnt/* | |
138 | fi | |
139 | ||
140 | log_must $ZFS mount $pool | |
141 | fi | |
142 | if [[ -d $mntpnt ]]; then | |
143 | log_must $RM -rf $mntpnt/* | |
144 | fi | |
145 | ||
146 | return 0 | |
147 | } | |
148 | ||
149 | # | |
150 | # Detect if the given two filesystems have same sub-datasets | |
151 | # | |
152 | # $1 source filesystem | |
153 | # $2 destination filesystem | |
154 | # | |
155 | function cmp_ds_subs | |
156 | { | |
157 | typeset src_fs=$1 | |
158 | typeset dst_fs=$2 | |
159 | ||
160 | $ZFS list -r -H -t filesystem,snapshot,volume -o name $src_fs > $BACKDIR/src1 | |
161 | $ZFS list -r -H -t filesystem,snapshot,volume -o name $dst_fs > $BACKDIR/dst1 | |
162 | ||
163 | eval $SED -e 's:^$src_fs:PREFIX:g' < $BACKDIR/src1 > $BACKDIR/src | |
164 | eval $SED -e 's:^$dst_fs:PREFIX:g' < $BACKDIR/dst1 > $BACKDIR/dst | |
165 | ||
166 | $DIFF $BACKDIR/src $BACKDIR/dst | |
167 | typeset -i ret=$? | |
168 | ||
169 | $RM -f $BACKDIR/src $BACKDIR/dst $BACKDIR/src1 $BACKDIR/dst1 | |
170 | ||
171 | return $ret | |
172 | } | |
173 | ||
174 | # | |
175 | # Compare all the directores and files in two filesystems | |
176 | # | |
177 | # $1 source filesystem | |
178 | # $2 destination filesystem | |
179 | # | |
180 | function cmp_ds_cont | |
181 | { | |
182 | typeset src_fs=$1 | |
183 | typeset dst_fs=$2 | |
184 | ||
185 | typeset srcdir dstdir | |
186 | srcdir=$(get_prop mountpoint $src_fs) | |
187 | dstdir=$(get_prop mountpoint $dst_fs) | |
188 | ||
189 | $DIFF -r $srcdir $dstdir > /dev/null 2>&1 | |
190 | echo $? | |
191 | } | |
192 | ||
193 | # | |
194 | # Compare the given two dataset properties | |
195 | # | |
196 | # $1 dataset 1 | |
197 | # $2 dataset 2 | |
198 | # | |
199 | function cmp_ds_prop | |
200 | { | |
201 | typeset dtst1=$1 | |
202 | typeset dtst2=$2 | |
203 | ||
47dfff3b | 204 | for item in "type" "origin" "volblocksize" "aclinherit" "acltype" \ |
6bb24f4d | 205 | "atime" "canmount" "checksum" "compression" "copies" "devices" \ |
50c957f7 | 206 | "dnodesize" "exec" "quota" "readonly" "recordsize" "reservation" \ |
47dfff3b | 207 | "setuid" "snapdir" "version" "volsize" "xattr" "zoned" \ |
6bb24f4d BB |
208 | "mountpoint"; |
209 | do | |
210 | $ZFS get -H -o property,value,source $item $dtst1 >> \ | |
211 | $BACKDIR/dtst1 | |
212 | $ZFS get -H -o property,value,source $item $dtst2 >> \ | |
213 | $BACKDIR/dtst2 | |
214 | done | |
215 | ||
216 | eval $SED -e 's:$dtst1:PREFIX:g' < $BACKDIR/dtst1 > $BACKDIR/dtst1 | |
217 | eval $SED -e 's:$dtst2:PREFIX:g' < $BACKDIR/dtst2 > $BACKDIR/dtst2 | |
218 | ||
219 | $DIFF $BACKDIR/dtst1 $BACKDIR/dtst2 | |
220 | typeset -i ret=$? | |
221 | ||
222 | $RM -f $BACKDIR/dtst1 $BACKDIR/dtst2 | |
223 | ||
224 | return $ret | |
225 | ||
226 | } | |
227 | ||
228 | # | |
229 | # Random create directories and files | |
230 | # | |
231 | # $1 directory | |
232 | # | |
233 | function random_tree | |
234 | { | |
235 | typeset dir=$1 | |
236 | ||
237 | if [[ -d $dir ]]; then | |
238 | $RM -rf $dir | |
239 | fi | |
240 | $MKDIR -p $dir | |
241 | typeset -i ret=$? | |
242 | ||
243 | typeset -i nl nd nf | |
244 | ((nl = RANDOM % 6 + 1)) | |
245 | ((nd = RANDOM % 3 )) | |
246 | ((nf = RANDOM % 5 )) | |
247 | $MKTREE -b $dir -l $nl -d $nd -f $nf | |
248 | ((ret |= $?)) | |
249 | ||
250 | return $ret | |
251 | } | |
252 | ||
253 | # | |
254 | # Put data in filesystem and take snapshot | |
255 | # | |
256 | # $1 snapshot name | |
257 | # | |
258 | function snapshot_tree | |
259 | { | |
260 | typeset snap=$1 | |
261 | typeset ds=${snap%%@*} | |
262 | typeset type=$(get_prop "type" $ds) | |
263 | ||
264 | typeset -i ret=0 | |
265 | if [[ $type == "filesystem" ]]; then | |
266 | typeset mntpnt=$(get_prop mountpoint $ds) | |
267 | ((ret |= $?)) | |
268 | ||
269 | if ((ret == 0)) ; then | |
270 | eval random_tree $mntpnt/${snap##$ds} | |
271 | ((ret |= $?)) | |
272 | fi | |
273 | fi | |
274 | ||
275 | if ((ret == 0)) ; then | |
276 | $ZFS snapshot $snap | |
277 | ((ret |= $?)) | |
278 | fi | |
279 | ||
280 | return $ret | |
281 | } | |
282 | ||
283 | # | |
284 | # Destroy the given snapshot and stuff | |
285 | # | |
286 | # $1 snapshot | |
287 | # | |
288 | function destroy_tree | |
289 | { | |
290 | typeset -i ret=0 | |
291 | typeset snap | |
292 | for snap in "$@" ; do | |
293 | $ZFS destroy $snap | |
294 | ret=$? | |
295 | ||
296 | typeset ds=${snap%%@*} | |
297 | typeset type=$(get_prop "type" $ds) | |
298 | if [[ $type == "filesystem" ]]; then | |
299 | typeset mntpnt=$(get_prop mountpoint $ds) | |
300 | ((ret |= $?)) | |
301 | ||
302 | if ((ret != 0)); then | |
303 | $RM -r $mntpnt/$snap | |
304 | ((ret |= $?)) | |
305 | fi | |
306 | fi | |
307 | ||
308 | if ((ret != 0)); then | |
309 | return $ret | |
310 | fi | |
311 | done | |
312 | ||
313 | return 0 | |
314 | } | |
315 | ||
316 | # | |
317 | # Get all the sub-datasets of give dataset with specific suffix | |
318 | # | |
319 | # $1 Given dataset | |
320 | # $2 Suffix | |
321 | # | |
322 | function getds_with_suffix | |
323 | { | |
324 | typeset ds=$1 | |
325 | typeset suffix=$2 | |
326 | ||
327 | typeset list=$($ZFS list -r -H -t filesystem,snapshot,volume -o name $ds \ | |
328 | | $GREP "$suffix$") | |
329 | ||
330 | $ECHO $list | |
331 | } | |
332 | ||
333 | # | |
334 | # Output inherited properties whitch is edited for file system | |
335 | # | |
336 | function fs_inherit_prop | |
337 | { | |
338 | typeset fs_prop | |
339 | if is_global_zone ; then | |
340 | fs_prop=$($ZFS inherit 2>&1 | \ | |
341 | $AWK '$2=="YES" && $3=="YES" {print $1}') | |
342 | if ! is_te_enabled ; then | |
343 | fs_prop=$(echo $fs_prop | $GREP -v "mlslabel") | |
344 | fi | |
345 | else | |
346 | fs_prop=$($ZFS inherit 2>&1 | \ | |
347 | $AWK '$2=="YES" && $3=="YES" {print $1}'| | |
348 | $EGREP -v "devices|mlslabel|sharenfs|sharesmb|zoned") | |
349 | fi | |
350 | ||
351 | $ECHO $fs_prop | |
352 | } | |
353 | ||
354 | # | |
355 | # Output inherited properties for volume | |
356 | # | |
357 | function vol_inherit_prop | |
358 | { | |
359 | $ECHO "checksum readonly" | |
360 | } | |
361 | ||
362 | # | |
363 | # Get the destination dataset to compare | |
364 | # | |
365 | function get_dst_ds | |
366 | { | |
367 | typeset srcfs=$1 | |
368 | typeset dstfs=$2 | |
369 | ||
370 | # | |
371 | # If the srcfs is not pool | |
372 | # | |
373 | if ! $ZPOOL list $srcfs > /dev/null 2>&1 ; then | |
374 | eval dstfs="$dstfs/${srcfs#*/}" | |
375 | fi | |
376 | ||
377 | $ECHO $dstfs | |
378 | } | |
379 | ||
380 | # | |
381 | # Make test files | |
382 | # | |
383 | # $1 Number of files to create | |
384 | # $2 Maximum file size | |
385 | # $3 File ID offset | |
386 | # $4 File system to create the files on | |
387 | # | |
388 | function mk_files | |
389 | { | |
390 | nfiles=$1 | |
391 | maxsize=$2 | |
392 | file_id_offset=$3 | |
393 | fs=$4 | |
394 | ||
395 | for ((i=0; i<$nfiles; i=i+1)); do | |
396 | $DD if=/dev/urandom \ | |
397 | of=/$fs/file-$maxsize-$((i+$file_id_offset)) \ | |
47dfff3b | 398 | bs=$((($RANDOM * $RANDOM % ($maxsize - 1)) + 1)) \ |
6bb24f4d BB |
399 | count=1 >/dev/null 2>&1 || log_fail \ |
400 | "Failed to create /$fs/file-$maxsize-$((i+$file_id_offset))" | |
401 | done | |
402 | $ECHO Created $nfiles files of random sizes up to $maxsize bytes | |
403 | } | |
404 | ||
405 | # | |
406 | # Remove test files | |
407 | # | |
408 | # $1 Number of files to remove | |
409 | # $2 Maximum file size | |
410 | # $3 File ID offset | |
411 | # $4 File system to remove the files from | |
412 | # | |
413 | function rm_files | |
414 | { | |
415 | nfiles=$1 | |
416 | maxsize=$2 | |
417 | file_id_offset=$3 | |
418 | fs=$4 | |
419 | ||
420 | for ((i=0; i<$nfiles; i=i+1)); do | |
421 | $RM -f /$fs/file-$maxsize-$((i+$file_id_offset)) | |
422 | done | |
423 | $ECHO Removed $nfiles files of random sizes up to $maxsize bytes | |
424 | } | |
425 | ||
426 | # | |
427 | # Mess up file contents | |
428 | # | |
429 | # $1 The file path | |
430 | # | |
431 | function mess_file | |
432 | { | |
433 | file=$1 | |
434 | ||
435 | filesize=$($STAT -c '%s' $file) | |
436 | offset=$(($RANDOM * $RANDOM % $filesize)) | |
437 | if (($RANDOM % 7 <= 1)); then | |
438 | # | |
439 | # We corrupt 2 bytes to minimize the chance that we | |
440 | # write the same value that's already there. | |
441 | # | |
442 | log_must eval "$DD if=/dev/urandom of=$file conv=notrunc " \ | |
47dfff3b | 443 | "bs=1 count=2 seek=$offset >/dev/null 2>&1" |
6bb24f4d BB |
444 | else |
445 | log_must $TRUNCATE -s $offset $file | |
446 | fi | |
447 | } | |
448 | ||
449 | # | |
450 | # Diff the send/receive filesystems | |
451 | # | |
452 | # $1 The sent filesystem | |
453 | # $2 The received filesystem | |
454 | # | |
455 | function file_check | |
456 | { | |
457 | sendfs=$1 | |
458 | recvfs=$2 | |
459 | ||
460 | if [[ -d /$recvfs/.zfs/snapshot/a && -d \ | |
461 | /$sendfs/.zfs/snapshot/a ]]; then | |
462 | $DIFF -r /$recvfs/.zfs/snapshot/a /$sendfs/.zfs/snapshot/a | |
463 | [[ $? -eq 0 ]] || log_fail "Differences found in snap a" | |
464 | fi | |
465 | if [[ -d /$recvfs/.zfs/snapshot/b && -d \ | |
466 | /$sendfs/.zfs/snapshot/b ]]; then | |
467 | $DIFF -r /$recvfs/.zfs/snapshot/b /$sendfs/.zfs/snapshot/b | |
468 | [[ $? -eq 0 ]] || log_fail "Differences found in snap b" | |
469 | fi | |
470 | } | |
471 | ||
472 | # | |
473 | # Resume test helper | |
474 | # | |
475 | # $1 The ZFS send command | |
476 | # $2 The filesystem where the streams are sent | |
477 | # $3 The receive filesystem | |
478 | # | |
479 | function resume_test | |
480 | { | |
481 | sendcmd=$1 | |
482 | streamfs=$2 | |
483 | recvfs=$3 | |
484 | ||
485 | stream_num=1 | |
486 | log_must eval "$sendcmd >/$streamfs/$stream_num" | |
487 | ||
488 | for ((i=0; i<2; i=i+1)); do | |
489 | mess_file /$streamfs/$stream_num | |
490 | log_mustnot $ZFS recv -sv $recvfs </$streamfs/$stream_num | |
491 | stream_num=$((stream_num+1)) | |
492 | ||
493 | token=$($ZFS get -Hp -o value receive_resume_token $recvfs) | |
494 | log_must eval "$ZFS send -v -t $token >/$streamfs/$stream_num" | |
495 | [[ -f /$streamfs/$stream_num ]] || \ | |
496 | log_fail "NO FILE /$streamfs/$stream_num" | |
497 | done | |
498 | log_must $ZFS recv -sv $recvfs </$streamfs/$stream_num | |
499 | } | |
500 | ||
501 | # | |
502 | # Setup filesystems for the resumable send/receive tests | |
503 | # | |
504 | # $1 The pool to set up with the "send" filesystems | |
505 | # $2 The pool for receive | |
506 | # | |
507 | function test_fs_setup | |
508 | { | |
509 | sendpool=$1 | |
510 | recvpool=$2 | |
511 | ||
512 | sendfs=$sendpool/sendfs | |
513 | recvfs=$recvpool/recvfs | |
514 | streamfs=$sendpool/stream | |
515 | ||
516 | if datasetexists $recvfs; then | |
517 | log_must $ZFS destroy -r $recvfs | |
518 | fi | |
519 | if datasetexists $sendfs; then | |
520 | log_must $ZFS destroy -r $sendfs | |
521 | fi | |
522 | if $($ZFS create -o compress=lz4 $sendfs); then | |
523 | mk_files 1000 256 0 $sendfs & | |
524 | mk_files 1000 131072 0 $sendfs & | |
525 | mk_files 100 1048576 0 $sendfs & | |
526 | mk_files 10 10485760 0 $sendfs & | |
527 | mk_files 1 104857600 0 $sendfs & | |
47dfff3b | 528 | wait |
6bb24f4d BB |
529 | log_must $ZFS snapshot $sendfs@a |
530 | ||
531 | rm_files 200 256 0 $sendfs & | |
532 | rm_files 200 131072 0 $sendfs & | |
533 | rm_files 20 1048576 0 $sendfs & | |
534 | rm_files 2 10485760 0 $sendfs & | |
47dfff3b | 535 | wait |
6bb24f4d BB |
536 | |
537 | mk_files 400 256 0 $sendfs & | |
538 | mk_files 400 131072 0 $sendfs & | |
539 | mk_files 40 1048576 0 $sendfs & | |
540 | mk_files 4 10485760 0 $sendfs & | |
47dfff3b | 541 | wait |
6bb24f4d BB |
542 | |
543 | log_must $ZFS snapshot $sendfs@b | |
544 | log_must eval "$ZFS send -v $sendfs@a >/$sendpool/initial.zsend" | |
545 | log_must eval "$ZFS send -v -i @a $sendfs@b " \ | |
546 | ">/$sendpool/incremental.zsend" | |
547 | fi | |
548 | ||
549 | if datasetexists $streamfs; then | |
550 | log_must $ZFS destroy -r $streamfs | |
551 | fi | |
552 | log_must $ZFS create -o compress=lz4 $sendpool/stream | |
553 | } |