mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-22 02:27:36 +03:00
port async unlinked drain from illumos-nexenta
This patch is an async implementation of the existing sync zfs_unlinked_drain() function. This function is called at mount time and is responsible for freeing znodes that we didn't get to freeing before. We don't have to hold mounting of the dataset until the unlinked list is fully drained as is done now. Since we can process the unlinked set asynchronously this results in a better user experience when mounting a dataset with entries in the unlinked set. Reviewed by: Jorgen Lundman <lundman@lundman.net> Reviewed by: Tom Caputi <tcaputi@datto.com> Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed-by: Matt Ahrens <mahrens@delphix.com> Reviewed by: Paul Dagnelie <pcd@delphix.com> Signed-off-by: Alek Pinchuk <apinchuk@datto.com> Closes #8142
This commit is contained in:
@@ -644,7 +644,7 @@ tests = ['mmp_on_thread', 'mmp_on_uberblocks', 'mmp_on_off', 'mmp_interval',
|
||||
tags = ['functional', 'mmp']
|
||||
|
||||
[tests/functional/mount]
|
||||
tests = ['umount_001', 'umountall_001']
|
||||
tests = ['umount_001', 'umount_unlinked_drain', 'umountall_001']
|
||||
tags = ['functional', 'mount']
|
||||
|
||||
[tests/functional/mv_files]
|
||||
|
||||
@@ -3,4 +3,5 @@ dist_pkgdata_SCRIPTS = \
|
||||
setup.ksh \
|
||||
cleanup.ksh \
|
||||
umount_001.ksh \
|
||||
umount_unlinked_drain.ksh \
|
||||
umountall_001.ksh
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
#!/bin/ksh -p
|
||||
|
||||
#
|
||||
# This file and its contents are supplied under the terms of the
|
||||
# Common Development and Distribution License ("CDDL"), version 1.0.
|
||||
# You may only use this file in accordance with the terms of version
|
||||
# 1.0 of the CDDL.
|
||||
#
|
||||
# A full copy of the text of the CDDL should have accompanied this
|
||||
# source. A copy of the CDDL is also available via the Internet at
|
||||
# http://www.illumos.org/license/CDDL.
|
||||
#
|
||||
|
||||
#
|
||||
# Copyright 2018 Datto Inc.
|
||||
#
|
||||
|
||||
. $STF_SUITE/include/libtest.shlib
|
||||
|
||||
#
|
||||
# DESCRIPTION:
|
||||
# Test async unlinked drain to ensure mounting is not held up when there are
|
||||
# entries in the unlinked set. We also try to test that the list is able to be
|
||||
# filled up and drained at the same time.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Use zfs_unlink_suspend_progress tunable to disable freeing to build up
|
||||
# the unlinked set
|
||||
# 2. Make sure mount happens even when there are entries in the unlinked set
|
||||
# 3. Drain and build up the unlinked list at the same time to test for races
|
||||
#
|
||||
|
||||
function cleanup
|
||||
{
|
||||
log_must set_tunable32 zfs_unlink_suspend_progress $default_unlink_sp
|
||||
for fs in $(seq 1 3); do
|
||||
mounted $TESTDIR.$fs || zfs mount $TESTPOOL/$TESTFS.$fs
|
||||
rm -f $TESTDIR.$fs/file-*
|
||||
zfs set xattr=on $TESTPOOL/$TESTFS.$fs
|
||||
done
|
||||
}
|
||||
|
||||
function unlinked_size_is
|
||||
{
|
||||
MAX_ITERS=5 # iteration to do before we consider reported number stable
|
||||
iters=0
|
||||
last_usize=0
|
||||
while [[ $iters -le $MAX_ITERS ]]; do
|
||||
kstat_file=$(grep -nrwl /proc/spl/kstat/zfs/$2/objset-0x* -e $3)
|
||||
nunlinks=`cat $kstat_file | grep nunlinks | awk '{print $3}'`
|
||||
nunlinked=`cat $kstat_file | grep nunlinked | awk '{print $3}'`
|
||||
usize=$(($nunlinks - $nunlinked))
|
||||
if [[ $iters == $MAX_ITERS && $usize == $1 ]]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ $usize == $last_usize ]]; then
|
||||
(( iters++ ))
|
||||
else
|
||||
iters=0
|
||||
fi
|
||||
last_usize=$usize
|
||||
done
|
||||
|
||||
log_note "Unexpected unlinked set size: $last_usize, expected $1"
|
||||
return 1
|
||||
}
|
||||
|
||||
|
||||
UNLINK_SP_PARAM=/sys/module/zfs/parameters/zfs_unlink_suspend_progress
|
||||
default_unlink_sp=$(get_tunable zfs_unlink_suspend_progress)
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
log_assert "Unlinked list drain does not hold up mounting of fs"
|
||||
|
||||
for fs in 1 2 3; do
|
||||
set -A xattrs on sa off
|
||||
for xa in ${xattrs[@]}; do
|
||||
# setup fs and ensure all deleted files got into unliked set
|
||||
log_must mounted $TESTDIR.$fs
|
||||
|
||||
log_must zfs set xattr=$xa $TESTPOOL/$TESTFS.$fs
|
||||
|
||||
if [[ $xa == off ]]; then
|
||||
for fn in $(seq 1 175); do
|
||||
log_must mkfile 128k $TESTDIR.$fs/file-$fn
|
||||
done
|
||||
else
|
||||
log_must xattrtest -f 175 -x 3 -r -k -p $TESTDIR.$fs
|
||||
fi
|
||||
|
||||
log_must set_tunable32 zfs_unlink_suspend_progress 1
|
||||
log_must unlinked_size_is 0 $TESTPOOL $TESTPOOL/$TESTFS.$fs
|
||||
|
||||
# build up unlinked set
|
||||
for fn in $(seq 1 100); do
|
||||
log_must eval "rm $TESTDIR.$fs/file-$fn &"
|
||||
done
|
||||
log_must unlinked_size_is 100 $TESTPOOL $TESTPOOL/$TESTFS.$fs
|
||||
|
||||
# test that we can mount fs without emptying the unlinked list
|
||||
log_must zfs umount $TESTPOOL/$TESTFS.$fs
|
||||
log_must unmounted $TESTDIR.$fs
|
||||
log_must zfs mount $TESTPOOL/$TESTFS.$fs
|
||||
log_must mounted $TESTDIR.$fs
|
||||
log_must unlinked_size_is 100 $TESTPOOL $TESTPOOL/$TESTFS.$fs
|
||||
|
||||
# confirm we can drain and add to unlinked set at the same time
|
||||
log_must set_tunable32 zfs_unlink_suspend_progress 0
|
||||
log_must zfs umount $TESTPOOL/$TESTFS.$fs
|
||||
log_must zfs mount $TESTPOOL/$TESTFS.$fs
|
||||
for fn in $(seq 101 175); do
|
||||
log_must eval "rm $TESTDIR.$fs/file-$fn &"
|
||||
done
|
||||
log_must unlinked_size_is 0 $TESTPOOL $TESTPOOL/$TESTFS.$fs
|
||||
done
|
||||
done
|
||||
|
||||
log_pass "Confirmed unlinked list drain does not hold up mounting of fs"
|
||||
Reference in New Issue
Block a user