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 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 69default_unlink_sp=$(get_tunable UNLINK_SUSPEND_PROGRESS) 70 71log_onexit cleanup 72 73log_assert "Unlinked list drain does not hold up mounting of fs" 74 75for fs in 1 2 3; do 76 set -A xattrs on sa off 77 for xa in ${xattrs[@]}; do 78 # setup fs and ensure all deleted files got into unliked set 79 log_must mounted $TESTDIR.$fs 80 81 log_must zfs set xattr=$xa $TESTPOOL/$TESTFS.$fs 82 83 if [[ $xa == off ]]; then 84 for fn in $(seq 1 175); do 85 log_must mkfile 128k $TESTDIR.$fs/file-$fn 86 done 87 else 88 log_must xattrtest -f 175 -x 3 -r -k -p $TESTDIR.$fs 89 fi 90 91 log_must set_tunable32 UNLINK_SUSPEND_PROGRESS 1 92 log_must unlinked_size_is 0 $TESTPOOL $TESTPOOL/$TESTFS.$fs 93 94 # build up unlinked set 95 for fn in $(seq 1 100); do 96 log_must eval "rm $TESTDIR.$fs/file-$fn &" 97 done 98 log_must unlinked_size_is 100 $TESTPOOL $TESTPOOL/$TESTFS.$fs 99 100 # test that we can mount fs without emptying the unlinked list 101 log_must zfs umount $TESTPOOL/$TESTFS.$fs 102 log_must unmounted $TESTDIR.$fs 103 log_must zfs mount $TESTPOOL/$TESTFS.$fs 104 log_must mounted $TESTDIR.$fs 105 log_must unlinked_size_is 100 $TESTPOOL $TESTPOOL/$TESTFS.$fs 106 107 # confirm we can drain and add to unlinked set at the same time 108 log_must set_tunable32 UNLINK_SUSPEND_PROGRESS 0 109 log_must zfs umount $TESTPOOL/$TESTFS.$fs 110 log_must zfs mount $TESTPOOL/$TESTFS.$fs 111 for fn in $(seq 101 175); do 112 log_must eval "rm $TESTDIR.$fs/file-$fn &" 113 done 114 log_must unlinked_size_is 0 $TESTPOOL $TESTPOOL/$TESTFS.$fs 115 done 116done 117 118log_pass "Confirmed unlinked list drain does not hold up mounting of fs" 119