zfs_rename: support RENAME_* flags

Implement support for Linux's RENAME_* flags (for renameat2). Aside from
being quite useful for userspace (providing race-free ways to exchange
paths and implement mv --no-clobber), they are used by overlayfs and are
thus required in order to use overlayfs-on-ZFS.

In order for us to represent the new renameat2(2) flags in the ZIL, we
create two new transaction types for the two flags which need
transactional-level support (RENAME_EXCHANGE and RENAME_WHITEOUT).
RENAME_NOREPLACE does not need any ZIL support because we know that if
the operation succeeded before creating the ZIL entry, there was no file
to be clobbered and thus it can be treated as a regular TX_RENAME.

Reviewed-by: Ryan Moeller <ryan@iXsystems.com>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Pavel Snajdr <snajpa@snajpa.net>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
Closes #12209
Closes #14070
This commit is contained in:
Aleksa Sarai
2019-06-22 10:35:11 +10:00
committed by Brian Behlendorf
parent e015d6cc0b
commit dbf6108b4d
33 changed files with 932 additions and 74 deletions
@@ -0,0 +1,7 @@
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/renameat2
dist_pkgdata_SCRIPTS = \
setup.ksh \
cleanup.ksh \
renameat2_noreplace.ksh \
renameat2_exchange.ksh \
renameat2_whiteout.ksh
+34
View File
@@ -0,0 +1,34 @@
#!/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.
#
#
# Copyright (c) 2013 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
default_cleanup
@@ -0,0 +1,61 @@
#!/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 (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
# Copyright (C) 2019 SUSE LLC
#
. $STF_SUITE/include/libtest.shlib
verify_runnable "both"
function cleanup
{
log_must rm -rf $TESTDIR/*
}
log_assert "ZFS supports RENAME_EXCHANGE."
log_onexit cleanup
cd $TESTDIR
echo "foo" > foo
echo "bar" > bar
# Self-exchange is a no-op.
log_must renameat2 -x foo foo
log_must grep '^foo$' foo
# Basic exchange.
log_must renameat2 -x foo bar
log_must grep '^bar$' foo
log_must grep '^foo$' bar
# And exchange back.
log_must renameat2 -x foo bar
log_must grep '^foo$' foo
log_must grep '^bar$' bar
# Exchange with a bad path should fail.
log_mustnot renameat2 -x bar baz
log_pass "ZFS supports RENAME_EXCHANGE as expected."
@@ -0,0 +1,51 @@
#!/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 (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
# Copyright (C) 2019 SUSE LLC
#
. $STF_SUITE/include/libtest.shlib
verify_runnable "both"
function cleanup
{
log_must rm -rf $TESTDIR/*
}
log_assert "ZFS supports RENAME_NOREPLACE."
log_onexit cleanup
cd $TESTDIR
touch foo bar
# Clobbers should always fail.
log_mustnot renameat2 -n foo foo
log_mustnot renameat2 -n foo bar
log_mustnot renameat2 -n bar foo
# Regular renames should succeed.
log_must renameat2 -n bar baz
log_pass "ZFS supports RENAME_NOREPLACE as expected."
@@ -0,0 +1,50 @@
#!/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 (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
# Copyright (C) 2019 SUSE LLC
#
. $STF_SUITE/include/libtest.shlib
verify_runnable "both"
function cleanup
{
log_must rm -rf $TESTDIR/*
}
log_assert "ZFS supports RENAME_WHITEOUT."
log_onexit cleanup
cd $TESTDIR
echo "whiteout" > whiteout
# Straight-forward rename-with-whiteout.
log_must renameat2 -w whiteout new
# Check new file.
log_must grep '^whiteout$' new
# Check that the whiteout is actually a {0,0} char device.
log_must grep '^character special file:0:0$' <<<"$(stat -c '%F:%t:%T' whiteout)"
log_pass "ZFS supports RENAME_WHITEOUT as expected."
+37
View File
@@ -0,0 +1,37 @@
#!/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 (C) 2019 Aleksa Sarai <cyphar@cyphar.com>
# Copyright (C) 2019 SUSE LLC
#
. $STF_SUITE/include/libtest.shlib
if ! is_linux ; then
log_unsupported "renameat2 is linux-only"
elif ! renameat2 -C ; then
log_unsupported "renameat2 not supported on this (pre-3.15) linux kernel"
fi
DISK=${DISKS%% *}
default_setup $DISK
@@ -175,6 +175,29 @@ log_must ln /$TESTPOOL/$TESTFS/link_and_unlink \
/$TESTPOOL/$TESTFS/link_and_unlink.link
log_must rm /$TESTPOOL/$TESTFS/link_and_unlink.link
# We can't test RENAME_* flags without renameat2(2) support.
if ! is_linux ; then
log_note "renameat2 is linux-only"
elif ! renameat2 -C ; then
log_note "renameat2 not supported on this (pre-3.15) linux kernel"
else
# TX_RENAME_EXCHANGE
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/xchg-a bs=1k count=1
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/xchg-b bs=1k count=1
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/xchg-c bs=1k count=1
log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/xchg-d bs=1k count=1
# rotate the files around
log_must renameat2 -x /$TESTPOOL/$TESTFS/xchg-{a,b}
log_must renameat2 -x /$TESTPOOL/$TESTFS/xchg-{b,c}
log_must renameat2 -x /$TESTPOOL/$TESTFS/xchg-{c,a}
# exchange same path
log_must renameat2 -x /$TESTPOOL/$TESTFS/xchg-{d,d}
# TX_RENAME_WHITEOUT
log_must mkfile 1k /$TESTPOOL/$TESTFS/whiteout
log_must renameat2 -w /$TESTPOOL/$TESTFS/whiteout{,-moved}
fi
#
# 4. Copy TESTFS to temporary location (TESTDIR/copy)
#