blob: 8954caa1c933f4056acf2b5bcecb6fea4dce8a0e [file] [log] [blame]
#!/bin/ksh -p
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
. $STF_SUITE/tests/functional/slog/slog.kshlib
#
# DESCRIPTION:
# Verify slogs are replayed correctly. This test is a direct
# adaptation of the ziltest.sh script for the ZFS Test Suite.
#
# The general idea is to build up an intent log from a bunch of
# diverse user commands without actually committing them to the
# file system. Then copy the file system, replay the intent
# log and compare the file system and the copy.
#
# To enable this automated testing of the intent log some minimal
# support is required of the file system. In particular, a
# "freeze" command is required to flush the in-flight transactions;
# to stop the actual committing of transactions; and to ensure no
# deltas are discarded. All deltas past a freeze point are kept
# for replay and comparison later. Here is the flow:
#
# STRATEGY:
# 1. Create an empty file system (TESTFS)
# 2. Freeze TESTFS
# 3. Run various user commands that create files, directories and ACLs
# 4. Copy TESTFS to temporary location (TESTDIR/copy)
# 5. Unmount filesystem
# <at this stage TESTFS is empty again and unfrozen, and the
# intent log contains a complete set of deltas to replay it>
# 6. Remount TESTFS <which replays the intent log>
# 7. Compare TESTFS against the TESTDIR/copy
#
verify_runnable "global"
log_assert "Replay of intent log succeeds."
log_onexit cleanup
log_must setup
#
# 1. Create an empty file system (TESTFS)
#
log_must zpool create $TESTPOOL $VDEV log mirror $LDEV
log_must zfs set compression=on $TESTPOOL
log_must zfs create $TESTPOOL/$TESTFS
#
# This dd command works around an issue where ZIL records aren't created
# after freezing the pool unless a ZIL header already exists. Create a file
# synchronously to force ZFS to write one out.
#
log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/sync \
conv=fdatasync,fsync bs=1 count=1
#
# 2. Freeze TESTFS
#
log_must zpool freeze $TESTPOOL
#
# 3. Run various user commands that create files, directories and ACLs
#
# TX_CREATE
log_must touch /$TESTPOOL/$TESTFS/a
# TX_RENAME
log_must mv /$TESTPOOL/$TESTFS/a /$TESTPOOL/$TESTFS/b
# TX_SYMLINK
log_must touch /$TESTPOOL/$TESTFS/c
log_must ln -s /$TESTPOOL/$TESTFS/c /$TESTPOOL/$TESTFS/d
# TX_LINK
log_must touch /$TESTPOOL/$TESTFS/e
log_must ln /$TESTPOOL/$TESTFS/e /$TESTPOOL/$TESTFS/f
# TX_MKDIR
log_must mkdir /$TESTPOOL/$TESTFS/dir_to_delete
# TX_RMDIR
log_must rmdir /$TESTPOOL/$TESTFS/dir_to_delete
# Create a simple validation payload
log_must mkdir -p $TESTDIR
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/payload bs=1k count=8
typeset checksum=$(sha256digest /$TESTPOOL/$TESTFS/payload)
# TX_WRITE (small file with ordering)
log_must mkfile 1k /$TESTPOOL/$TESTFS/small_file
log_must mkfile 512b /$TESTPOOL/$TESTFS/small_file
# TX_CREATE, TX_MKDIR, TX_REMOVE, TX_RMDIR
log_must cp -R /usr/share/dict /$TESTPOOL/$TESTFS
log_must rm -rf /$TESTPOOL/$TESTFS/dict
# TX_SETATTR
log_must touch /$TESTPOOL/$TESTFS/setattr
log_must chmod 567 /$TESTPOOL/$TESTFS/setattr
log_must chgrp root /$TESTPOOL/$TESTFS/setattr
log_must touch -cm -t 201311271200 /$TESTPOOL/$TESTFS/setattr
# TX_TRUNCATE (to zero)
log_must mkfile 4k /$TESTPOOL/$TESTFS/truncated_file
log_must truncate -s 0 /$TESTPOOL/$TESTFS/truncated_file
# TX_WRITE (large file)
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/large \
bs=128k count=64 oflag=sync
# Write zeros, which compress to holes, in the middle of a file
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.1 bs=128k count=8
log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.1 bs=128k count=2
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.2 bs=128k count=8
log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.2 bs=128k count=2 seek=2
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/holes.3 bs=128k count=8
log_must dd if=/dev/zero of=/$TESTPOOL/$TESTFS/holes.3 bs=128k count=2 \
seek=2 conv=notrunc
# TX_MKXATTR
log_must mkdir /$TESTPOOL/$TESTFS/xattr.dir
log_must attr -qs fileattr -V HelloWorld /$TESTPOOL/$TESTFS/xattr.dir
log_must attr -qs tmpattr -V HelloWorld /$TESTPOOL/$TESTFS/xattr.dir
log_must attr -qr tmpattr /$TESTPOOL/$TESTFS/xattr.dir
log_must touch /$TESTPOOL/$TESTFS/xattr.file
log_must attr -qs fileattr -V HelloWorld /$TESTPOOL/$TESTFS/xattr.file
log_must attr -qs tmpattr -V HelloWorld /$TESTPOOL/$TESTFS/xattr.file
log_must attr -qr tmpattr /$TESTPOOL/$TESTFS/xattr.file
# TX_WRITE, TX_LINK, TX_REMOVE
# Make sure TX_REMOVE won't affect TX_WRITE if file is not destroyed
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/link_and_unlink bs=128k \
count=8
log_must ln /$TESTPOOL/$TESTFS/link_and_unlink \
/$TESTPOOL/$TESTFS/link_and_unlink.link
log_must rm /$TESTPOOL/$TESTFS/link_and_unlink.link
#
# 4. Copy TESTFS to temporary location (TESTDIR/copy)
#
log_must mkdir -p $TESTDIR/copy
log_must cp -a /$TESTPOOL/$TESTFS/* $TESTDIR/copy/
#
# 5. Unmount filesystem and export the pool
#
# At this stage TESTFS is empty again and frozen, the intent log contains
# a complete set of deltas to replay.
#
log_must zfs unmount /$TESTPOOL/$TESTFS
log_note "Verify transactions to replay:"
log_must zdb -iv $TESTPOOL/$TESTFS
log_must zpool export $TESTPOOL
#
# 6. Remount TESTFS <which replays the intent log>
#
# Import the pool to unfreeze it and claim log blocks. It has to be
# `zpool import -f` because we can't write a frozen pool's labels!
#
log_must zpool import -f -d $VDIR $TESTPOOL
#
# 7. Compare TESTFS against the TESTDIR/copy
#
log_note "Verify current block usage:"
log_must zdb -bcv $TESTPOOL
log_note "Verify copy of xattrs:"
log_must attr -l /$TESTPOOL/$TESTFS/xattr.dir
log_must attr -l /$TESTPOOL/$TESTFS/xattr.file
log_note "Verify working set diff:"
log_must diff -r /$TESTPOOL/$TESTFS $TESTDIR/copy
log_note "Verify file checksum:"
typeset checksum1=$(sha256digest /$TESTPOOL/$TESTFS/payload)
[[ "$checksum1" == "$checksum" ]] || \
log_fail "checksum mismatch ($checksum1 != $checksum)"
log_pass "Replay of intent log succeeds."