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 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 2007 Sun Microsystems, Inc.  All rights reserved.
25# Copyright (c) 2017 by Lawrence Livermore National Security, LLC.
26# Use is subject to license terms.
27#
28
29. $STF_SUITE/tests/functional/slog/slog.kshlib
30
31#
32# DESCRIPTION:
33#	Verify slogs are replayed correctly for a volume.
34#
35#	The general idea is to build up an intent log from a bunch of
36#	diverse user commands without actually committing them to the
37#	file system.  Then generate checksums for files and volume,
38#	replay the intent log and verify the checksums.
39#
40#	To enable this automated testing of the intent log some minimal
41#	support is required of the file system.  In particular, a
42#	"freeze" command is required to flush the in-flight transactions;
43#	to stop the actual committing of transactions; and to ensure no
44#	deltas are discarded. All deltas past a freeze point are kept
45#	for replay and comparison later. Here is the flow:
46#
47# STRATEGY:
48#	1. Create an empty volume (TESTVOL), set sync=always, and format
49#	   it with an ext4 filesystem and mount it.
50#	2. Freeze TESTVOL.
51#	3. Create log records of various types to verify replay.
52#	4. Generate checksums for all ext4 files.
53#	5. Unmount filesystem and export the pool
54#	   <at this stage TESTVOL is empty again and unfrozen, and the
55#	   intent log contains a complete set of deltas to replay it>
56#	6. Import TESTVOL <which replays the intent log> and mount it.
57#	7. Verify the stored checksums
58#
59
60verify_runnable "global"
61
62VOLUME=$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL
63MNTPNT=$TESTDIR/$TESTVOL
64FSTYPE=none
65
66function cleanup_volume
67{
68	if ismounted $MNTPNT $FSTYPE; then
69		log_must umount $MNTPNT
70		rmdir $MNTPNT
71	fi
72
73	rm -f $TESTDIR/checksum.files
74
75	cleanup
76}
77
78log_assert "Replay of intent log succeeds."
79log_onexit cleanup_volume
80log_must setup
81
82#
83# 1. Create an empty volume (TESTVOL), set sync=always, and format
84#    it with an ext4 filesystem and mount it.
85#
86log_must zpool create $TESTPOOL ${DISKS%% *}
87log_must zfs create -V 128M $TESTPOOL/$TESTVOL
88log_must zfs set compression=on $TESTPOOL/$TESTVOL
89log_must zfs set sync=always $TESTPOOL/$TESTVOL
90log_must mkdir -p $TESTDIR
91block_device_wait
92if is_linux; then
93	# ext4 only on Linux
94	log_must new_fs -t ext4 -v $VOLUME
95	log_must mkdir -p $MNTPNT
96	log_must mount -o discard $VOLUME $MNTPNT
97	FSTYPE=ext4
98	log_must rmdir $MNTPNT/lost+found
99else
100	log_must new_fs $VOLUME
101	log_must mkdir -p $MNTPNT
102	log_must mount $VOLUME $MNTPNT
103	FSTYPE=$NEWFS_DEFAULT_FS
104fi
105log_must zpool sync
106
107#
108# 2. Freeze TESTVOL
109#
110log_must zpool freeze $TESTPOOL
111
112#
113# 3. Create log records of various types to verify replay.
114#
115
116# TX_WRITE
117log_must dd if=/dev/urandom of=$MNTPNT/latency-8k bs=8k count=1 oflag=sync
118log_must dd if=/dev/urandom of=$MNTPNT/latency-128k bs=128k count=1 oflag=sync
119
120# TX_WRITE (WR_INDIRECT)
121log_must zfs set logbias=throughput $TESTPOOL/$TESTVOL
122log_must dd if=/dev/urandom of=$MNTPNT/throughput-8k bs=8k count=1
123log_must dd if=/dev/urandom of=$MNTPNT/throughput-128k bs=128k count=1
124
125# TX_WRITE (holes)
126log_must dd if=/dev/urandom of=$MNTPNT/holes bs=128k count=8
127log_must dd if=/dev/zero of=$MNTPNT/holes bs=128k count=2 seek=2 conv=notrunc
128
129if is_linux; then
130	# TX_TRUNCATE
131	if fallocate --punch-hole 2>&1 | grep -q "unrecognized option"; then
132		log_note "fallocate(1) does not support --punch-hole"
133	else
134		log_must dd if=/dev/urandom of=$MNTPNT/discard bs=128k count=16
135		log_must fallocate --punch-hole -l 128K -o 512K $MNTPNT/discard
136		log_must fallocate --punch-hole -l 512K -o 1M $MNTPNT/discard
137	fi
138fi
139
140#
141# 4. Generate checksums for all ext4 files.
142#
143typeset checksum=$(cat $MNTPNT/* | sha256digest)
144
145#
146# 5. Unmount filesystem and export the pool
147#
148# At this stage TESTVOL is initialized with the random data and frozen,
149# the intent log contains a complete set of deltas to replay.
150#
151log_must umount $MNTPNT
152
153log_note "Verify transactions to replay:"
154log_must zdb -iv $TESTPOOL/$TESTVOL
155
156log_must zpool export $TESTPOOL
157
158#
159# 6. Import TESTPOOL, the intent log is replayed during minor creation.
160#
161# Import the pool to unfreeze it and claim log blocks.  It has to be
162# `zpool import -f` because we can't write a frozen pool's labels!
163#
164log_must zpool import -f $TESTPOOL
165block_device_wait
166log_must mount $VOLUME $MNTPNT
167
168#
169# 7. Verify the stored checksums
170#
171log_note "Verify current block usage:"
172log_must zdb -bcv $TESTPOOL
173
174log_note "Verify checksums"
175typeset checksum1=$(cat $MNTPNT/* | sha256digest)
176[[ "$checksum1" == "$checksum" ]] || \
177    log_fail "checksum mismatch ($checksum1 != $checksum)"
178
179log_pass "Replay of intent log succeeds."
180