5 function expect_false() {
6 if "$@"; then return 1; else return 0; fi
9 function assert_locked() {
10 local dev_id="${1#/dev/rbd}"
13 client_addr="$(< $SYSFS_DIR/$dev_id/client_addr)"
16 client_id="$(< $SYSFS_DIR/$dev_id/client_id)"
17 # client4324 -> client.4324
18 client_id="client.${client_id#client}"
21 watch_cookie="$(rados -p rbd listwatchers rbd_header.$IMAGE_ID |
22 grep $client_id | cut -d ' ' -f 3 | cut -d '=' -f 2)"
23 [[ $(echo -n "$watch_cookie" | grep -c '^') -eq 1 ]]
26 actual="$(rados -p rbd --format=json lock info rbd_header.$IMAGE_ID rbd_lock |
30 expected="$(cat <<EOF | python -m json.tool
34 "addr": "$client_addr",
35 "cookie": "auto $watch_cookie",
37 "expiration": "0.000000",
48 [ "$actual" = "$expected" ]
51 function assert_unlocked() {
52 rados -p rbd --format=json lock info rbd_header.$IMAGE_ID rbd_lock |
56 SYSFS_DIR="/sys/bus/rbd/devices"
57 IMAGE_NAME="exclusive-option-test"
59 rbd create --size 1 --image-feature '' $IMAGE_NAME
61 IMAGE_ID="$(rbd info --format=json $IMAGE_NAME |
62 python -c "import sys, json; print json.load(sys.stdin)['block_name_prefix'].split('.')[1]")"
64 DEV=$(sudo rbd map $IMAGE_NAME)
69 expect_false sudo rbd map -o exclusive $IMAGE_NAME
72 rbd feature enable $IMAGE_NAME exclusive-lock
73 rbd snap create $IMAGE_NAME@snap
75 DEV=$(sudo rbd map $IMAGE_NAME)
80 DEV=$(sudo rbd map -o exclusive $IMAGE_NAME)
82 [[ $(blockdev --getro $DEV) -eq 0 ]]
86 DEV=$(sudo rbd map -o exclusive $IMAGE_NAME@snap)
88 [[ $(blockdev --getro $DEV) -eq 1 ]]
92 DEV=$(sudo rbd map -o exclusive,ro $IMAGE_NAME)
94 [[ $(blockdev --getro $DEV) -eq 1 ]]
99 DEV=$(sudo rbd map --exclusive --read-only $IMAGE_NAME)
101 [[ $(blockdev --getro $DEV) -eq 1 ]]
105 DEV=$(sudo rbd map $IMAGE_NAME)
107 dd if=/dev/urandom of=$DEV bs=4k count=10 oflag=direct
109 OTHER_DEV=$(sudo rbd map -o noshare,exclusive $IMAGE_NAME)
110 assert_locked $OTHER_DEV
112 sudo rbd unmap $OTHER_DEV
115 DEV=$(sudo rbd map -o exclusive $IMAGE_NAME)
117 expect_false sudo rbd map -o noshare,exclusive $IMAGE_NAME
122 DEV=$(sudo rbd map -o exclusive $IMAGE_NAME)
124 OTHER_DEV=$(sudo rbd map -o noshare $IMAGE_NAME)
125 dd if=/dev/urandom of=$OTHER_DEV bs=4k count=10 oflag=direct &
129 [ "$(ps -o stat= $PID)" = "D" ]
132 assert_locked $OTHER_DEV
133 sudo rbd unmap $OTHER_DEV
136 DEV=$(sudo rbd map -o exclusive $IMAGE_NAME)
138 sudo rbd map -o noshare,lock_on_read $IMAGE_NAME &
142 PID="$(ps -o pid= --ppid $SUDO_PID)"
143 [ "$(ps -o stat= $PID)" = "Dl" ]
146 assert_locked $OTHER_DEV
147 sudo rbd unmap $OTHER_DEV
150 # induce a watch error after 30 seconds
151 DEV=$(sudo rbd map -o exclusive,osdkeepalive=60 $IMAGE_NAME)
153 OLD_WATCHER="$(rados -p rbd listwatchers rbd_header.$IMAGE_ID)"
156 NEW_WATCHER="$(rados -p rbd listwatchers rbd_header.$IMAGE_ID)"
157 # same client_id, old cookie < new cookie
158 [ "$(echo "$OLD_WATCHER" | cut -d ' ' -f 2)" = \
159 "$(echo "$NEW_WATCHER" | cut -d ' ' -f 2)" ]
160 [[ $(echo "$OLD_WATCHER" | cut -d ' ' -f 3 | cut -d '=' -f 2) -lt \
161 $(echo "$NEW_WATCHER" | cut -d ' ' -f 3 | cut -d '=' -f 2) ]]