1#!/bin/ksh -p
2#
3# This file and its contents are supplied under the terms of the
4# Common Development and Distribution License ("CDDL"), version 1.0.
5# You may only use this file in accordance with the terms of version
6# 1.0 of the CDDL.
7#
8# A full copy of the text of the CDDL should have accompanied this
9# source.  A copy of the CDDL is also available via the Internet at
10# http://www.illumos.org/license/CDDL.
11#
12
13#
14# Copyright (c) 2017 by Delphix. All rights reserved.
15#
16. $STF_SUITE/tests/functional/channel_program/channel_common.kshlib
17
18#
19# DESCRIPTION: Execute a long-running zfs channel program and attempt to
20# cancel it by sending a signal.
21#
22
23verify_runnable "global"
24
25rootfs=$TESTPOOL/$TESTFS
26snapname=snap
27limit=50000000
28
29function cleanup
30{
31	datasetexists $rootfs && log_must zfs destroy -R $rootfs
32}
33
34log_onexit cleanup
35
36#
37# Create a working set of 100 file systems
38#
39for i in {1..100}; do
40	log_must zfs create "$rootfs/child$i"
41done
42
43#
44# Attempt to create 100 snapshots with zfs.sync.snapshot() along with some
45# time consuming efforts. We use loops of zfs.check.* (dry run operations)
46# to consume instructions before the next zfs.sync.snapshot() occurs.
47#
48# Without a signal interruption this ZCP would take several minutes and
49# generate over 30 million Lua instructions.
50#
51function chan_prog
52{
53zfs program -t $limit $TESTPOOL - $rootfs $snapname <<-EOF
54	arg = ...
55	fs = arg["argv"][1]
56	snap = arg["argv"][2]
57	for child in zfs.list.children(fs) do
58		local snapname = child .. "@" .. snap
59		zfs.check.snapshot(snapname)
60		zfs.sync.snapshot(snapname)
61		for i=1,20000,1 do
62			zfs.check.snapshot(snapname)
63			zfs.check.destroy(snapname)
64			zfs.check.destroy(fs)
65		end
66	end
67	return "should not have reached here"
68EOF
69}
70
71log_note "Executing a long-running zfs program in the background"
72chan_prog &
73CHILD=$!
74
75#
76# After waiting, send a kill signal to the channel program process.
77# This should stop the ZCP near a million instructions but still have
78# created some of the snapshots. Note that since the above zfs program
79# command might get wrapped, we also issue a kill to the group.
80#
81sleep 10
82log_pos pkill -P $CHILD
83log_pos kill $CHILD
84
85#
86# Make sure the channel program did not fully complete by enforcing
87# that not all of the snapshots were created.
88#
89snap_count=$(zfs list -t snapshot | grep $TESTPOOL | wc -l)
90log_note "$snap_count snapshots created by ZCP"
91
92if [ "$snap_count" -eq 0 ]; then
93	log_fail "Channel progam failed to run."
94elif [ "$snap_count" -gt 50 ]; then
95	log_fail "Too many snapshots after a cancel ($snap_count)."
96else
97	log_pass "Canceling a long-running channel program works."
98fi
99