| 1 | #!/bin/bash |
| 2 | |
| 3 | blkzone=$(type -p blkzone 2>/dev/null) |
| 4 | sg_inq=$(type -p sg_inq 2>/dev/null) |
| 5 | zbc_report_zones=$(type -p zbc_report_zones 2>/dev/null) |
| 6 | zbc_reset_zone=$(type -p zbc_reset_zone 2>/dev/null) |
| 7 | zbc_info=$(type -p zbc_info 2>/dev/null) |
| 8 | if [ -z "${blkzone}" ] && |
| 9 | { [ -z "${zbc_report_zones}" ] || [ -z "${zbc_reset_zone}" ]; }; then |
| 10 | echo "Error: neither blkzone nor zbc_report_zones is available" |
| 11 | exit 1 |
| 12 | fi |
| 13 | |
| 14 | if [ -n "${use_libzbc}" ] && |
| 15 | { [ -z "${zbc_report_zones}" ] || [ -z "${zbc_reset_zone}" ] || |
| 16 | [ -z "${zbc_info}" ]; }; then |
| 17 | echo "Error: zbc_report_zones, or zbc_reset_zone or zbc_info is not available" |
| 18 | echo "Error: reinstall libzbc tools" |
| 19 | exit 1 |
| 20 | fi |
| 21 | |
| 22 | # Reports the starting sector and length of the first sequential zone of device |
| 23 | # $1. |
| 24 | first_sequential_zone() { |
| 25 | local dev=$1 |
| 26 | |
| 27 | if [ -n "${blkzone}" ] && [ ! -n "${use_libzbc}" ]; then |
| 28 | ${blkzone} report "$dev" | |
| 29 | sed -n 's/^[[:blank:]]*start:[[:blank:]]\([0-9a-zA-Z]*\),[[:blank:]]len[[:blank:]]\([0-9a-zA-Z]*\),.*type:[[:blank:]]2(.*/\1 \2/p' | |
| 30 | { |
| 31 | read -r starting_sector length && |
| 32 | # Convert from hex to decimal |
| 33 | echo $((starting_sector)) $((length)) |
| 34 | } |
| 35 | else |
| 36 | ${zbc_report_zones} "$dev" | |
| 37 | sed -n 's/^Zone [0-9]*: type 0x2 .*, sector \([0-9]*\), \([0-9]*\) sectors,.*$/\1 \2/p' | |
| 38 | head -n1 |
| 39 | fi |
| 40 | } |
| 41 | |
| 42 | max_open_zones() { |
| 43 | local dev=$1 |
| 44 | |
| 45 | if [ -n "${sg_inq}" ] && [ ! -n "${use_libzbc}" ]; then |
| 46 | if ! ${sg_inq} -e --page=0xB6 --len=20 --hex "$dev" 2> /dev/null; then |
| 47 | # Non scsi device such as null_blk can not return max open zones. |
| 48 | # Use default value. |
| 49 | echo 128 |
| 50 | else |
| 51 | ${sg_inq} -e --page=0xB6 --len=20 --hex "$dev" | tail -1 | |
| 52 | { |
| 53 | read -r offset b0 b1 b2 b3 trailer || return $? |
| 54 | # Convert from hex to decimal |
| 55 | max_nr_open_zones=$((0x${b0})) |
| 56 | max_nr_open_zones=$((max_nr_open_zones * 256 + 0x${b1})) |
| 57 | max_nr_open_zones=$((max_nr_open_zones * 256 + 0x${b2})) |
| 58 | max_nr_open_zones=$((max_nr_open_zones * 256 + 0x${b3})) |
| 59 | echo ${max_nr_open_zones} |
| 60 | } |
| 61 | fi |
| 62 | else |
| 63 | ${zbc_report_zones} "$dev" | |
| 64 | sed -n 's/^[[:blank:]]*Maximum number of open sequential write required zones:[[:blank:]]*//p' |
| 65 | fi |
| 66 | } |
| 67 | |
| 68 | is_zbc() { |
| 69 | local dev=$1 |
| 70 | |
| 71 | [[ -z "$(${zbc_info} "$dev" | grep "is not a zoned block device")" ]] |
| 72 | } |
| 73 | |
| 74 | zbc_logical_block_size() { |
| 75 | local dev=$1 |
| 76 | |
| 77 | ${zbc_info} "$dev" | |
| 78 | grep "logical blocks" | |
| 79 | sed -n 's/^[[:blank:]]*[0-9]* logical blocks of[[:blank:]]*//p' | |
| 80 | sed 's/ B//' |
| 81 | } |
| 82 | |
| 83 | zbc_disk_sectors() { |
| 84 | local dev=$1 |
| 85 | |
| 86 | zbc_info "$dev" | |
| 87 | grep "512-bytes sectors" | |
| 88 | sed -e 's/[[:blank:]]*\([0-9]*\)512-bytes sectors.*/\1/' |
| 89 | } |
| 90 | |
| 91 | # Reset the write pointer of one zone on device $1 at offset $2. The offset |
| 92 | # must be specified in units of 512 byte sectors. Offset -1 means reset all |
| 93 | # zones. |
| 94 | reset_zone() { |
| 95 | local dev=$1 offset=$2 sectors |
| 96 | |
| 97 | if [ -n "${blkzone}" ] && [ ! -n "${use_libzbc}" ]; then |
| 98 | if [ "$offset" -lt 0 ]; then |
| 99 | sectors=$(<"/sys/class/block/${dev#/dev/}/size") |
| 100 | ${blkzone} reset -o "${offset}" -l "$sectors" "$dev" |
| 101 | else |
| 102 | ${blkzone} reset -o "${offset}" -c 1 "$dev" |
| 103 | fi |
| 104 | else |
| 105 | if [ "$offset" -lt 0 ]; then |
| 106 | ${zbc_reset_zone} -all "$dev" "${offset}" >/dev/null |
| 107 | else |
| 108 | ${zbc_reset_zone} -sector "$dev" "${offset}" >/dev/null |
| 109 | fi |
| 110 | fi |
| 111 | } |
| 112 | |
| 113 | # Extract the number of bytes that have been transferred from a line like |
| 114 | # READ: bw=6847KiB/s (7011kB/s), 6847KiB/s-6847KiB/s (7011kB/s-7011kB/s), io=257MiB (269MB), run=38406-38406msec |
| 115 | fio_io() { |
| 116 | sed -n 's/^[[:blank:]]*'"$1"'.*, io=\([^[:blank:]]*\).*/\1/p' | |
| 117 | tail -n 1 | |
| 118 | ( |
| 119 | read -r io; |
| 120 | # Parse <number>.<number><suffix> into n1, n2 and s. See also |
| 121 | # num2str(). |
| 122 | shopt -s extglob |
| 123 | n1=${io%${io##*([0-9])}} |
| 124 | s=${io#${io%%*([a-zA-Z])}} |
| 125 | n2=${io#${n1}} |
| 126 | n2=${n2#.} |
| 127 | n2=${n2%$s}000 |
| 128 | n2=${n2:0:3} |
| 129 | case "$s" in |
| 130 | KiB) m=10;; |
| 131 | MiB) m=20;; |
| 132 | GiB) m=30;; |
| 133 | B) m=0;; |
| 134 | *) return 1;; |
| 135 | esac |
| 136 | [ -n "$n1" ] || return 1 |
| 137 | echo $(((n1 << m) + (n2 << m) / 1000)) |
| 138 | ) |
| 139 | } |
| 140 | |
| 141 | fio_read() { |
| 142 | fio_io 'READ:' |
| 143 | } |
| 144 | |
| 145 | fio_written() { |
| 146 | fio_io 'WRITE:' |
| 147 | } |
| 148 | |
| 149 | fio_reset_count() { |
| 150 | local count |
| 151 | |
| 152 | count=$(sed -n 's/^.*write:[^;]*; \([0-9]*\) zone resets$/\1/p') |
| 153 | echo "${count:-0}" |
| 154 | } |