xref: /openbmc/qemu/tests/qemu-iotests/216 (revision eabfeb0c)
1#!/usr/bin/env python3
2#
3# Copy-on-read tests using a COR filter node
4#
5# Copyright (C) 2018 Red Hat, Inc.
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program.  If not, see <http://www.gnu.org/licenses/>.
19#
20# Creator/Owner: Max Reitz <mreitz@redhat.com>
21
22import iotests
23from iotests import log, qemu_img, qemu_io_silent
24
25# Need backing file support
26iotests.script_initialize(supported_fmts=['qcow2', 'qcow', 'qed', 'vmdk'],
27                          supported_platforms=['linux'])
28
29log('')
30log('=== Copy-on-read across nodes ===')
31log('')
32
33# The old copy-on-read mechanism without a filter node cannot request
34# WRITE_UNCHANGED permissions for its child.  Therefore it just tries
35# to sneak its write by the usual permission system and holds its
36# fingers crossed.  However, that sneaking does not work so well when
37# there is a filter node in the way: That will receive the write
38# request and re-issue a new one to its child, which this time is a
39# proper write request that will make the permission system cough --
40# unless there is someone at the top (like a guest device) that has
41# requested write permissions.
42#
43# A COR filter node, however, can request the proper permissions for
44# its child and therefore is not hit by this issue.
45
46with iotests.FilePath('base.img') as base_img_path, \
47     iotests.FilePath('top.img') as top_img_path, \
48     iotests.VM() as vm:
49
50    log('--- Setting up images ---')
51    log('')
52
53    assert qemu_img('create', '-f', iotests.imgfmt, base_img_path, '64M') == 0
54    assert qemu_io_silent(base_img_path, '-c', 'write -P 1 0M 1M') == 0
55    assert qemu_img('create', '-f', iotests.imgfmt, '-b', base_img_path,
56                    '-F', iotests.imgfmt, top_img_path) == 0
57    assert qemu_io_silent(top_img_path,  '-c', 'write -P 2 1M 1M') == 0
58
59    log('Done')
60
61    log('')
62    log('--- Doing COR ---')
63    log('')
64
65    # Compare with e.g. the following:
66    #   vm.add_drive_raw('if=none,node-name=node0,copy-on-read=on,driver=raw,' \
67    #                    'file.driver=%s,file.file.filename=%s' %
68    #                       (iotests.imgfmt, top_img_path))
69    # (Remove the blockdev-add instead.)
70    # ((Not tested here because it hits an assertion in the permission
71    #   system.))
72
73    vm.launch()
74
75    log(vm.qmp('blockdev-add',
76                    node_name='node0',
77                    driver='copy-on-read',
78                    file={
79                        'driver': 'raw',
80                        'file': {
81                            'driver': 'copy-on-read',
82                            'file': {
83                                'driver': 'raw',
84                                'file': {
85                                    'driver': iotests.imgfmt,
86                                    'file': {
87                                        'driver': 'file',
88                                        'filename': top_img_path
89                                    },
90                                    'backing': {
91                                        'driver': iotests.imgfmt,
92                                        'file': {
93                                            'driver': 'file',
94                                            'filename': base_img_path
95                                        }
96                                    }
97                                }
98                            }
99                        }
100                    }))
101
102    # Trigger COR
103    log(vm.qmp('human-monitor-command',
104               command_line='qemu-io node0 "read 0 64M"'))
105
106    vm.shutdown()
107
108    log('')
109    log('--- Checking COR result ---')
110    log('')
111
112    assert qemu_io_silent(base_img_path, '-c', 'discard 0 64M') == 0
113    assert qemu_io_silent(top_img_path,  '-c', 'read -P 1 0M 1M') == 0
114    assert qemu_io_silent(top_img_path,  '-c', 'read -P 2 1M 1M') == 0
115
116    log('Done')
117