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:
Alek P
2019-02-12 10:41:15 -08:00
committed by Brian Behlendorf
parent 425d3237ee
commit dcec0a12c8
13 changed files with 300 additions and 10 deletions
+1 -1
View File
@@ -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"