5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are
9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer.
12 # * Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
16 # * Neither the name of Red Hat nor the names of its contributors may be
17 # used to endorse or promote products derived from this software without
18 # specific prior written permission.
20 # THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
21 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 # PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
24 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 # Demonstrate a fix for a bug where blocksize could lose aligned writes
34 # run in parallel with unaligned writes
42 requires
dd oflag
=seek_bytes
</dev
/null
44 files
='blocksize-sharding.img blocksize-sharding.tmp'
46 cleanup_fn
rm -f $files
48 # Script a server that requires 16-byte aligned requests, and which delays
49 # 4s after reads if a witness file exists. Couple it with the delay filter
50 # that delays 2s before writes. If an unaligned and aligned write overlap,
51 # and can execute in parallel, we would have this timeline:
53 # T1 aligned write 1's to 0/16 T2 unaligned write 2's to 4/12
54 #t=0 blocksize: next->pwrite(0, 16) blocksize: next->pread(0, 16)
55 # delay: wait 2s delay: next->pread(0, 16)
56 # ... eval: read 0's, wait 4s
57 #t=2 delay: next->pwrite(0, 16) ...
60 #t=4 return 0's (now stale)
61 # blocksize: next->pwrite(0, 16)
63 #t=6 delay: next->pwrite(0, 16)
64 # eval: write stale RMW buffer
66 # leaving us with a sharded 0000222222222222 (T1's write is lost).
67 # But as long as the blocksize filter detects the overlap, we should end
68 # up with either 1111222222222222 (aligned write completed first), or with
69 # 1111111111111111 (unaligned write completed first), either taking 8s,
70 # but with no sharding.
72 # We also need an nbdsh script that kicks off parallel writes.
77 witness = os.getenv("witness")
80 open(path, "a").close()
82 # First pass: check that two aligned operations work in parallel
83 # Total time should be closer to 2 seconds, rather than 4 if serialized
85 ba1 = bytearray(b"1"*16)
86 ba2 = bytearray(b"2"*16)
87 buf1 = nbd.Buffer.from_bytearray(ba1)
88 buf2 = nbd.Buffer.from_bytearray(ba2)
94 while h.aio_in_flight() > 0:
103 assert out in [b"1"*16, b"2"*16]
104 assert t >= 2 and t <= 3
106 # Next pass: try to kick off unaligned first
107 print("unaligned first")
109 ba3 = bytearray(b"3"*12)
110 ba4 = bytearray(b"4"*16)
111 buf3 = nbd.Buffer.from_bytearray(ba3)
112 buf4 = nbd.Buffer.from_bytearray(ba4)
114 start_t = time.time()
115 h.aio_pwrite(buf3, 4)
116 h.aio_pwrite(buf4, 0)
118 while h.aio_in_flight() > 0:
127 assert out in [b"4"*4 + b"3"*12, b"4"*16]
130 # Next pass: try to kick off aligned first
131 print("aligned first")
132 ba5 = bytearray(b"5"*16)
133 ba6 = bytearray(b"6"*12)
134 buf5 = nbd.Buffer.from_bytearray(ba5)
135 buf6 = nbd.Buffer.from_bytearray(ba6)
138 start_t = time.time()
139 h.aio_pwrite(buf5, 0)
140 h.aio_pwrite(buf6, 4)
142 while h.aio_in_flight() > 0:
151 assert out in [b"5"*4 + b"6"*12, b"5"*16]
156 $TRUNCATE -s 16 blocksize-sharding.img
157 export witness
="$PWD/blocksize-sharding.tmp"
158 nbdkit
-U - --filter=blocksize
--filter=delay
eval delay-write
=2 \
159 config
='ln -sf "$(realpath "$3")" $tmpdir/$2' \
160 img
="$PWD/blocksize-sharding.img" tmp
="$PWD/blocksize-sharding.tmp" \
161 get_size
='echo 16' block_size
='echo 16 64K 1M' \
162 thread_model
='echo parallel' \
163 zero
='dd if=/dev/zero of=$tmpdir/img skip=$4 count=$3 \
164 iflag=count_bytes,skip_bytes' \
166 dd if=$tmpdir/img skip=$4 count=$3 iflag=count_bytes,skip_bytes
167 if [ -f $tmpdir/tmp ]; then sleep 4; fi ' \
168 pwrite
='dd of=$tmpdir/img seek=$4 conv=notrunc oflag=seek_bytes' \
169 --run 'nbdsh -u "$uri" -c "$script"'