024 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #!/usr/bin/env bash
  2. # group: rw backing auto quick
  3. #
  4. # Rebasing COW images
  5. #
  6. # Copyright (C) 2009 Red Hat, Inc.
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. # creator
  22. owner=kwolf@redhat.com
  23. seq=`basename $0`
  24. echo "QA output created by $seq"
  25. status=1 # failure is the default!
  26. _cleanup()
  27. {
  28. _cleanup_test_img
  29. _rm_test_img "$TEST_DIR/t.$IMGFMT.base_old"
  30. _rm_test_img "$TEST_DIR/t.$IMGFMT.base_new"
  31. _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT"
  32. _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base_old"
  33. _rm_test_img "$TEST_DIR/subdir/t.$IMGFMT.base_new"
  34. rmdir "$TEST_DIR/subdir" 2> /dev/null
  35. }
  36. trap "_cleanup; exit \$status" 0 1 2 3 15
  37. # get standard environment, filters and checks
  38. . ./common.rc
  39. . ./common.filter
  40. . ./common.pattern
  41. # Currently only qcow2 and qed support rebasing
  42. _supported_fmt qcow2 qed
  43. _supported_proto file
  44. _supported_os Linux
  45. CLUSTER_SIZE=65536
  46. # Cluster allocations to be tested:
  47. #
  48. # Backing (old) 11 -- 11 -- 11 -- 11 --
  49. # Backing (new) 22 22 -- -- 22 22 -- --
  50. # COW image 33 33 33 33 -- -- -- --
  51. #
  52. # The pattern is written twice to have both an alloc -> non-alloc and a
  53. # non-alloc -> alloc transition in the COW image.
  54. echo "Creating backing file"
  55. echo
  56. TEST_IMG_SAVE="$TEST_IMG"
  57. TEST_IMG="$TEST_IMG.base_old"
  58. _make_test_img 1G
  59. io_pattern writev 0 $CLUSTER_SIZE $((2 * CLUSTER_SIZE)) 8 0x11
  60. TEST_IMG="$TEST_IMG_SAVE.base_new"
  61. echo "Creating new backing file"
  62. echo
  63. _make_test_img 1G
  64. io_pattern writev 0 $((2 * CLUSTER_SIZE)) $((4 * CLUSTER_SIZE)) 4 0x22
  65. TEST_IMG="$TEST_IMG_SAVE"
  66. echo "Creating COW image"
  67. echo
  68. _make_test_img -b "$TEST_IMG.base_old" -F $IMGFMT 1G
  69. io_pattern writev 0 $((4 * CLUSTER_SIZE)) 0 1 0x33
  70. io_pattern writev $((8 * CLUSTER_SIZE)) $((4 * CLUSTER_SIZE)) 0 1 0x33
  71. echo "Read before the rebase to make sure everything is set up correctly"
  72. echo
  73. io_pattern readv $((0 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  74. io_pattern readv $((1 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  75. io_pattern readv $((2 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  76. io_pattern readv $((3 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  77. io_pattern readv $((4 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
  78. io_pattern readv $((5 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
  79. io_pattern readv $((6 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
  80. io_pattern readv $((7 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
  81. io_pattern readv $((8 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  82. io_pattern readv $((9 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  83. io_pattern readv $((10 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  84. io_pattern readv $((11 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  85. io_pattern readv $((12 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
  86. io_pattern readv $((13 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
  87. io_pattern readv $((14 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
  88. io_pattern readv $((15 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
  89. echo
  90. echo Rebase and test again
  91. echo
  92. $QEMU_IMG rebase -b "$TEST_IMG.base_new" -F $IMGFMT "$TEST_IMG"
  93. io_pattern readv $((0 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  94. io_pattern readv $((1 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  95. io_pattern readv $((2 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  96. io_pattern readv $((3 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  97. io_pattern readv $((4 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
  98. io_pattern readv $((5 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
  99. io_pattern readv $((6 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
  100. io_pattern readv $((7 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
  101. io_pattern readv $((8 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  102. io_pattern readv $((9 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  103. io_pattern readv $((10 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  104. io_pattern readv $((11 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x33
  105. io_pattern readv $((12 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
  106. io_pattern readv $((13 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
  107. io_pattern readv $((14 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x11
  108. io_pattern readv $((15 * CLUSTER_SIZE)) $CLUSTER_SIZE 0 1 0x00
  109. echo
  110. echo "=== Test rebase in a subdirectory of the working directory ==="
  111. echo
  112. # Clean up the old images beforehand so they do not interfere with
  113. # this test
  114. _cleanup
  115. mkdir "$TEST_DIR/subdir"
  116. # Relative to the overlay
  117. BASE_OLD_OREL="t.$IMGFMT.base_old"
  118. BASE_NEW_OREL="t.$IMGFMT.base_new"
  119. # Relative to $TEST_DIR (which is going to be our working directory)
  120. OVERLAY_WREL="subdir/t.$IMGFMT"
  121. BASE_OLD="$TEST_DIR/subdir/$BASE_OLD_OREL"
  122. BASE_NEW="$TEST_DIR/subdir/$BASE_NEW_OREL"
  123. OVERLAY="$TEST_DIR/$OVERLAY_WREL"
  124. # Test done here:
  125. #
  126. # Backing (old): 11 11 -- 11
  127. # Backing (new): -- 22 22 11
  128. # Overlay: -- -- -- --
  129. #
  130. # Rebasing works, we have verified that above. Here, we just want to
  131. # see that rebasing is done for the correct target backing file.
  132. TEST_IMG=$BASE_OLD _make_test_img 1M
  133. TEST_IMG=$BASE_NEW _make_test_img 1M
  134. TEST_IMG=$OVERLAY _make_test_img -b "$BASE_OLD_OREL" -F $IMGFMT 1M
  135. echo
  136. $QEMU_IO "$BASE_OLD" \
  137. -c "write -P 0x11 $((0 * CLUSTER_SIZE)) $((2 * CLUSTER_SIZE))" \
  138. -c "write -P 0x11 $((3 * CLUSTER_SIZE)) $((1 * CLUSTER_SIZE))" \
  139. | _filter_qemu_io
  140. $QEMU_IO "$BASE_NEW" \
  141. -c "write -P 0x22 $((1 * CLUSTER_SIZE)) $((2 * CLUSTER_SIZE))" \
  142. -c "write -P 0x11 $((3 * CLUSTER_SIZE)) $((1 * CLUSTER_SIZE))" \
  143. | _filter_qemu_io
  144. echo
  145. pushd "$TEST_DIR" >/dev/null
  146. $QEMU_IMG rebase -f "$IMGFMT" -b "$BASE_NEW_OREL" -F $IMGFMT "$OVERLAY_WREL"
  147. popd >/dev/null
  148. # Verify the backing path is correct
  149. TEST_IMG=$OVERLAY _img_info | grep '^backing file:'
  150. echo
  151. # Verify the data is correct
  152. $QEMU_IO "$OVERLAY" \
  153. -c "read -P 0x11 $((0 * CLUSTER_SIZE)) $CLUSTER_SIZE" \
  154. -c "read -P 0x11 $((1 * CLUSTER_SIZE)) $CLUSTER_SIZE" \
  155. -c "read -P 0x00 $((2 * CLUSTER_SIZE)) $CLUSTER_SIZE" \
  156. -c "read -P 0x11 $((3 * CLUSTER_SIZE)) $CLUSTER_SIZE" \
  157. | _filter_qemu_io
  158. echo
  159. # Verify that cluster #3 is not allocated (because it is the same in
  160. # $BASE_OLD and $BASE_NEW)
  161. $QEMU_IMG map "$OVERLAY" | _filter_qemu_img_map
  162. # Check that rebase within the chain is working when
  163. # overlay_size > old_backing_size
  164. #
  165. # base_new <-- base_old <-- overlay
  166. #
  167. # Backing (new): 11 11 11 11 11
  168. # Backing (old): 22 22 22 22
  169. # Overlay: -- -- -- -- --
  170. #
  171. # As a result, overlay should contain data identical to base_old, with the
  172. # last cluster remaining unallocated.
  173. echo
  174. echo "=== Test rebase within one backing chain ==="
  175. echo
  176. echo "Creating backing chain"
  177. echo
  178. TEST_IMG=$BASE_NEW _make_test_img $(( CLUSTER_SIZE * 5 ))
  179. TEST_IMG=$BASE_OLD _make_test_img -b "$BASE_NEW" -F $IMGFMT \
  180. $(( CLUSTER_SIZE * 4 ))
  181. TEST_IMG=$OVERLAY _make_test_img -b "$BASE_OLD" -F $IMGFMT \
  182. $(( CLUSTER_SIZE * 5 ))
  183. echo
  184. echo "Fill backing files with data"
  185. echo
  186. $QEMU_IO "$BASE_NEW" -c "write -P 0x11 0 $(( CLUSTER_SIZE * 5 ))" \
  187. | _filter_qemu_io
  188. $QEMU_IO "$BASE_OLD" -c "write -P 0x22 0 $(( CLUSTER_SIZE * 4 ))" \
  189. | _filter_qemu_io
  190. echo
  191. echo "Check the last cluster is zeroed in overlay before the rebase"
  192. echo
  193. $QEMU_IO "$OVERLAY" -c "read -P 0x00 $(( CLUSTER_SIZE * 4 )) $CLUSTER_SIZE" \
  194. | _filter_qemu_io
  195. echo
  196. echo "Rebase onto another image in the same chain"
  197. echo
  198. $QEMU_IMG rebase -b "$BASE_NEW" -F $IMGFMT "$OVERLAY"
  199. echo "Verify that data is read the same before and after rebase"
  200. echo
  201. # Verify the first 4 clusters are still read the same as in the old base
  202. $QEMU_IO "$OVERLAY" -c "read -P 0x22 0 $(( CLUSTER_SIZE * 4 ))" \
  203. | _filter_qemu_io
  204. # Verify the last cluster still reads as zeroes
  205. $QEMU_IO "$OVERLAY" -c "read -P 0x00 $(( CLUSTER_SIZE * 4 )) $CLUSTER_SIZE" \
  206. | _filter_qemu_io
  207. echo
  208. # Check that rebase within the chain is working when
  209. # overlay cluster size > backings cluster size
  210. # (here overlay cluster size == 2 * backings cluster size)
  211. #
  212. # base_new <-- base_old <-- overlay
  213. #
  214. # Backing (new): -- -- -- -- -- --
  215. # Backing (old): -- 11 -- -- 22 --
  216. # Overlay: |-- --|-- --|-- --|
  217. #
  218. # We should end up having 1st and 3rd cluster allocated, and their halves
  219. # being read as zeroes.
  220. echo
  221. echo "=== Test rebase with different cluster sizes ==="
  222. echo
  223. echo "Creating backing chain"
  224. echo
  225. TEST_IMG=$BASE_NEW _make_test_img $(( CLUSTER_SIZE * 6 ))
  226. TEST_IMG=$BASE_OLD _make_test_img -b "$BASE_NEW" -F $IMGFMT \
  227. $(( CLUSTER_SIZE * 6 ))
  228. CLUSTER_SIZE=$(( CLUSTER_SIZE * 2 )) TEST_IMG=$OVERLAY \
  229. _make_test_img -b "$BASE_OLD" -F $IMGFMT $(( CLUSTER_SIZE * 6 ))
  230. TEST_IMG=$OVERLAY _img_info | grep -v '^backing file format:'
  231. echo
  232. echo "Fill backing files with data"
  233. echo
  234. $QEMU_IO "$BASE_OLD" -c "write -P 0x11 $CLUSTER_SIZE $CLUSTER_SIZE" \
  235. -c "write -P 0x22 $(( CLUSTER_SIZE * 4 )) $CLUSTER_SIZE" \
  236. | _filter_qemu_io
  237. echo
  238. echo "Rebase onto another image in the same chain"
  239. echo
  240. $QEMU_IMG rebase -b "$BASE_NEW" -F $IMGFMT "$OVERLAY"
  241. echo "Verify that data is read the same before and after rebase"
  242. echo
  243. $QEMU_IO "$OVERLAY" -c "read -P 0x00 0 $CLUSTER_SIZE" \
  244. -c "read -P 0x11 $CLUSTER_SIZE $CLUSTER_SIZE" \
  245. -c "read -P 0x00 $(( CLUSTER_SIZE * 2 )) $(( CLUSTER_SIZE * 2 ))" \
  246. -c "read -P 0x22 $(( CLUSTER_SIZE * 4 )) $CLUSTER_SIZE" \
  247. -c "read -P 0x00 $(( CLUSTER_SIZE * 5 )) $CLUSTER_SIZE" \
  248. | _filter_qemu_io
  249. echo
  250. echo "Verify that untouched cluster remains unallocated"
  251. echo
  252. $QEMU_IMG map "$OVERLAY" | _filter_qemu_img_map
  253. echo
  254. # success, all done
  255. echo "*** done"
  256. rm -f $seq.full
  257. status=0