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# Use is subject to license terms.
26#
27
28. $STF_SUITE/tests/functional/slog/slog.kshlib
29
30#
31# DESCRIPTION:
32#	Verify slogs are replayed correctly.  This test is a direct
33#	adaptation of the ziltest.sh script for the ZFS Test Suite.
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 copy the file system, replay the intent
38#	log and compare the file system and the copy.
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 file system (TESTFS)
49#	2. Freeze TESTFS
50#	3. Run various user commands that create files, directories and ACLs
51#	4. Copy TESTFS to temporary location (TESTDIR/copy)
52#	5. Unmount filesystem
53#	   <at this stage TESTFS is empty again and unfrozen, and the
54#	   intent log contains a complete set of deltas to replay it>
55#	6. Remount TESTFS <which replays the intent log>
56#	7. Compare TESTFS against the TESTDIR/copy
57#
58
59verify_runnable "global"
60
61log_assert "Replay of intent log succeeds."
62log_onexit cleanup
63log_must setup
64
65#
66# 1. Create an empty file system (TESTFS)
67#
68log_must zpool create $TESTPOOL $VDEV log mirror $LDEV
69log_must zfs set compression=on $TESTPOOL
70log_must zfs create $TESTPOOL/$TESTFS
71
72#
73# This dd command works around an issue where ZIL records aren't created
74# after freezing the pool unless a ZIL header already exists. Create a file
75# synchronously to force ZFS to write one out.
76#
77log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/sync \
78    conv=fdatasync,fsync bs=1 count=1
79
80#
81# 2. Freeze TESTFS
82#
83log_must zpool freeze $TESTPOOL
84
85#
86# 3. Run various user commands that create files, directories and ACLs
87#
88
89# TX_CREATE
90log_must touch /$TESTPOOL/$TESTFS/a
91
92# TX_RENAME
93log_must mv /$TESTPOOL/$TESTFS/a /$TESTPOOL/$TESTFS/b
94
95# TX_SYMLINK
96log_must touch /$TESTPOOL/$TESTFS/c
97log_must ln -s /$TESTPOOL/$TESTFS/c /$TESTPOOL/$TESTFS/d
98
99# TX_LINK
100log_must touch /$TESTPOOL/$TESTFS/e
101log_must ln /$TESTPOOL/$TESTFS/e /$TESTPOOL/$TESTFS/f
102
103# TX_MKDIR
104log_must mkdir /$TESTPOOL/$TESTFS/dir_to_delete
105
106# TX_RMDIR
107log_must rmdir /$TESTPOOL/$TESTFS/dir_to_delete
108
109# Create a simple validation payload
110log_must mkdir -p $TESTDIR
111log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/payload \
112    oflag=sync bs=1k count=8
113typeset checksum=$(sha256digest /$TESTPOOL/$TESTFS/payload)
114
115# TX_WRITE (small file with ordering)
116log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/small_file \
117    oflag=sync bs=1k count=1
118log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/small_file \
119    oflag=sync bs=512 count=1
120
121# TX_CREATE, TX_MKDIR, TX_REMOVE, TX_RMDIR
122log_must cp -R /usr/share/dict /$TESTPOOL/$TESTFS
123log_must rm -rf /$TESTPOOL/$TESTFS/dict
124
125# TX_SETATTR
126log_must touch /$TESTPOOL/$TESTFS/setattr
127log_must chmod 567 /$TESTPOOL/$TESTFS/setattr
128if is_freebsd; then
129	log_must chgrp wheel /$TESTPOOL/$TESTFS/setattr
130else
131	log_must chgrp root /$TESTPOOL/$TESTFS/setattr
132fi
133log_must touch -cm -t 201311271200 /$TESTPOOL/$TESTFS/setattr
134
135# TX_TRUNCATE (to zero)
136log_must mkfile 4k /$TESTPOOL/$TESTFS/truncated_file
137log_must truncate -s 0 /$TESTPOOL/$TESTFS/truncated_file
138
139# TX_WRITE (large file)
140log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/large \
141    oflag=sync bs=128k count=64
142
143# Write zeros, which compress to holes, in the middle of a file
144log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.1 \
145    oflag=sync bs=128k count=8
146log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.1 \
147    oflag=sync bs=128k count=2
148
149log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.2 \
150    oflag=sync bs=128k count=8
151log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.2 \
152    oflag=sync bs=128k count=2 seek=2
153
154log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.3 \
155    oflag=sync bs=128k count=8
156log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.3 \
157    oflag=sync bs=128k count=2 seek=2 conv=notrunc
158
159# TX_MKXATTR
160log_must mkdir /$TESTPOOL/$TESTFS/xattr.dir
161log_must touch /$TESTPOOL/$TESTFS/xattr.file
162log_must set_xattr fileattr HelloWorld /$TESTPOOL/$TESTFS/xattr.dir
163log_must set_xattr tmpattr HelloWorld /$TESTPOOL/$TESTFS/xattr.dir
164log_must rm_xattr fileattr /$TESTPOOL/$TESTFS/xattr.dir
165
166log_must set_xattr fileattr HelloWorld /$TESTPOOL/$TESTFS/xattr.file
167log_must set_xattr tmpattr HelloWorld /$TESTPOOL/$TESTFS/xattr.file
168log_must rm_xattr tmpattr /$TESTPOOL/$TESTFS/xattr.file
169
170# TX_WRITE, TX_LINK, TX_REMOVE
171# Make sure TX_REMOVE won't affect TX_WRITE if file is not destroyed
172log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/link_and_unlink \
173    oflag=sync bs=128k count=8
174log_must ln /$TESTPOOL/$TESTFS/link_and_unlink \
175   /$TESTPOOL/$TESTFS/link_and_unlink.link
176log_must rm /$TESTPOOL/$TESTFS/link_and_unlink.link
177
178#
179# 4. Copy TESTFS to temporary location (TESTDIR/copy)
180#
181log_must mkdir -p $TESTDIR/copy
182log_must cp -a /$TESTPOOL/$TESTFS/* $TESTDIR/copy/
183
184#
185# 5. Unmount filesystem and export the pool
186#
187# At this stage TESTFS is empty again and frozen, the intent log contains
188# a complete set of deltas to replay.
189#
190log_must zfs unmount /$TESTPOOL/$TESTFS
191
192log_note "Verify transactions to replay:"
193log_must zdb -iv $TESTPOOL/$TESTFS
194
195log_must zpool export $TESTPOOL
196
197#
198# 6. Remount TESTFS <which replays the intent log>
199#
200# Import the pool to unfreeze it and claim log blocks.  It has to be
201# `zpool import -f` because we can't write a frozen pool's labels!
202#
203log_must zpool import -f -d $VDIR $TESTPOOL
204
205#
206# 7. Compare TESTFS against the TESTDIR/copy
207#
208log_note "Verify current block usage:"
209log_must zdb -bcv $TESTPOOL
210
211log_note "Verify copy of xattrs:"
212log_must ls_xattr /$TESTPOOL/$TESTFS/xattr.dir
213log_must ls_xattr /$TESTPOOL/$TESTFS/xattr.file
214
215log_note "Verify working set diff:"
216log_must diff -r /$TESTPOOL/$TESTFS $TESTDIR/copy
217
218log_note "Verify file checksum:"
219typeset checksum1=$(sha256digest /$TESTPOOL/$TESTFS/payload)
220[[ "$checksum1" == "$checksum" ]] || \
221    log_fail "checksum mismatch ($checksum1 != $checksum)"
222
223log_pass "Replay of intent log succeeds."
224