283 (a557b00469bca61a058fc1db4855503cac1c3219) 283 (d003e0aeced533074341c88fe6b58f97f8136397)
1#!/usr/bin/env python3
2# group: auto quick
3#
1#!/usr/bin/env python3
2# group: auto quick
3#
4# Test for backup-top filter permission activation failure
4# Test for copy-before-write filter permission conflict
5#
6# Copyright (c) 2019 Virtuozzo International GmbH.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#

--- 13 unchanged lines hidden (view full) ---

26 supported_fmts=['qcow2'],
27)
28
29size = 1024 * 1024
30
31""" Test description
32
33When performing a backup, all writes on the source subtree must go through the
5#
6# Copyright (c) 2019 Virtuozzo International GmbH.
7#
8# This program is free software; you can redistribute it and/or modify
9# it under the terms of the GNU General Public License as published by
10# the Free Software Foundation; either version 2 of the License, or
11# (at your option) any later version.
12#

--- 13 unchanged lines hidden (view full) ---

26 supported_fmts=['qcow2'],
27)
28
29size = 1024 * 1024
30
31""" Test description
32
33When performing a backup, all writes on the source subtree must go through the
34backup-top filter so it can copy all data to the target before it is changed.
35backup-top filter is appended above source node, to achieve this thing, so all
36parents of source node are handled. A configuration with side parents of source
37sub-tree with write permission is unsupported (we'd have append several
38backup-top filter like nodes to handle such parents). The test create an
39example of such configuration and checks that a backup is then not allowed
40(blockdev-backup command should fail).
34copy-before-write filter so it can copy all data to the target before it is
35changed. copy-before-write filter is appended above source node, to achieve
36this thing, so all parents of source node are handled. A configuration with
37side parents of source sub-tree with write permission is unsupported (we'd have
38append several copy-before-write filter like nodes to handle such parents). The
39test create an example of such configuration and checks that a backup is then
40not allowed (blockdev-backup command should fail).
41
42The configuration:
43
44 ┌────────┐ target ┌─────────────┐
45 │ target │ ◀─────── │ backup_top │
46 └────────┘ └─────────────┘
47
48 │ backing
49
50 ┌─────────────┐
51 │ source │
52 └─────────────┘
53
54 │ file
55
56 ┌─────────────┐ write perm ┌───────┐
57 │ base │ ◀──────────── │ other │
58 └─────────────┘ └───────┘
59
41
42The configuration:
43
44 ┌────────┐ target ┌─────────────┐
45 │ target │ ◀─────── │ backup_top │
46 └────────┘ └─────────────┘
47
48 │ backing
49
50 ┌─────────────┐
51 │ source │
52 └─────────────┘
53
54 │ file
55
56 ┌─────────────┐ write perm ┌───────┐
57 │ base │ ◀──────────── │ other │
58 └─────────────┘ └───────┘
59
60On activation (see .active field of backup-top state in block/backup-top.c),
61backup-top is going to unshare write permission on its source child. Write
62unsharing will be propagated to the "source->base" link and will conflict with
63other node write permission. So permission update will fail and backup job will
64not be started.
60copy-before-write filter wants to unshare write permission on its source child.
61Write unsharing will be propagated to the "source->base" link and will conflict
62with other node write permission. So permission update will fail and backup job
63will not be started.
65
66Note, that the only thing which prevents backup of running on such
67configuration is default permission propagation scheme. It may be altered by
68different block drivers, so backup will run in invalid configuration. But
69something is better than nothing. Also, before the previous commit (commit
70preceding this test creation), starting backup on such configuration led to
71crash, so current "something" is a lot better, and this test actual goal is
72to check that crash is fixed :)

--- 21 unchanged lines hidden (view full) ---

94 'take-child-perms': ['write']
95})
96
97vm.qmp_log('blockdev-backup', sync='full', device='source', target='target')
98
99vm.shutdown()
100
101
64
65Note, that the only thing which prevents backup of running on such
66configuration is default permission propagation scheme. It may be altered by
67different block drivers, so backup will run in invalid configuration. But
68something is better than nothing. Also, before the previous commit (commit
69preceding this test creation), starting backup on such configuration led to
70crash, so current "something" is a lot better, and this test actual goal is
71to check that crash is fixed :)

--- 21 unchanged lines hidden (view full) ---

93 'take-child-perms': ['write']
94})
95
96vm.qmp_log('blockdev-backup', sync='full', device='source', target='target')
97
98vm.shutdown()
99
100
102print('\n=== backup-top should be gone after job-finalize ===\n')
101print('\n=== copy-before-write filter should be gone after job-finalize ===\n')
103
102
104# Check that the backup-top node is gone after job-finalize.
105#
106# During finalization, the node becomes inactive and can no longer
107# function. If it is still present, new parents might be attached, and
108# there would be no meaningful way to handle their I/O requests.
103# Check that the copy-before-write node is gone after job-finalize.
109
110vm = iotests.VM()
111vm.launch()
112
113vm.qmp_log('blockdev-add', **{
114 'node-name': 'source',
115 'driver': 'null-co',
116})

--- 9 unchanged lines hidden (view full) ---

126 target='target',
127 sync='full',
128 filter_node_name='backup-filter',
129 auto_finalize=False,
130 auto_dismiss=False)
131
132vm.event_wait('BLOCK_JOB_PENDING', 5.0)
133
104
105vm = iotests.VM()
106vm.launch()
107
108vm.qmp_log('blockdev-add', **{
109 'node-name': 'source',
110 'driver': 'null-co',
111})

--- 9 unchanged lines hidden (view full) ---

121 target='target',
122 sync='full',
123 filter_node_name='backup-filter',
124 auto_finalize=False,
125 auto_dismiss=False)
126
127vm.event_wait('BLOCK_JOB_PENDING', 5.0)
128
134# The backup-top filter should still be present prior to finalization
129# The copy-before-write filter should still be present prior to finalization
135assert vm.node_info('backup-filter') is not None
136
137vm.qmp_log('job-finalize', id='backup')
138vm.event_wait('BLOCK_JOB_COMPLETED', 5.0)
139
140# The filter should be gone now. Check that by trying to access it
141# with qemu-io (which will most likely crash qemu if it is still
142# there.).
143vm.qmp_log('human-monitor-command',
144 command_line='qemu-io backup-filter "write 0 1M"')
145
146# (Also, do an explicit check.)
147assert vm.node_info('backup-filter') is None
148
149vm.qmp_log('job-dismiss', id='backup')
150vm.event_wait('JOB_STATUS_CHANGE', 5.0, {'data': {'status': 'null'}})
151
152vm.shutdown()
130assert vm.node_info('backup-filter') is not None
131
132vm.qmp_log('job-finalize', id='backup')
133vm.event_wait('BLOCK_JOB_COMPLETED', 5.0)
134
135# The filter should be gone now. Check that by trying to access it
136# with qemu-io (which will most likely crash qemu if it is still
137# there.).
138vm.qmp_log('human-monitor-command',
139 command_line='qemu-io backup-filter "write 0 1M"')
140
141# (Also, do an explicit check.)
142assert vm.node_info('backup-filter') is None
143
144vm.qmp_log('job-dismiss', id='backup')
145vm.event_wait('JOB_STATUS_CHANGE', 5.0, {'data': {'status': 'null'}})
146
147vm.shutdown()