1#!/bin/ksh -p
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright (c) 2021 by Delphix. All rights reserved.
15#
16
17# DESCRIPTION
18# Verify zfs destroy test for clones with livelists that contain
19# dedup blocks. This test is a baseline regression test created
20# to ensure that past bugs that we've encountered between dedup
21# and the livelist logic don't resurface.
22
23# STRATEGY
24# 1. Create a clone from a test filesystem and enable dedup.
25# 2. Write some data and create a livelist.
26# 3. Copy the data within the clone to create dedup blocks.
27# 4. Remove some of the dedup data to create multiple free
28#    entries for the same block pointers.
29# 5. Process all the livelist entries by destroying the clone.
30
31. $STF_SUITE/include/libtest.shlib
32. $STF_SUITE/tests/functional/cli_root/zfs_destroy/zfs_destroy_common.kshlib
33
34function cleanup
35{
36	log_must zfs destroy -Rf $TESTPOOL/$TESTFS1
37	# Reset the minimum percent shared to 75
38	set_tunable32 LIVELIST_MIN_PERCENT_SHARED $ORIGINAL_MIN_SHARED
39}
40
41function test_dedup
42{
43	# Set a small percent shared threshold so the livelist is not disabled
44	set_tunable32 LIVELIST_MIN_PERCENT_SHARED 10
45	clone_dataset $TESTFS1 snap $TESTCLONE
46
47	# Enable dedup
48	log_must zfs set dedup=on $TESTPOOL/$TESTCLONE
49
50	# Create some data to be deduped
51	log_must dd if=/dev/urandom of="/$TESTPOOL/$TESTCLONE/data" bs=512 count=10k
52
53	# Create dedup blocks
54	# Note: We sync before and after so all dedup blocks belong to the
55	#       same TXG, otherwise they won't look identical to the livelist
56	#       iterator due to their logical birth TXG being different.
57	sync_pool $TESTPOOL
58	log_must cp /$TESTPOOL/$TESTCLONE/data /$TESTPOOL/$TESTCLONE/data-dup-0
59	log_must cp /$TESTPOOL/$TESTCLONE/data /$TESTPOOL/$TESTCLONE/data-dup-1
60	log_must cp /$TESTPOOL/$TESTCLONE/data /$TESTPOOL/$TESTCLONE/data-dup-2
61	log_must cp /$TESTPOOL/$TESTCLONE/data /$TESTPOOL/$TESTCLONE/data-dup-3
62	sync_pool $TESTPOOL
63	check_livelist_exists $TESTCLONE
64
65	# Introduce "double frees"
66	#   We want to introduce consecutive FREEs of the same block as this
67	#   was what triggered past panics.
68	# Note: Similarly to the previouys step we sync before and after our
69	#       our deletions so all the entries end up in the same TXG.
70	sync_pool $TESTPOOL
71	log_must rm /$TESTPOOL/$TESTCLONE/data-dup-2
72	log_must rm /$TESTPOOL/$TESTCLONE/data-dup-3
73	sync_pool $TESTPOOL
74	check_livelist_exists $TESTCLONE
75
76	log_must zfs destroy $TESTPOOL/$TESTCLONE
77	check_livelist_gone
78}
79
80ORIGINAL_MIN_SHARED=$(get_tunable LIVELIST_MIN_PERCENT_SHARED)
81
82log_onexit cleanup
83# You might think that setting compression=off for $TESTFS1 would be
84# sufficient. You would be mistaken.
85# You need compression=off for whatever the parent of $TESTFS1 is,
86# and $TESTFS1.
87log_must zfs set compression=off $TESTPOOL
88log_must zfs create $TESTPOOL/$TESTFS1
89log_must mkfile 5m /$TESTPOOL/$TESTFS1/atestfile
90log_must zfs snapshot $TESTPOOL/$TESTFS1@snap
91test_dedup
92
93log_must zfs inherit compression $TESTPOOL
94
95log_pass "Clone's livelist processes dedup blocks as expected."
96