xref: /freebsd/tests/sys/cam/ctl/read_buffer.sh (revision f5c7feee7129dc88a2e5dc3ce0a075cb5e4f534a)
1# SPDX-License-Identifier: BSD-2-Clause
2#
3# Copyright (c) 2024 Axcient
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS DOCUMENTATION IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
26# Not tested
27# * modes other than "Data" and "Desc".  We don't support those.
28# * Buffer ID other than 0.  We don't support those.
29# * The Mode Specific field.  We don't support it.
30
31load_modules() {
32	if ! kldstat -q -m ctl; then
33		kldload ctl || atf_skip "could not load ctl kernel mod"
34	fi
35	if ! ctladm port -o on -p 0; then
36		atf_skip "could not enable the camsim frontend"
37	fi
38}
39
40find_da_device() {
41	SERIAL=$1
42
43	# Rescan camsim
44	# XXX  camsim doesn't update when creating a new device.  Worse, a
45	# rescan won't look for new devices.  So we must disable/re-enable it.
46	# Worse still, enabling it isn't synchronous, so we need a retry loop
47	# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=281000
48	retries=5
49	ctladm port -o off -p 0 >/dev/null
50	ctladm port -o on -p 0 >/dev/null
51	while true; do
52
53		# Find the corresponding da device
54		da=`geom disk list | awk -v serial=$SERIAL ' /Geom name:/ { devname=$NF } /ident:/ && $NF ~ serial { print devname; exit } '`
55		if [ -z "$da" ]; then
56			retries=$(( $retries - 1 ))
57			if [ $retries -eq 0 ]; then
58				cat lun-create.txt
59				geom disk list
60				atf_fail "Could not find da device"
61			fi
62			sleep 0.1
63			continue
64		fi
65		break
66	done
67}
68
69# Create a CTL LUN
70create_ramdisk() {
71	atf_check -o save:lun-create.txt ctladm create -b ramdisk -s 1048576
72	atf_check egrep -q "LUN created successfully" lun-create.txt
73	SERIAL=`awk '/Serial Number:/ {print $NF}' lun-create.txt`
74	if [ -z "$SERIAL" ]; then
75		atf_fail "Could not find serial number"
76	fi
77	find_da_device $SERIAL
78}
79
80cleanup() {
81	if [ -e "lun-create.txt" ]; then
82		lun_id=`awk '/LUN ID:/ {print $NF}' lun-create.txt`
83		ctladm remove -b ramdisk -l $lun_id > /dev/null
84	fi
85}
86
87atf_test_case basic cleanup
88basic_head()
89{
90	atf_set "descr" "READ BUFFER can retrieve data previously written by WRITE BUFFER"
91	atf_set "require.user" "root"
92	atf_set "require.progs" sg_read_buffer sg_write_buffer
93}
94basic_body()
95{
96	create_ramdisk
97
98	# Write to its buffer
99	cp /etc/passwd input
100	len=`wc -c input | cut -wf 2`
101	atf_check -o ignore sg_write_buffer --mode data --in=input /dev/$da
102
103	# Read it back
104	atf_check -o save:output sg_read_buffer --mode data -l $len --raw /dev/$da
105
106	# And verify
107	if ! diff -q input output; then
108		atf_fail "Miscompare!"
109	fi
110}
111basic_cleanup()
112{
113	cleanup
114}
115
116# Read from the Descriptor mode.  Along with Data, these are the only two modes
117# we support.
118atf_test_case desc cleanup
119desc_head()
120{
121	atf_set "descr" "READ BUFFER can retrieve the buffer size via the DESCRIPTOR mode"
122	atf_set "require.user" "root"
123	atf_set "require.progs" sg_read_buffer
124}
125desc_body()
126{
127	create_ramdisk
128
129	atf_check -o inline:" 00     00 04 00 00\n" sg_read_buffer --hex --mode desc /dev/$da
130}
131desc_cleanup()
132{
133	cleanup
134}
135
136atf_test_case length cleanup
137length_head()
138{
139	atf_set "descr" "READ BUFFER can limit its length with the LENGTH field"
140	atf_set "require.user" "root"
141	atf_set "require.progs" sg_read_buffer sg_write_buffer
142}
143length_body()
144{
145	create_ramdisk
146
147	# Write to its buffer
148	atf_check -o ignore -e ignore dd if=/dev/random of=input bs=4096 count=1
149	atf_check -o ignore -e ignore dd if=input bs=2048 count=1 of=expected
150	atf_check -o ignore sg_write_buffer --mode data --in=input /dev/$da
151
152	# Read it back
153	atf_check -o save:output sg_read_buffer --mode data -l 2048 --raw /dev/$da
154
155	# And verify
156	if ! diff -q expected output; then
157		atf_fail "Miscompare!"
158	fi
159}
160length_cleanup()
161{
162	cleanup
163}
164
165atf_test_case offset cleanup
166offset_head()
167{
168	atf_set "descr" "READ BUFFER accepts the BUFFER OFFSET field"
169	atf_set "require.user" "root"
170	atf_set "require.progs" sg_read_buffer sg_write_buffer
171}
172offset_body()
173{
174	create_ramdisk
175
176	# Write to its buffer
177	atf_check -o ignore -e ignore dd if=/dev/random of=input bs=4096 count=1
178	atf_check -o ignore -e ignore dd if=input iseek=2 bs=512 count=1 of=expected
179	atf_check -o ignore sg_write_buffer --mode data --in=input /dev/$da
180
181	# Read it back
182	atf_check -o save:output sg_read_buffer --mode data -l 512 -o 1024 --raw /dev/$da
183
184	# And verify
185	if ! diff -q expected output; then
186		atf_fail "Miscompare!"
187	fi
188}
189offset_cleanup()
190{
191	cleanup
192}
193
194atf_test_case uninitialized cleanup
195uninitialized_head()
196{
197	atf_set "descr" "READ BUFFER buffers are zero-initialized"
198	atf_set "require.user" "root"
199	atf_set "require.progs" sg_read_buffer
200}
201uninitialized_body()
202{
203	create_ramdisk
204
205	# Read an uninitialized buffer
206	atf_check -o save:output sg_read_buffer --mode data -l 262144 --raw /dev/$da
207
208	# And verify
209	atf_check -o ignore -e ignore dd if=/dev/zero bs=262144 count=1 of=expected
210	if ! diff -q expected output; then
211		atf_fail "Miscompare!"
212	fi
213}
214uninitialized_cleanup()
215{
216	cleanup
217}
218
219atf_init_test_cases()
220{
221	atf_add_test_case basic
222	atf_add_test_case desc
223	atf_add_test_case length
224	atf_add_test_case offset
225	atf_add_test_case uninitialized
226}
227