|  | #!/usr/bin/env bash | 
|  | # group: rw quick | 
|  | # | 
|  | # Test image locking for POSIX locks | 
|  | # | 
|  | # Copyright 2017 Red Hat, Inc. | 
|  | # | 
|  | # This program 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; either version 2 of the License, or | 
|  | # (at your option) any later version. | 
|  | # | 
|  | # This program is distributed in the hope that it will be useful, | 
|  | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | # GNU General Public License for more details. | 
|  | # | 
|  | # You should have received a copy of the GNU General Public License | 
|  | # along with this program.  If not, see <http://www.gnu.org/licenses/>. | 
|  | # | 
|  |  | 
|  | # creator | 
|  | owner=fam@euphon.net | 
|  |  | 
|  | seq="$(basename $0)" | 
|  | echo "QA output created by $seq" | 
|  |  | 
|  | tmp=/tmp/$$ | 
|  | status=1	# failure is the default! | 
|  |  | 
|  | _cleanup() | 
|  | { | 
|  | _cleanup_test_img | 
|  | _rm_test_img "$TEST_IMG.overlay" | 
|  | rm -f "$SOCK_DIR/nbd.socket" | 
|  | } | 
|  | trap "_cleanup; exit \$status" 0 1 2 3 15 | 
|  |  | 
|  | # get standard environment, filters and checks | 
|  | . ./common.rc | 
|  | . ./common.filter | 
|  | . ./common.qemu | 
|  |  | 
|  | _supported_fmt qcow2 | 
|  | _supported_proto file | 
|  |  | 
|  | size=32M | 
|  |  | 
|  | _make_test_img $size | 
|  |  | 
|  | echo "Starting QEMU" | 
|  | _launch_qemu -drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \ | 
|  | -device virtio-blk,drive=drive0 | 
|  |  | 
|  | echo | 
|  | echo "Starting a second QEMU using the same image should fail" | 
|  | echo 'quit' | $QEMU -nographic -monitor stdio \ | 
|  | -drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \ | 
|  | -device virtio-blk,drive=drive0 2>&1 | _filter_testdir 2>&1 | | 
|  | _filter_qemu | | 
|  | sed -e '/falling back to POSIX file/d' \ | 
|  | -e '/locks can be lost unexpectedly/d' | 
|  |  | 
|  | _cleanup_qemu | 
|  |  | 
|  | echo | 
|  | echo '=== Testing reopen ===' | 
|  | echo | 
|  |  | 
|  | # This tests that reopening does not unshare any permissions it should | 
|  | # not unshare | 
|  | # (There was a bug where reopening shared exactly the opposite of the | 
|  | # permissions it was supposed to share) | 
|  |  | 
|  | _launch_qemu | 
|  |  | 
|  | _send_qemu_cmd $QEMU_HANDLE \ | 
|  | "{'execute': 'qmp_capabilities'}" \ | 
|  | 'return' | 
|  |  | 
|  | # Open the image without any format layer (we are not going to access | 
|  | # it, so that is fine) | 
|  | # This should keep all permissions shared. | 
|  | success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ | 
|  | "{'execute': 'blockdev-add', | 
|  | 'arguments': { | 
|  | 'node-name': 'node0', | 
|  | 'driver': 'file', | 
|  | 'filename': '$TEST_IMG', | 
|  | 'locking': 'on' | 
|  | } }" \ | 
|  | 'return' \ | 
|  | 'error' | 
|  |  | 
|  | # This snapshot will perform a reopen to drop R/W to RO. | 
|  | # It should still keep all permissions shared. | 
|  | success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ | 
|  | "{'execute': 'blockdev-snapshot-sync', | 
|  | 'arguments': { | 
|  | 'node-name': 'node0', | 
|  | 'snapshot-file': '$TEST_IMG.overlay', | 
|  | 'snapshot-node-name': 'node1' | 
|  | } }" \ | 
|  | 'return' \ | 
|  | 'error' | 
|  |  | 
|  | # Now open the same file again | 
|  | # This does not require any permissions (and does not unshare any), so | 
|  | # this will not conflict with node0. | 
|  | success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ | 
|  | "{'execute': 'blockdev-add', | 
|  | 'arguments': { | 
|  | 'node-name': 'node1', | 
|  | 'driver': 'file', | 
|  | 'filename': '$TEST_IMG', | 
|  | 'locking': 'on' | 
|  | } }" \ | 
|  | 'return' \ | 
|  | 'error' | 
|  |  | 
|  | # Start an NBD server to which we can attach node1 | 
|  | success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ | 
|  | "{'execute': 'nbd-server-start', | 
|  | 'arguments': { | 
|  | 'addr': { | 
|  | 'type': 'unix', | 
|  | 'data': { | 
|  | 'path': '$SOCK_DIR/nbd.socket' | 
|  | } } } }" \ | 
|  | 'return' \ | 
|  | 'error' | 
|  |  | 
|  | # Now we attach the image to the NBD server.  This server does require | 
|  | # some permissions (at least WRITE and READ_CONSISTENT), so if | 
|  | # reopening node0 unshared any (which it should not have), this will | 
|  | # fail (but it should not). | 
|  | success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ | 
|  | "{'execute': 'nbd-server-add', | 
|  | 'arguments': { | 
|  | 'device': 'node1' | 
|  | } }" \ | 
|  | 'return' \ | 
|  | 'error' | 
|  |  | 
|  | _cleanup_qemu | 
|  |  | 
|  | echo | 
|  | echo '=== Testing failure to loosen restrictions ===' | 
|  | echo | 
|  |  | 
|  | _launch_qemu -drive file=$TEST_IMG,if=none,file.locking=on | 
|  |  | 
|  | _send_qemu_cmd $QEMU_HANDLE \ | 
|  | "{'execute': 'qmp_capabilities'}" \ | 
|  | 'return' | 
|  |  | 
|  | _cleanup_test_img | 
|  |  | 
|  | # When quitting qemu, it will try to drop its locks on the test image. | 
|  | # Because that file no longer exists, it will be unable to do so. | 
|  | # However, that is not fatal, so it should just move on. | 
|  | _send_qemu_cmd $QEMU_HANDLE \ | 
|  | "{'execute': 'quit'}" \ | 
|  | 'return' | 
|  |  | 
|  | wait=1 _cleanup_qemu | 
|  |  | 
|  | # success, all done | 
|  | echo "*** done" | 
|  | rm -f $seq.full | 
|  | status=0 |