1*c5832a53SAlek Pinchuk#!/bin/ksh -p
2*c5832a53SAlek Pinchuk
3*c5832a53SAlek Pinchuk#
4*c5832a53SAlek Pinchuk# This file and its contents are supplied under the terms of the
5*c5832a53SAlek Pinchuk# Common Development and Distribution License ("CDDL"), version 1.0.
6*c5832a53SAlek Pinchuk# You may only use this file in accordance with the terms of version
7*c5832a53SAlek Pinchuk# 1.0 of the CDDL.
8*c5832a53SAlek Pinchuk#
9*c5832a53SAlek Pinchuk# A full copy of the text of the CDDL should have accompanied this
10*c5832a53SAlek Pinchuk# source.  A copy of the CDDL is also available via the Internet at
11*c5832a53SAlek Pinchuk# http://www.illumos.org/license/CDDL.
12*c5832a53SAlek Pinchuk#
13*c5832a53SAlek Pinchuk
14*c5832a53SAlek Pinchuk#
15*c5832a53SAlek Pinchuk# Copyright 2018 Datto Inc.
16*c5832a53SAlek Pinchuk#
17*c5832a53SAlek Pinchuk
18*c5832a53SAlek Pinchuk. $STF_SUITE/include/libtest.shlib
19*c5832a53SAlek Pinchuk
20*c5832a53SAlek Pinchuk#
21*c5832a53SAlek Pinchuk# DESCRIPTION:
22*c5832a53SAlek Pinchuk# Test async unlinked drain to ensure mounting is not held up when there are
23*c5832a53SAlek Pinchuk# entries in the unlinked set. We also try to test that the list is able to be
24*c5832a53SAlek Pinchuk# filled up and drained at the same time.
25*c5832a53SAlek Pinchuk#
26*c5832a53SAlek Pinchuk# STRATEGY:
27*c5832a53SAlek Pinchuk# 1. Use zfs_unlink_suspend_progress tunable to disable freeing to build up
28*c5832a53SAlek Pinchuk#    the unlinked set
29*c5832a53SAlek Pinchuk# 2. Make sure mount happens even when there are entries in the unlinked set
30*c5832a53SAlek Pinchuk# 3. Drain and build up the unlinked list at the same time to test for races
31*c5832a53SAlek Pinchuk#
32*c5832a53SAlek Pinchuk
33*c5832a53SAlek Pinchukfunction cleanup
34*c5832a53SAlek Pinchuk{
35*c5832a53SAlek Pinchuk	log_must set_tunable32 zfs_unlink_suspend_progress $default_unlink_sp
36*c5832a53SAlek Pinchuk	for fs in $(seq 1 3); do
37*c5832a53SAlek Pinchuk		mounted $TESTDIR.$fs || zfs mount $TESTPOOL/$TESTFS.$fs
38*c5832a53SAlek Pinchuk		rm -f $TESTDIR.$fs/file-*
39*c5832a53SAlek Pinchuk		zfs set xattr=on $TESTPOOL/$TESTFS.$fs
40*c5832a53SAlek Pinchuk	done
41*c5832a53SAlek Pinchuk}
42*c5832a53SAlek Pinchuk
43*c5832a53SAlek Pinchukfunction unlinked_size_is
44*c5832a53SAlek Pinchuk{
45*c5832a53SAlek Pinchuk	MAX_ITERS=5 # iteration to do before we consider reported number stable
46*c5832a53SAlek Pinchuk	iters=0
47*c5832a53SAlek Pinchuk	last_usize=0
48*c5832a53SAlek Pinchuk	while [[ $iters -le $MAX_ITERS ]]; do
49*c5832a53SAlek Pinchuk		kstat_file=$(grep -nrwl /proc/spl/kstat/zfs/$2/objset-0x* -e $3)
50*c5832a53SAlek Pinchuk		nunlinks=`cat $kstat_file | grep nunlinks | awk '{print $3}'`
51*c5832a53SAlek Pinchuk		nunlinked=`cat $kstat_file | grep nunlinked | awk '{print $3}'`
52*c5832a53SAlek Pinchuk		usize=$(($nunlinks - $nunlinked))
53*c5832a53SAlek Pinchuk		if [[ $iters == $MAX_ITERS && $usize == $1 ]]; then
54*c5832a53SAlek Pinchuk			return 0
55*c5832a53SAlek Pinchuk		fi
56*c5832a53SAlek Pinchuk		if [[ $usize == $last_usize ]]; then
57*c5832a53SAlek Pinchuk			(( iters++ ))
58*c5832a53SAlek Pinchuk		else
59*c5832a53SAlek Pinchuk			iters=0
60*c5832a53SAlek Pinchuk		fi
61*c5832a53SAlek Pinchuk		last_usize=$usize
62*c5832a53SAlek Pinchuk	done
63*c5832a53SAlek Pinchuk
64*c5832a53SAlek Pinchuk	log_note "Unexpected unlinked set size: $last_usize, expected $1"
65*c5832a53SAlek Pinchuk	return 1
66*c5832a53SAlek Pinchuk}
67*c5832a53SAlek Pinchuk
68*c5832a53SAlek Pinchuk
69*c5832a53SAlek PinchukUNLINK_SP_PARAM=/sys/module/zfs/parameters/zfs_unlink_suspend_progress
70*c5832a53SAlek Pinchukdefault_unlink_sp=$(get_tunable zfs_unlink_suspend_progress)
71*c5832a53SAlek Pinchuk
72*c5832a53SAlek Pinchuklog_onexit cleanup
73*c5832a53SAlek Pinchuk
74*c5832a53SAlek Pinchuklog_assert "Unlinked list drain does not hold up mounting of fs"
75*c5832a53SAlek Pinchuk
76*c5832a53SAlek Pinchukfor fs in 1 2 3; do
77*c5832a53SAlek Pinchuk	set -A xattrs on sa off
78*c5832a53SAlek Pinchuk	for xa in ${xattrs[@]}; do
79*c5832a53SAlek Pinchuk		# setup fs and ensure all deleted files got into unliked set
80*c5832a53SAlek Pinchuk		log_must mounted $TESTDIR.$fs
81*c5832a53SAlek Pinchuk
82*c5832a53SAlek Pinchuk		log_must zfs set xattr=$xa $TESTPOOL/$TESTFS.$fs
83*c5832a53SAlek Pinchuk
84*c5832a53SAlek Pinchuk		if [[ $xa == off ]]; then
85*c5832a53SAlek Pinchuk			for fn in $(seq 1 175); do
86*c5832a53SAlek Pinchuk				log_must mkfile 128k $TESTDIR.$fs/file-$fn
87*c5832a53SAlek Pinchuk			done
88*c5832a53SAlek Pinchuk		else
89*c5832a53SAlek Pinchuk			log_must xattrtest -f 175 -x 3 -r -k -p $TESTDIR.$fs
90*c5832a53SAlek Pinchuk		fi
91*c5832a53SAlek Pinchuk
92*c5832a53SAlek Pinchuk		log_must set_tunable32 zfs_unlink_suspend_progress 1
93*c5832a53SAlek Pinchuk		log_must unlinked_size_is 0 $TESTPOOL $TESTPOOL/$TESTFS.$fs
94*c5832a53SAlek Pinchuk
95*c5832a53SAlek Pinchuk		# build up unlinked set
96*c5832a53SAlek Pinchuk		for fn in $(seq 1 100); do
97*c5832a53SAlek Pinchuk			log_must eval "rm $TESTDIR.$fs/file-$fn &"
98*c5832a53SAlek Pinchuk		done
99*c5832a53SAlek Pinchuk		log_must unlinked_size_is 100 $TESTPOOL $TESTPOOL/$TESTFS.$fs
100*c5832a53SAlek Pinchuk
101*c5832a53SAlek Pinchuk		# test that we can mount fs without emptying the unlinked list
102*c5832a53SAlek Pinchuk		log_must zfs umount $TESTPOOL/$TESTFS.$fs
103*c5832a53SAlek Pinchuk		log_must unmounted $TESTDIR.$fs
104*c5832a53SAlek Pinchuk		log_must zfs mount $TESTPOOL/$TESTFS.$fs
105*c5832a53SAlek Pinchuk		log_must mounted $TESTDIR.$fs
106*c5832a53SAlek Pinchuk		log_must unlinked_size_is 100 $TESTPOOL $TESTPOOL/$TESTFS.$fs
107*c5832a53SAlek Pinchuk
108*c5832a53SAlek Pinchuk		# confirm we can drain and add to unlinked set at the same time
109*c5832a53SAlek Pinchuk		log_must set_tunable32 zfs_unlink_suspend_progress 0
110*c5832a53SAlek Pinchuk		log_must zfs umount $TESTPOOL/$TESTFS.$fs
111*c5832a53SAlek Pinchuk		log_must zfs mount $TESTPOOL/$TESTFS.$fs
112*c5832a53SAlek Pinchuk		for fn in $(seq 101 175); do
113*c5832a53SAlek Pinchuk			log_must eval "rm $TESTDIR.$fs/file-$fn &"
114*c5832a53SAlek Pinchuk		done
115*c5832a53SAlek Pinchuk		log_must unlinked_size_is 0 $TESTPOOL $TESTPOOL/$TESTFS.$fs
116*c5832a53SAlek Pinchuk	done
117*c5832a53SAlek Pinchukdone
118*c5832a53SAlek Pinchuk
119*c5832a53SAlek Pinchuklog_pass "Confirmed unlinked list drain does not hold up mounting of fs"
120