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