1#!/bin/ksh -p
2# SPDX-License-Identifier: CDDL-1.0
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 (c) 2017 by Delphix. All rights reserved.
16#
17. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
18
19#
20# DESCRIPTION: Execute a long-running zfs channel program and attempt to
21# cancel it by sending a signal.
22#
23
24verify_runnable "global"
25
26rootfs=$TESTPOOL/$TESTFS
27snapname=snap
28limit=50000000
29
30function cleanup
31{
32	datasetexists $rootfs && destroy_dataset $rootfs -R
33}
34
35log_onexit cleanup
36
37#
38# Create a working set of 100 file systems
39#
40for i in {1..100}; do
41	log_must zfs create "$rootfs/child$i"
42done
43
44#
45# Attempt to create 100 snapshots with zfs.sync.snapshot() along with some
46# time consuming efforts. We use loops of zfs.check.* (dry run operations)
47# to consume instructions before the next zfs.sync.snapshot() occurs.
48#
49# Without a signal interruption this ZCP would take several minutes and
50# generate over 30 million Lua instructions.
51#
52function chan_prog
53{
54zfs program -t $limit $TESTPOOL - $rootfs $snapname <<-EOF
55	arg = ...
56	fs = arg["argv"][1]
57	snap = arg["argv"][2]
58	for child in zfs.list.children(fs) do
59		local snapname = child .. "@" .. snap
60		zfs.check.snapshot(snapname)
61		zfs.sync.snapshot(snapname)
62		for i=1,20000,1 do
63			zfs.check.snapshot(snapname)
64			zfs.check.destroy(snapname)
65			zfs.check.destroy(fs)
66		end
67	end
68	return "should not have reached here"
69EOF
70}
71
72log_note "Executing a long-running zfs program in the background"
73chan_prog &
74CHILD=$!
75
76#
77# After waiting, send a kill signal to the channel program process.
78# This should stop the ZCP near a million instructions but still have
79# created some of the snapshots. Note that since the above zfs program
80# command might get wrapped, we also issue a kill to the group.
81#
82sleep 10
83log_pos pkill -P $CHILD
84log_pos kill $CHILD
85
86#
87# Make sure the channel program did not fully complete by enforcing
88# that not all of the snapshots were created.
89#
90snap_count=$(zfs list -t snapshot | grep -c $TESTPOOL)
91log_note "$snap_count snapshots created by ZCP"
92
93log_mustnot [ "$snap_count" -eq 0 ]
94log_mustnot [ "$snap_count" -gt 90 ]
95
96log_pass "Cancelling a long-running channel program works."
97