summaryrefslogtreecommitdiffstats
path: root/src/ceph/qa/workunits/rbd/image_read.sh
diff options
context:
space:
mode:
Diffstat (limited to 'src/ceph/qa/workunits/rbd/image_read.sh')
-rwxr-xr-xsrc/ceph/qa/workunits/rbd/image_read.sh677
1 files changed, 0 insertions, 677 deletions
diff --git a/src/ceph/qa/workunits/rbd/image_read.sh b/src/ceph/qa/workunits/rbd/image_read.sh
deleted file mode 100755
index 907ce86..0000000
--- a/src/ceph/qa/workunits/rbd/image_read.sh
+++ /dev/null
@@ -1,677 +0,0 @@
-#!/bin/bash -e
-
-# Copyright (C) 2013 Inktank Storage, Inc.
-#
-# This is free software; see the source for copying conditions.
-# There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR
-# A PARTICULAR PURPOSE.
-#
-# This is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as
-# published by the Free Software Foundation version 2.
-
-# Alex Elder <elder@inktank.com>
-# April 10, 2013
-
-################################################################
-
-# The purpose of this test is to validate that data read from a
-# mapped rbd image is what it's expected to be.
-#
-# By default it creates an image and fills it with some data. It
-# then reads back the data at a series of offsets known to cover
-# various situations (such as reading the beginning, end, or the
-# entirety of an object, or doing a read that spans multiple
-# objects), and stashes the results in a set of local files.
-#
-# It also creates and maps a snapshot of the original image after
-# it's been filled, and reads back the same ranges of data from the
-# snapshot. It then compares the data read back with what was read
-# back from the original image, verifying they match.
-#
-# Clone functionality is tested as well, in which case a clone is
-# made of the snapshot, and the same ranges of data are again read
-# and compared with the original. In addition, a snapshot of that
-# clone is created, and a clone of *that* snapshot is put through
-# the same set of tests. (Clone testing can be optionally skipped.)
-
-################################################################
-
-# Default parameter values. Environment variables, if set, will
-# supercede these defaults. Such variables have names that begin
-# with "IMAGE_READ_", for e.g. use IMAGE_READ_PAGE_SIZE=65536
-# to use 65536 as the page size.
-
-DEFAULT_VERBOSE=true
-DEFAULT_TEST_CLONES=true
-DEFAULT_LOCAL_FILES=false
-DEFAULT_FORMAT=2
-DEFAULT_DOUBLE_ORDER=true
-DEFAULT_HALF_ORDER=false
-DEFAULT_PAGE_SIZE=4096
-DEFAULT_OBJECT_ORDER=22
-MIN_OBJECT_ORDER=12 # technically 9, but the rbd CLI enforces 12
-MAX_OBJECT_ORDER=32
-
-PROGNAME=$(basename $0)
-
-ORIGINAL=original-$$
-SNAP1=snap1-$$
-CLONE1=clone1-$$
-SNAP2=snap2-$$
-CLONE2=clone2-$$
-
-function err() {
- if [ $# -gt 0 ]; then
- echo "${PROGNAME}: $@" >&2
- fi
- exit 2
-}
-
-function usage() {
- if [ $# -gt 0 ]; then
- echo "" >&2
- echo "${PROGNAME}: $@" >&2
- fi
- echo "" >&2
- echo "Usage: ${PROGNAME} [<options>]" >&2
- echo "" >&2
- echo "options are:" >&2
- echo " -o object_order" >&2
- echo " must be ${MIN_OBJECT_ORDER}..${MAX_OBJECT_ORDER}" >&2
- echo " -p page_size (in bytes)" >&2
- echo " note: there must be at least 4 pages per object" >&2
- echo " -1" >&2
- echo " test using format 1 rbd images (default)" >&2
- echo " -2" >&2
- echo " test using format 2 rbd images" >&2
- echo " -c" >&2
- echo " also test rbd clone images (implies format 2)" >&2
- echo " -d" >&2
- echo " clone object order double its parent's (format 2)" >&2
- echo " -h" >&2
- echo " clone object order half of its parent's (format 2)" >&2
- echo " -l" >&2
- echo " use local files rather than rbd images" >&2
- echo " -v" >&2
- echo " disable reporting of what's going on" >&2
- echo "" >&2
- exit 1
-}
-
-function verbose() {
- [ "${VERBOSE}" = true ] && echo "$@"
- true # Don't let the verbose test spoil our return value
-}
-
-function quiet() {
- "$@" 2> /dev/null
-}
-
-function boolean_toggle() {
- [ $# -eq 1 ] || exit 99
- test "$1" = "true" && echo false || echo true
-}
-
-function parseargs() {
- local opts="o:p:12clv"
- local lopts="order:,page_size:,local,clone,verbose"
- local parsed
- local clone_order_msg
-
- # use values from environment if available
- VERBOSE="${IMAGE_READ_VERBOSE:-${DEFAULT_VERBOSE}}"
- TEST_CLONES="${IMAGE_READ_TEST_CLONES:-${DEFAULT_TEST_CLONES}}"
- LOCAL_FILES="${IMAGE_READ_LOCAL_FILES:-${DEFAULT_LOCAL_FILES}}"
- DOUBLE_ORDER="${IMAGE_READ_DOUBLE_ORDER:-${DEFAULT_DOUBLE_ORDER}}"
- HALF_ORDER="${IMAGE_READ_HALF_ORDER:-${DEFAULT_HALF_ORDER}}"
- FORMAT="${IMAGE_READ_FORMAT:-${DEFAULT_FORMAT}}"
- PAGE_SIZE="${IMAGE_READ_PAGE_SIZE:-${DEFAULT_PAGE_SIZE}}"
- OBJECT_ORDER="${IMAGE_READ_OBJECT_ORDER:-${DEFAULT_OBJECT_ORDER}}"
-
- parsed=$(getopt -o "${opts}" -l "${lopts}" -n "${PROGNAME}" -- "$@") ||
- usage
- eval set -- "${parsed}"
- while true; do
- case "$1" in
- -v|--verbose)
- VERBOSE=$(boolean_toggle "${VERBOSE}");;
- -c|--clone)
- TEST_CLONES=$(boolean_toggle "${TEST_CLONES}");;
- -d|--double)
- DOUBLE_ORDER=$(boolean_toggle "${DOUBLE_ORDER}");;
- -h|--half)
- HALF_ORDER=$(boolean_toggle "${HALF_ORDER}");;
- -l|--local)
- LOCAL_FILES=$(boolean_toggle "${LOCAL_FILES}");;
- -1|-2)
- FORMAT="${1:1}";;
- -p|--page_size)
- PAGE_SIZE="$2"; shift;;
- -o|--order)
- OBJECT_ORDER="$2"; shift;;
- --)
- shift; break;;
- *)
- err "getopt internal error"
- esac
- shift
- done
- [ $# -gt 0 ] && usage "excess arguments ($*)"
-
- if [ "${TEST_CLONES}" = true ]; then
- # If we're using different object orders for clones,
- # make sure the limits are updated accordingly. If
- # both "half" and "double" are specified, just
- # ignore them both.
- if [ "${DOUBLE_ORDER}" = true ]; then
- if [ "${HALF_ORDER}" = true ]; then
- DOUBLE_ORDER=false
- HALF_ORDER=false
- else
- ((MAX_OBJECT_ORDER -= 2))
- fi
- elif [ "${HALF_ORDER}" = true ]; then
- ((MIN_OBJECT_ORDER += 2))
- fi
- fi
-
- [ "${OBJECT_ORDER}" -lt "${MIN_OBJECT_ORDER}" ] &&
- usage "object order (${OBJECT_ORDER}) must be" \
- "at least ${MIN_OBJECT_ORDER}"
- [ "${OBJECT_ORDER}" -gt "${MAX_OBJECT_ORDER}" ] &&
- usage "object order (${OBJECT_ORDER}) must be" \
- "at most ${MAX_OBJECT_ORDER}"
-
- if [ "${TEST_CLONES}" = true ]; then
- if [ "${DOUBLE_ORDER}" = true ]; then
- ((CLONE1_ORDER = OBJECT_ORDER + 1))
- ((CLONE2_ORDER = OBJECT_ORDER + 2))
- clone_order_msg="double"
- elif [ "${HALF_ORDER}" = true ]; then
- ((CLONE1_ORDER = OBJECT_ORDER - 1))
- ((CLONE2_ORDER = OBJECT_ORDER - 2))
- clone_order_msg="half of"
- else
- CLONE1_ORDER="${OBJECT_ORDER}"
- CLONE2_ORDER="${OBJECT_ORDER}"
- clone_order_msg="the same as"
- fi
- fi
-
- [ "${TEST_CLONES}" != true ] || FORMAT=2
-
- OBJECT_SIZE=$(echo "2 ^ ${OBJECT_ORDER}" | bc)
- OBJECT_PAGES=$(echo "${OBJECT_SIZE} / ${PAGE_SIZE}" | bc)
- IMAGE_SIZE=$((2 * 16 * OBJECT_SIZE / (1024 * 1024)))
- [ "${IMAGE_SIZE}" -lt 1 ] && IMAGE_SIZE=1
- IMAGE_OBJECTS=$((IMAGE_SIZE * (1024 * 1024) / OBJECT_SIZE))
-
- [ "${OBJECT_PAGES}" -lt 4 ] &&
- usage "object size (${OBJECT_SIZE}) must be" \
- "at least 4 * page size (${PAGE_SIZE})"
-
- echo "parameters for this run:"
- echo " format ${FORMAT} images will be tested"
- echo " object order is ${OBJECT_ORDER}, so" \
- "objects are ${OBJECT_SIZE} bytes"
- echo " page size is ${PAGE_SIZE} bytes, so" \
- "there are are ${OBJECT_PAGES} pages in an object"
- echo " derived image size is ${IMAGE_SIZE} MB, so" \
- "there are ${IMAGE_OBJECTS} objects in an image"
- if [ "${TEST_CLONES}" = true ]; then
- echo " clone functionality will be tested"
- echo " object size for a clone will be ${clone_order_msg}"
- echo " the object size of its parent image"
- fi
-
- true # Don't let the clones test spoil our return value
-}
-
-function image_dev_path() {
- [ $# -eq 1 ] || exit 99
- local image_name="$1"
-
- if [ "${LOCAL_FILES}" = true ]; then
- echo "${TEMP}/${image_name}"
- return
- fi
-
- echo "/dev/rbd/rbd/${image_name}"
-}
-
-function out_data_dir() {
- [ $# -lt 2 ] || exit 99
- local out_data="${TEMP}/data"
- local image_name
-
- if [ $# -eq 1 ]; then
- image_name="$1"
- echo "${out_data}/${image_name}"
- else
- echo "${out_data}"
- fi
-}
-
-function setup() {
- verbose "===== setting up ====="
- TEMP=$(mktemp -d /tmp/rbd_image_read.XXXXX)
- mkdir -p $(out_data_dir)
-
- # create and fill the original image with some data
- create_image "${ORIGINAL}"
- map_image "${ORIGINAL}"
- fill_original
-
- # create a snapshot of the original
- create_image_snap "${ORIGINAL}" "${SNAP1}"
- map_image_snap "${ORIGINAL}" "${SNAP1}"
-
- if [ "${TEST_CLONES}" = true ]; then
- # create a clone of the original snapshot
- create_snap_clone "${ORIGINAL}" "${SNAP1}" \
- "${CLONE1}" "${CLONE1_ORDER}"
- map_image "${CLONE1}"
-
- # create a snapshot of that clone
- create_image_snap "${CLONE1}" "${SNAP2}"
- map_image_snap "${CLONE1}" "${SNAP2}"
-
- # create a clone of that clone's snapshot
- create_snap_clone "${CLONE1}" "${SNAP2}" \
- "${CLONE2}" "${CLONE2_ORDER}"
- map_image "${CLONE2}"
- fi
-}
-
-function teardown() {
- verbose "===== cleaning up ====="
- if [ "${TEST_CLONES}" = true ]; then
- unmap_image "${CLONE2}" || true
- destroy_snap_clone "${CLONE1}" "${SNAP2}" "${CLONE2}" || true
-
- unmap_image_snap "${CLONE1}" "${SNAP2}" || true
- destroy_image_snap "${CLONE1}" "${SNAP2}" || true
-
- unmap_image "${CLONE1}" || true
- destroy_snap_clone "${ORIGINAL}" "${SNAP1}" "${CLONE1}" || true
- fi
- unmap_image_snap "${ORIGINAL}" "${SNAP1}" || true
- destroy_image_snap "${ORIGINAL}" "${SNAP1}" || true
- unmap_image "${ORIGINAL}" || true
- destroy_image "${ORIGINAL}" || true
-
- rm -rf $(out_data_dir)
- rmdir "${TEMP}"
-}
-
-function create_image() {
- [ $# -eq 1 ] || exit 99
- local image_name="$1"
- local image_path
- local bytes
-
- verbose "creating image \"${image_name}\""
- if [ "${LOCAL_FILES}" = true ]; then
- image_path=$(image_dev_path "${image_name}")
- bytes=$(echo "${IMAGE_SIZE} * 1024 * 1024 - 1" | bc)
- quiet dd if=/dev/zero bs=1 count=1 seek="${bytes}" \
- of="${image_path}"
- return
- fi
-
- rbd create "${image_name}" --image-format "${FORMAT}" \
- --size "${IMAGE_SIZE}" --order "${OBJECT_ORDER}" \
- --image-shared
-}
-
-function destroy_image() {
- [ $# -eq 1 ] || exit 99
- local image_name="$1"
- local image_path
-
- verbose "destroying image \"${image_name}\""
- if [ "${LOCAL_FILES}" = true ]; then
- image_path=$(image_dev_path "${image_name}")
- rm -f "${image_path}"
- return
- fi
-
- rbd rm "${image_name}"
-}
-
-function map_image() {
- [ $# -eq 1 ] || exit 99
- local image_name="$1" # can be image@snap too
-
- if [ "${LOCAL_FILES}" = true ]; then
- return
- fi
-
- sudo rbd map "${image_name}"
-}
-
-function unmap_image() {
- [ $# -eq 1 ] || exit 99
- local image_name="$1" # can be image@snap too
- local image_path
-
- if [ "${LOCAL_FILES}" = true ]; then
- return
- fi
- image_path=$(image_dev_path "${image_name}")
-
- if [ -e "${image_path}" ]; then
- sudo rbd unmap "${image_path}"
- fi
-}
-
-function map_image_snap() {
- [ $# -eq 2 ] || exit 99
- local image_name="$1"
- local snap_name="$2"
- local image_snap
-
- if [ "${LOCAL_FILES}" = true ]; then
- return
- fi
-
- image_snap="${image_name}@${snap_name}"
- map_image "${image_snap}"
-}
-
-function unmap_image_snap() {
- [ $# -eq 2 ] || exit 99
- local image_name="$1"
- local snap_name="$2"
- local image_snap
-
- if [ "${LOCAL_FILES}" = true ]; then
- return
- fi
-
- image_snap="${image_name}@${snap_name}"
- unmap_image "${image_snap}"
-}
-
-function create_image_snap() {
- [ $# -eq 2 ] || exit 99
- local image_name="$1"
- local snap_name="$2"
- local image_snap="${image_name}@${snap_name}"
- local image_path
- local snap_path
-
- verbose "creating snapshot \"${snap_name}\"" \
- "of image \"${image_name}\""
- if [ "${LOCAL_FILES}" = true ]; then
- image_path=$(image_dev_path "${image_name}")
- snap_path=$(image_dev_path "${image_snap}")
-
- cp "${image_path}" "${snap_path}"
- return
- fi
-
- rbd snap create "${image_snap}"
-}
-
-function destroy_image_snap() {
- [ $# -eq 2 ] || exit 99
- local image_name="$1"
- local snap_name="$2"
- local image_snap="${image_name}@${snap_name}"
- local snap_path
-
- verbose "destroying snapshot \"${snap_name}\"" \
- "of image \"${image_name}\""
- if [ "${LOCAL_FILES}" = true ]; then
- snap_path=$(image_dev_path "${image_snap}")
- rm -rf "${snap_path}"
- return
- fi
-
- rbd snap rm "${image_snap}"
-}
-
-function create_snap_clone() {
- [ $# -eq 4 ] || exit 99
- local image_name="$1"
- local snap_name="$2"
- local clone_name="$3"
- local clone_order="$4"
- local image_snap="${image_name}@${snap_name}"
- local snap_path
- local clone_path
-
- verbose "creating clone image \"${clone_name}\"" \
- "of image snapshot \"${image_name}@${snap_name}\""
- if [ "${LOCAL_FILES}" = true ]; then
- snap_path=$(image_dev_path "${image_name}@${snap_name}")
- clone_path=$(image_dev_path "${clone_name}")
-
- cp "${snap_path}" "${clone_path}"
- return
- fi
-
- rbd snap protect "${image_snap}"
- rbd clone --order "${clone_order}" --image-shared \
- "${image_snap}" "${clone_name}"
-}
-
-function destroy_snap_clone() {
- [ $# -eq 3 ] || exit 99
- local image_name="$1"
- local snap_name="$2"
- local clone_name="$3"
- local image_snap="${image_name}@${snap_name}"
- local clone_path
-
- verbose "destroying clone image \"${clone_name}\""
- if [ "${LOCAL_FILES}" = true ]; then
- clone_path=$(image_dev_path "${clone_name}")
-
- rm -rf "${clone_path}"
- return
- fi
-
- rbd rm "${clone_name}"
- rbd snap unprotect "${image_snap}"
-}
-
-# function that produces "random" data with which to fill the image
-function source_data() {
- while quiet dd if=/bin/bash skip=$(($$ % 199)) bs="${PAGE_SIZE}"; do
- : # Just do the dd
- done
-}
-
-function fill_original() {
- local image_path=$(image_dev_path "${ORIGINAL}")
-
- verbose "filling original image"
- # Fill 16 objects worth of "random" data
- source_data |
- quiet dd bs="${PAGE_SIZE}" count=$((16 * OBJECT_PAGES)) \
- of="${image_path}"
-}
-
-function do_read() {
- [ $# -eq 3 -o $# -eq 4 ] || exit 99
- local image_name="$1"
- local offset="$2"
- local length="$3"
- [ "${length}" -gt 0 ] || err "do_read: length must be non-zero"
- local image_path=$(image_dev_path "${image_name}")
- local out_data=$(out_data_dir "${image_name}")
- local range=$(printf "%06u~%04u" "${offset}" "${length}")
- local out_file
-
- [ $# -eq 4 ] && offset=$((offset + 16 * OBJECT_PAGES))
-
- verbose "reading \"${image_name}\" pages ${range}"
-
- out_file="${out_data}/pages_${range}"
-
- quiet dd bs="${PAGE_SIZE}" skip="${offset}" count="${length}" \
- if="${image_path}" of="${out_file}"
-}
-
-function one_pass() {
- [ $# -eq 1 -o $# -eq 2 ] || exit 99
- local image_name="$1"
- local extended
- [ $# -eq 2 ] && extended="true"
- local offset
- local length
-
- offset=0
-
- # +-----------+-----------+---
- # |X:X:X...X:X| : : ... : | :
- # +-----------+-----------+---
- length="${OBJECT_PAGES}"
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+---
- # : |X: : ... : | :
- # ---+-----------+---
- length=1
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+---
- # : | :X: ... : | :
- # ---+-----------+---
- length=1
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+---
- # : | : :X...X: | :
- # ---+-----------+---
- length=$((OBJECT_PAGES - 3))
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+---
- # : | : : ... :X| :
- # ---+-----------+---
- length=1
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+---
- # : |X:X:X...X:X| :
- # ---+-----------+---
- length="${OBJECT_PAGES}"
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- offset=$((offset + 1)) # skip 1
-
- # ---+-----------+---
- # : | :X:X...X:X| :
- # ---+-----------+---
- length=$((OBJECT_PAGES - 1))
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+-----------+---
- # : |X:X:X...X:X|X: : ... : | :
- # ---+-----------+-----------+---
- length=$((OBJECT_PAGES + 1))
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+-----------+---
- # : | :X:X...X:X|X: : ... : | :
- # ---+-----------+-----------+---
- length="${OBJECT_PAGES}"
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+-----------+---
- # : | :X:X...X:X|X:X: ... : | :
- # ---+-----------+-----------+---
- length=$((OBJECT_PAGES + 1))
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # ---+-----------+-----------+---
- # : | : :X...X:X|X:X:X...X:X| :
- # ---+-----------+-----------+---
- length=$((2 * OBJECT_PAGES + 2))
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- offset=$((offset + 1)) # skip 1
-
- # ---+-----------+-----------+-----
- # : | :X:X...X:X|X:X:X...X:X|X: :
- # ---+-----------+-----------+-----
- length=$((2 * OBJECT_PAGES))
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- offset=$((offset + length))
-
- # --+-----------+-----------+--------
- # : | :X:X...X:X|X:X:X...X:X|X:X: :
- # --+-----------+-----------+--------
- length=2049
- length=$((2 * OBJECT_PAGES + 1))
- do_read "${image_name}" "${offset}" "${length}" ${extended}
- # offset=$((offset + length))
-}
-
-function run_using() {
- [ $# -eq 1 ] || exit 99
- local image_name="$1"
- local out_data=$(out_data_dir "${image_name}")
-
- verbose "===== running using \"${image_name}\" ====="
- mkdir -p "${out_data}"
- one_pass "${image_name}"
- one_pass "${image_name}" extended
-}
-
-function compare() {
- [ $# -eq 1 ] || exit 99
- local image_name="$1"
- local out_data=$(out_data_dir "${image_name}")
- local original=$(out_data_dir "${ORIGINAL}")
-
- verbose "===== comparing \"${image_name}\" ====="
- for i in $(ls "${original}"); do
- verbose compare "\"${image_name}\" \"${i}\""
- cmp "${original}/${i}" "${out_data}/${i}"
- done
- [ "${image_name}" = "${ORIGINAL}" ] || rm -rf "${out_data}"
-}
-
-function doit() {
- [ $# -eq 1 ] || exit 99
- local image_name="$1"
-
- run_using "${image_name}"
- compare "${image_name}"
-}
-
-########## Start
-
-parseargs "$@"
-
-trap teardown EXIT HUP INT
-setup
-
-run_using "${ORIGINAL}"
-doit "${ORIGINAL}@${SNAP1}"
-if [ "${TEST_CLONES}" = true ]; then
- doit "${CLONE1}"
- doit "${CLONE1}@${SNAP2}"
- doit "${CLONE2}"
-fi
-rm -rf $(out_data_dir "${ORIGINAL}")
-
-echo "Success!"
-
-exit 0