xref: /spdk/test/dd/posix.sh (revision 99a43e75ed9ac3c87d23e3746173cf5a5a992544)
1#!/usr/bin/env bash
2#  SPDX-License-Identifier: BSD-3-Clause
3#  Copyright (C) 2020 Intel Corporation
4#  All rights reserved.
5#
6testdir=$(readlink -f "$(dirname "$0")")
7rootdir=$(readlink -f "$testdir/../../")
8source "$testdir/common.sh"
9
10cleanup() {
11	rm -f "$test_file0"{,.link}
12	rm -f "$test_file1"{,.link}
13}
14
15append() {
16	local dump0
17	local dump1
18
19	dump0=$(gen_bytes 32)
20	dump1=$(gen_bytes 32)
21
22	printf '%s' "$dump0" > "$test_file0"
23	printf '%s' "$dump1" > "$test_file1"
24
25	"${DD_APP[@]}" --if="$test_file0" --of="$test_file1" --oflag=append
26
27	[[ $(< "$test_file1") == "${dump1}${dump0}" ]]
28}
29
30directory() {
31	NOT "${DD_APP[@]}" --if="$test_file0" --iflag=directory --of="$test_file0"
32	NOT "${DD_APP[@]}" --if="$test_file0" --of="$test_file0" --oflag=directory
33}
34
35nofollow() {
36	local test_file0_link=$test_file0.link
37	local test_file1_link=$test_file1.link
38
39	ln -fs "$test_file0" "$test_file0_link"
40	ln -fs "$test_file1" "$test_file1_link"
41
42	NOT "${DD_APP[@]}" --if="$test_file0_link" --iflag=nofollow --of="$test_file1"
43	NOT "${DD_APP[@]}" --if="$test_file0" --of="$test_file1_link" --oflag=nofollow
44
45	# Do an extra step of checking if we actually can follow symlinks
46	gen_bytes 512 > "$test_file0"
47
48	"${DD_APP[@]}" --if="$test_file0_link" --of="$test_file1"
49	[[ $(< "$test_file0") == "$(< "$test_file1")" ]]
50}
51
52noatime() {
53	local atime_if
54	local atime_of
55
56	# It seems like spdk_dd doesn't update the atime in case 0 bytes are copied.
57	# This differs from how standard dd works for instance
58	gen_bytes 512 > "$test_file0"
59
60	atime_if=$(stat --printf="%X" "$test_file0")
61	atime_of=$(stat --printf="%X" "$test_file1")
62
63	# Make sure atime has a chance to be updated - if all tests finish within
64	# 1s (see %X) we may get a false negative at the last check. See:
65	# https://github.com/spdk/spdk/issues/2720
66	sleep 1
67
68	"${DD_APP[@]}" --if="$test_file0" --iflag=noatime --of="$test_file1"
69	((atime_if == $(stat --printf="%X" "$test_file0")))
70	((atime_of == $(stat --printf="%X" "$test_file1")))
71
72	"${DD_APP[@]}" --if="$test_file0" --of="$test_file1"
73	((atime_if < $(stat --printf="%X" "$test_file0")))
74}
75
76io() {
77	local flags_ro flags_rw flag_ro flag_rw
78
79	# O_NONBLOCK is actually a no-op, from a functional perspective, while
80	# open()ing a regular file, but let's keep it just to test its usage.
81	flags_ro=(direct nonblock)
82	flags_rw=("${flags_ro[@]}" sync dsync)
83
84	# simply check if data was correctly copied between files
85	for flag_ro in "${flags_ro[@]}"; do
86		gen_bytes 512 > "$test_file0"
87		for flag_rw in "${flags_rw[@]}"; do
88			"${DD_APP[@]}" \
89				--if="$test_file0" \
90				--iflag="$flag_ro" \
91				--of="$test_file1" \
92				--oflag="$flag_rw"
93			[[ $(< "$test_file0") == "$(< "$test_file1")" ]]
94		done
95	done
96}
97
98tests() {
99	printf '* First test run%s\n' \
100		"${msg[liburing_in_use]}" >&2
101
102	run_test "dd_flag_append" append
103	run_test "dd_flag_directory" directory
104	run_test "dd_flag_nofollow" nofollow
105	run_test "dd_flag_noatime" noatime
106	run_test "dd_flags_misc" io
107}
108
109tests_forced_aio() {
110	printf '* Second test run%s\n' \
111		"${msg[liburing_in_use ? 2 : 0]}" >&2
112
113	DD_APP+=("--aio")
114	run_test "dd_flag_append_forced_aio" append
115	run_test "dd_flag_directory_forced_aio" directory
116	run_test "dd_flag_nofollow_forced_aio" nofollow
117	run_test "dd_flag_noatime_forced_aio" noatime
118	run_test "dd_flags_misc_forced_aio" io
119}
120
121msg[0]=", using AIO"
122msg[1]=", liburing in use"
123msg[2]=", disabling liburing, forcing AIO"
124
125trap "cleanup" EXIT
126
127test_file0=$SPDK_TEST_STORAGE/dd.dump0
128test_file1=$SPDK_TEST_STORAGE/dd.dump1
129
130tests
131tests_forced_aio
132