2 * backup-top filter driver
4 * The driver performs Copy-Before-Write (CBW) operation: it is injected above
5 * some node, and before each write it copies _old_ data to the target node.
7 * Copyright (c) 2018-2019 Virtuozzo International GmbH.
10 * Sementsov-Ogievskiy Vladimir <vsementsov@virtuozzo.com>
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "qemu/osdep.h"
28 #include "sysemu/block-backend.h"
29 #include "qemu/cutils.h"
30 #include "qapi/error.h"
31 #include "block/block_int.h"
32 #include "block/qdict.h"
33 #include "block/block-copy.h"
35 #include "block/backup-top.h"
37 typedef struct BDRVBackupTopState
{
44 static coroutine_fn
int backup_top_co_preadv(
45 BlockDriverState
*bs
, uint64_t offset
, uint64_t bytes
,
46 QEMUIOVector
*qiov
, int flags
)
48 return bdrv_co_preadv(bs
->backing
, offset
, bytes
, qiov
, flags
);
51 static coroutine_fn
int backup_top_cbw(BlockDriverState
*bs
, uint64_t offset
,
52 uint64_t bytes
, BdrvRequestFlags flags
)
54 BDRVBackupTopState
*s
= bs
->opaque
;
57 if (flags
& BDRV_REQ_WRITE_UNCHANGED
) {
61 off
= QEMU_ALIGN_DOWN(offset
, s
->cluster_size
);
62 end
= QEMU_ALIGN_UP(offset
+ bytes
, s
->cluster_size
);
64 return block_copy(s
->bcs
, off
, end
- off
, NULL
);
67 static int coroutine_fn
backup_top_co_pdiscard(BlockDriverState
*bs
,
68 int64_t offset
, int bytes
)
70 int ret
= backup_top_cbw(bs
, offset
, bytes
, 0);
75 return bdrv_co_pdiscard(bs
->backing
, offset
, bytes
);
78 static int coroutine_fn
backup_top_co_pwrite_zeroes(BlockDriverState
*bs
,
79 int64_t offset
, int bytes
, BdrvRequestFlags flags
)
81 int ret
= backup_top_cbw(bs
, offset
, bytes
, flags
);
86 return bdrv_co_pwrite_zeroes(bs
->backing
, offset
, bytes
, flags
);
89 static coroutine_fn
int backup_top_co_pwritev(BlockDriverState
*bs
,
92 QEMUIOVector
*qiov
, int flags
)
94 int ret
= backup_top_cbw(bs
, offset
, bytes
, flags
);
99 return bdrv_co_pwritev(bs
->backing
, offset
, bytes
, qiov
, flags
);
102 static int coroutine_fn
backup_top_co_flush(BlockDriverState
*bs
)
108 return bdrv_co_flush(bs
->backing
->bs
);
111 static void backup_top_refresh_filename(BlockDriverState
*bs
)
113 if (bs
->backing
== NULL
) {
115 * we can be here after failed bdrv_attach_child in
116 * bdrv_set_backing_hd
120 pstrcpy(bs
->exact_filename
, sizeof(bs
->exact_filename
),
121 bs
->backing
->bs
->filename
);
124 static void backup_top_child_perm(BlockDriverState
*bs
, BdrvChild
*c
,
125 const BdrvChildRole
*role
,
126 BlockReopenQueue
*reopen_queue
,
127 uint64_t perm
, uint64_t shared
,
128 uint64_t *nperm
, uint64_t *nshared
)
130 BDRVBackupTopState
*s
= bs
->opaque
;
134 * The filter node may be in process of bdrv_append(), which firstly do
135 * bdrv_set_backing_hd() and then bdrv_replace_node(). This means that
136 * we can't unshare BLK_PERM_WRITE during bdrv_append() operation. So,
137 * let's require nothing during bdrv_append() and refresh permissions
138 * after it (see bdrv_backup_top_append()).
141 *nshared
= BLK_PERM_ALL
;
145 if (role
== &child_file
) {
149 * Share write to target (child_file), to not interfere
150 * with guest writes to its disk which may be in target backing chain.
152 *nshared
= BLK_PERM_ALL
;
153 *nperm
= BLK_PERM_WRITE
;
156 bdrv_filter_default_perms(bs
, c
, role
, reopen_queue
, perm
, shared
,
159 if (perm
& BLK_PERM_WRITE
) {
160 *nperm
= *nperm
| BLK_PERM_CONSISTENT_READ
;
162 *nshared
&= ~BLK_PERM_WRITE
;
166 BlockDriver bdrv_backup_top_filter
= {
167 .format_name
= "backup-top",
168 .instance_size
= sizeof(BDRVBackupTopState
),
170 .bdrv_co_preadv
= backup_top_co_preadv
,
171 .bdrv_co_pwritev
= backup_top_co_pwritev
,
172 .bdrv_co_pwrite_zeroes
= backup_top_co_pwrite_zeroes
,
173 .bdrv_co_pdiscard
= backup_top_co_pdiscard
,
174 .bdrv_co_flush
= backup_top_co_flush
,
176 .bdrv_co_block_status
= bdrv_co_block_status_from_backing
,
178 .bdrv_refresh_filename
= backup_top_refresh_filename
,
180 .bdrv_child_perm
= backup_top_child_perm
,
185 BlockDriverState
*bdrv_backup_top_append(BlockDriverState
*source
,
186 BlockDriverState
*target
,
187 const char *filter_node_name
,
188 uint64_t cluster_size
,
189 BdrvRequestFlags write_flags
,
190 BlockCopyState
**bcs
,
193 Error
*local_err
= NULL
;
194 BDRVBackupTopState
*state
;
195 BlockDriverState
*top
= bdrv_new_open_driver(&bdrv_backup_top_filter
,
198 bool appended
= false;
205 top
->total_sectors
= source
->total_sectors
;
206 top
->supported_write_flags
= BDRV_REQ_WRITE_UNCHANGED
|
207 (BDRV_REQ_FUA
& source
->supported_write_flags
);
208 top
->supported_zero_flags
= BDRV_REQ_WRITE_UNCHANGED
|
209 ((BDRV_REQ_FUA
| BDRV_REQ_MAY_UNMAP
| BDRV_REQ_NO_FALLBACK
) &
210 source
->supported_zero_flags
);
213 state
->target
= bdrv_attach_child(top
, target
, "target", &child_file
, errp
);
214 if (!state
->target
) {
220 bdrv_drained_begin(source
);
223 bdrv_append(top
, source
, &local_err
);
225 error_prepend(&local_err
, "Cannot append backup-top filter: ");
231 * bdrv_append() finished successfully, now we can require permissions
234 state
->active
= true;
235 bdrv_child_refresh_perms(top
, top
->backing
, &local_err
);
237 error_prepend(&local_err
,
238 "Cannot set permissions for backup-top filter: ");
242 state
->cluster_size
= cluster_size
;
243 state
->bcs
= block_copy_state_new(top
->backing
, state
->target
,
244 cluster_size
, write_flags
, &local_err
);
246 error_prepend(&local_err
, "Cannot create block-copy-state: ");
251 bdrv_drained_end(source
);
257 state
->active
= false;
258 bdrv_backup_top_drop(top
);
263 bdrv_drained_end(source
);
264 error_propagate(errp
, local_err
);
269 void bdrv_backup_top_drop(BlockDriverState
*bs
)
271 BDRVBackupTopState
*s
= bs
->opaque
;
273 bdrv_drained_begin(bs
);
275 block_copy_state_free(s
->bcs
);
278 bdrv_child_refresh_perms(bs
, bs
->backing
, &error_abort
);
279 bdrv_replace_node(bs
, backing_bs(bs
), &error_abort
);
280 bdrv_set_backing_hd(bs
, NULL
, &error_abort
);
282 bdrv_drained_end(bs
);