1
# Put test-related bits that are parted-specific here.
2
# This file is sourced from the testing framework.
3
sector_size_=${PARTED_SECTOR_SIZE:-512}
5
scsi_debug_lock_dir_="$abs_srcdir/scsi_debug.lock"
7
require_scsi_debug_module_()
9
require_udevadm_settle_
10
# check for scsi_debug module
11
modprobe -n scsi_debug ||
12
skip_ "you lack the scsi_debug kernel module"
15
scsi_debug_modprobe_succeeded_=
17
# Always run this cleanup function.
18
cleanup_final_() { scsi_debug_cleanup_; }
22
# This function must always release the lock.
23
# If modprobe succeeded, it must be sure to run rmmod.
24
if test -n "$scsi_debug_modprobe_succeeded_"; then
25
# We have to insist. Otherwise, a single rmmod usually fails to remove it,
26
# due either to "Resource temporarily unavailable" or to
27
# "Module scsi_debug is in use".
30
while [ $i -lt 10 ] ; do
32
&& { test "$VERBOSE" = yes && warn_ $ME_ rmmod scsi_debug...; break; }
38
rm -fr $scsi_debug_lock_dir_
41
# Helper function: wait 2s (via .1s increments) for FILE to appear.
42
# Usage: wait_for_dev_to_appear_ /dev/sdg
43
# Return 0 upon success, 1 upon failure.
44
wait_for_dev_to_appear_()
50
ls "$file" > /dev/null 2>&1 && return 0
51
sleep .1 2>/dev/null || { sleep 1; incr=10; }
52
i=$(expr $i + $incr); test $i = 20 && break
57
# Tests that uses "modprobe scsi_debug ..." must not be run in parallel.
58
scsi_debug_acquire_lock_()
61
local lock_timeout_stale_seconds=120
63
# If it was created more than $lock_timeout_stale_seconds ago, remove it.
64
# FIXME: implement this
69
mkdir "$scsi_debug_lock_dir_" && return 0
70
sleep .1 2>/dev/null || { sleep 1; incr=10; }
71
i=$(expr $i + $incr); test $i = $(expr $retries \* 10) && break
74
warn_ "$ME_: failed to acquire lock: $scsi_debug_lock_dir_"
78
# If there is a scsi_debug device, print the corresponding "sdN" and return 0.
79
# Otherwise, return 1.
82
local m; m=$(grep -lw scsi_debug /sys/block/sd*/device/model) || return 1
84
# Remove the /sys/block/ prefix, and then the /device/model suffix.
91
# Create a device using the scsi_debug module with the options passed to
92
# this function as arguments. Upon success, print the name of the new device.
95
scsi_debug_acquire_lock_
97
# It is not trivial to determine the name of the device we're creating.
98
# Record the names of all /sys/block/sd* devices *before* probing:
100
modprobe scsi_debug "$@" || { rm -f stamp; return 1; }
101
scsi_debug_modprobe_succeeded_=1
102
test "$VERBOSE" = yes \
103
&& warn_ $ME_ modprobe scsi_debug succeeded
105
# Wait up to 2s (via .1s increments) for the list of devices to change.
106
# Sleeping for a fraction of a second requires GNU sleep, so fall
107
# back on sleeping 2x1s if that fails.
108
# FIXME-portability: using "cmp - ..." probably requires GNU cmp.
113
new_dev=$(new_sdX_) && break
114
sleep .1 2>/dev/null || { sleep 1; incr=10; }
115
i=$(expr $i + $incr); test $i = 20 && break
121
*) warn_ $ME_ unexpected device name: $new_dev; return 1 ;;
123
local t=/dev/$new_dev
124
wait_for_dev_to_appear_ $t
129
require_512_byte_sector_size_()
131
test $sector_size_ = 512 \
132
|| skip_ FS test with sector size != 512
137
case $# in 2) ;; *) echo "usage: peek_ FILE 0_BASED_OFFSET" >&2; exit 1;; esac
138
case $2 in *[^0-9]*) echo "peek_: invalid offset: $2" >&2; exit 1 ;; esac
139
dd if="$1" bs=1 skip="$2" count=1
144
case $# in 3) ;; *) echo "usage: poke_ FILE 0_BASED_OFFSET BYTE" >&2; exit 1;;
146
case $2 in *[^0-9]*) echo "poke_: invalid offset: $2" >&2; exit 1 ;; esac
147
case $3 in ?) ;; *) echo "poke_: invalid byte: '$3'" >&2; exit 1 ;; esac
148
printf %s "$3" | dd of="$1" bs=1 seek="$2" count=1 conv=notrunc
151
# byte 56 of the partition entry is the first byte of its 72-byte name field
152
gpt1_pte_name_offset_()
155
case $ss in *[^0-9]*) echo "$0: invalid sector size: $ss">&2; return 1;; esac
160
# Change the name of the first partition in the primary GPT table,
161
# thus invalidating the PartitionEntryArrayCRC32 checksum.
162
gpt_corrupt_primary_table_()
164
case $# in 2) ;; *) echo "$0: expected 2 args, got $#" >&2; return 1;; esac
167
case $ss in *[^0-9]*) echo "$0: invalid sector size: $ss">&2; return 1;; esac
169
# get the first byte of the name
170
local orig_pte_name_byte
171
orig_pte_name_byte=$(peek_ $dev $(gpt1_pte_name_offset_ $ss)) || return 1
174
test x"$orig_pte_name_byte" = xA && new_byte=B || new_byte=A
176
# Replace with a different byte
177
poke_ $dev $(gpt1_pte_name_offset_ $ss) "$new_byte" || return 1
179
printf %s "$orig_pte_name_byte"
183
gpt_restore_primary_table_()
185
case $# in 3) ;; *) echo "$0: expected 2 args, got $#" >&2; return 1;; esac
188
case $ss in *[^0-9]*) echo "$0: invalid sector size: $ss">&2; return 1;; esac
190
poke_ $dev $(gpt1_pte_name_offset_ $ss) "$orig_byte" || return 1
193
. "$abs_top_srcdir/tests/t-lvm.sh"