]>
Commit | Line | Data |
---|---|---|
20209d8d TL |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | |
3 | Date: Thu, 11 Apr 2024 11:29:25 +0200 | |
4 | Subject: [PATCH] qapi: blockdev-backup: add discard-source parameter | |
5 | ||
6 | Add a parameter that enables discard-after-copy. That is mostly useful | |
7 | in "push backup with fleecing" scheme, when source is snapshot-access | |
8 | format driver node, based on copy-before-write filter snapshot-access | |
9 | API: | |
10 | ||
11 | [guest] [snapshot-access] ~~ blockdev-backup ~~> [backup target] | |
12 | | | | |
13 | | root | file | |
14 | v v | |
15 | [copy-before-write] | |
16 | | | | |
17 | | file | target | |
18 | v v | |
19 | [active disk] [temp.img] | |
20 | ||
21 | In this case discard-after-copy does two things: | |
22 | ||
23 | - discard data in temp.img to save disk space | |
24 | - avoid further copy-before-write operation in discarded area | |
25 | ||
26 | Note that we have to declare WRITE permission on source in | |
27 | copy-before-write filter, for discard to work. Still we can't take it | |
28 | unconditionally, as it will break normal backup from RO source. So, we | |
29 | have to add a parameter and pass it thorough bdrv_open flags. | |
30 | ||
31 | Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> | |
32 | Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> | |
33 | Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com> | |
34 | --- | |
35 | block/backup.c | 5 +++-- | |
36 | block/block-copy.c | 9 +++++++++ | |
37 | block/copy-before-write.c | 15 +++++++++++++-- | |
38 | block/copy-before-write.h | 1 + | |
39 | block/replication.c | 4 ++-- | |
40 | blockdev.c | 2 +- | |
41 | include/block/block-common.h | 2 ++ | |
42 | include/block/block-copy.h | 1 + | |
43 | include/block/block_int-global-state.h | 2 +- | |
44 | qapi/block-core.json | 4 ++++ | |
45 | 10 files changed, 37 insertions(+), 8 deletions(-) | |
46 | ||
47 | diff --git a/block/backup.c b/block/backup.c | |
f1eed34a | 48 | index aec140e0c8..f19b751fe6 100644 |
20209d8d TL |
49 | --- a/block/backup.c |
50 | +++ b/block/backup.c | |
51 | @@ -332,7 +332,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, | |
52 | BlockDriverState *target, int64_t speed, | |
53 | MirrorSyncMode sync_mode, BdrvDirtyBitmap *sync_bitmap, | |
54 | BitmapSyncMode bitmap_mode, | |
55 | - bool compress, | |
56 | + bool compress, bool discard_source, | |
57 | const char *filter_node_name, | |
58 | BackupPerf *perf, | |
59 | BlockdevOnError on_source_error, | |
f1eed34a | 60 | @@ -433,7 +433,8 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, |
20209d8d TL |
61 | goto error; |
62 | } | |
63 | ||
64 | - cbw = bdrv_cbw_append(bs, target, filter_node_name, &bcs, errp); | |
65 | + cbw = bdrv_cbw_append(bs, target, filter_node_name, discard_source, | |
66 | + &bcs, errp); | |
67 | if (!cbw) { | |
68 | goto error; | |
69 | } | |
70 | diff --git a/block/block-copy.c b/block/block-copy.c | |
f1eed34a | 71 | index 8fca2c3698..7e3b378528 100644 |
20209d8d TL |
72 | --- a/block/block-copy.c |
73 | +++ b/block/block-copy.c | |
74 | @@ -137,6 +137,7 @@ typedef struct BlockCopyState { | |
75 | CoMutex lock; | |
76 | int64_t in_flight_bytes; | |
77 | BlockCopyMethod method; | |
78 | + bool discard_source; | |
79 | BlockReqList reqs; | |
80 | QLIST_HEAD(, BlockCopyCallState) calls; | |
81 | /* | |
f1eed34a | 82 | @@ -353,6 +354,7 @@ static int64_t block_copy_calculate_cluster_size(BlockDriverState *target, |
20209d8d TL |
83 | BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target, |
84 | BlockDriverState *copy_bitmap_bs, | |
85 | const BdrvDirtyBitmap *bitmap, | |
86 | + bool discard_source, | |
87 | Error **errp) | |
88 | { | |
89 | ERRP_GUARD(); | |
f1eed34a | 90 | @@ -418,6 +420,7 @@ BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target, |
20209d8d TL |
91 | cluster_size), |
92 | }; | |
93 | ||
94 | + s->discard_source = discard_source; | |
95 | block_copy_set_copy_opts(s, false, false); | |
96 | ||
97 | ratelimit_init(&s->rate_limit); | |
f1eed34a | 98 | @@ -589,6 +592,12 @@ static coroutine_fn int block_copy_task_entry(AioTask *task) |
20209d8d TL |
99 | co_put_to_shres(s->mem, t->req.bytes); |
100 | block_copy_task_end(t, ret); | |
101 | ||
102 | + if (s->discard_source && ret == 0) { | |
103 | + int64_t nbytes = | |
104 | + MIN(t->req.offset + t->req.bytes, s->len) - t->req.offset; | |
105 | + bdrv_co_pdiscard(s->source, t->req.offset, nbytes); | |
106 | + } | |
107 | + | |
108 | return ret; | |
109 | } | |
110 | ||
111 | diff --git a/block/copy-before-write.c b/block/copy-before-write.c | |
f1eed34a | 112 | index afa5f473d2..5506f66857 100644 |
20209d8d TL |
113 | --- a/block/copy-before-write.c |
114 | +++ b/block/copy-before-write.c | |
115 | @@ -44,6 +44,7 @@ typedef struct BDRVCopyBeforeWriteState { | |
116 | BdrvChild *target; | |
117 | OnCbwError on_cbw_error; | |
118 | uint32_t cbw_timeout_ns; | |
119 | + bool discard_source; | |
120 | ||
121 | /* | |
122 | * @lock: protects access to @access_bitmap, @done_bitmap and | |
f1eed34a FE |
123 | @@ -357,6 +358,8 @@ cbw_child_perm(BlockDriverState *bs, BdrvChild *c, BdrvChildRole role, |
124 | uint64_t perm, uint64_t shared, | |
125 | uint64_t *nperm, uint64_t *nshared) | |
20209d8d TL |
126 | { |
127 | + BDRVCopyBeforeWriteState *s = bs->opaque; | |
128 | + | |
129 | if (!(role & BDRV_CHILD_FILTERED)) { | |
130 | /* | |
131 | * Target child | |
f1eed34a | 132 | @@ -381,6 +384,10 @@ cbw_child_perm(BlockDriverState *bs, BdrvChild *c, BdrvChildRole role, |
20209d8d TL |
133 | * start |
134 | */ | |
135 | *nperm = *nperm | BLK_PERM_CONSISTENT_READ; | |
136 | + if (s->discard_source) { | |
137 | + *nperm = *nperm | BLK_PERM_WRITE; | |
138 | + } | |
139 | + | |
140 | *nshared &= ~(BLK_PERM_WRITE | BLK_PERM_RESIZE); | |
141 | } | |
142 | } | |
f1eed34a | 143 | @@ -472,7 +479,9 @@ static int cbw_open(BlockDriverState *bs, QDict *options, int flags, |
20209d8d TL |
144 | ((BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK) & |
145 | bs->file->bs->supported_zero_flags); | |
146 | ||
147 | - s->bcs = block_copy_state_new(bs->file, s->target, bs, bitmap, errp); | |
148 | + s->discard_source = flags & BDRV_O_CBW_DISCARD_SOURCE; | |
149 | + s->bcs = block_copy_state_new(bs->file, s->target, bs, bitmap, | |
150 | + flags & BDRV_O_CBW_DISCARD_SOURCE, errp); | |
151 | if (!s->bcs) { | |
152 | error_prepend(errp, "Cannot create block-copy-state: "); | |
153 | ret = -EINVAL; | |
f1eed34a | 154 | @@ -546,12 +555,14 @@ static BlockDriver bdrv_cbw_filter = { |
20209d8d TL |
155 | BlockDriverState *bdrv_cbw_append(BlockDriverState *source, |
156 | BlockDriverState *target, | |
157 | const char *filter_node_name, | |
158 | + bool discard_source, | |
159 | BlockCopyState **bcs, | |
160 | Error **errp) | |
161 | { | |
162 | BDRVCopyBeforeWriteState *state; | |
163 | BlockDriverState *top; | |
164 | QDict *opts; | |
165 | + int flags = BDRV_O_RDWR | (discard_source ? BDRV_O_CBW_DISCARD_SOURCE : 0); | |
166 | ||
167 | assert(source->total_sectors == target->total_sectors); | |
168 | GLOBAL_STATE_CODE(); | |
f1eed34a | 169 | @@ -564,7 +575,7 @@ BlockDriverState *bdrv_cbw_append(BlockDriverState *source, |
20209d8d TL |
170 | qdict_put_str(opts, "file", bdrv_get_node_name(source)); |
171 | qdict_put_str(opts, "target", bdrv_get_node_name(target)); | |
172 | ||
173 | - top = bdrv_insert_node(source, opts, BDRV_O_RDWR, errp); | |
174 | + top = bdrv_insert_node(source, opts, flags, errp); | |
175 | if (!top) { | |
176 | return NULL; | |
177 | } | |
178 | diff --git a/block/copy-before-write.h b/block/copy-before-write.h | |
179 | index 6e72bb25e9..01af0cd3c4 100644 | |
180 | --- a/block/copy-before-write.h | |
181 | +++ b/block/copy-before-write.h | |
182 | @@ -39,6 +39,7 @@ | |
183 | BlockDriverState *bdrv_cbw_append(BlockDriverState *source, | |
184 | BlockDriverState *target, | |
185 | const char *filter_node_name, | |
186 | + bool discard_source, | |
187 | BlockCopyState **bcs, | |
188 | Error **errp); | |
189 | void bdrv_cbw_drop(BlockDriverState *bs); | |
190 | diff --git a/block/replication.c b/block/replication.c | |
f1eed34a | 191 | index 5ded5f1ca9..bd75a6aee3 100644 |
20209d8d TL |
192 | --- a/block/replication.c |
193 | +++ b/block/replication.c | |
f1eed34a | 194 | @@ -604,8 +604,8 @@ static void replication_start(ReplicationState *rs, ReplicationMode mode, |
20209d8d TL |
195 | |
196 | s->backup_job = backup_job_create( | |
197 | NULL, s->secondary_disk->bs, s->hidden_disk->bs, | |
198 | - 0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, NULL, | |
199 | - &perf, | |
200 | + 0, MIRROR_SYNC_MODE_NONE, NULL, 0, false, false, | |
201 | + NULL, &perf, | |
202 | BLOCKDEV_ON_ERROR_REPORT, | |
203 | BLOCKDEV_ON_ERROR_REPORT, JOB_INTERNAL, | |
204 | backup_job_completed, bs, NULL, &local_err); | |
205 | diff --git a/blockdev.c b/blockdev.c | |
f1eed34a | 206 | index 3049811be8..e167ad1e54 100644 |
20209d8d TL |
207 | --- a/blockdev.c |
208 | +++ b/blockdev.c | |
f1eed34a | 209 | @@ -2854,7 +2854,7 @@ static BlockJob *do_backup_common(BackupCommon *backup, |
20209d8d TL |
210 | |
211 | job = backup_job_create(backup->job_id, bs, target_bs, backup->speed, | |
212 | backup->sync, bmap, backup->bitmap_mode, | |
213 | - backup->compress, | |
214 | + backup->compress, backup->discard_source, | |
215 | backup->filter_node_name, | |
216 | &perf, | |
217 | backup->on_source_error, | |
218 | diff --git a/include/block/block-common.h b/include/block/block-common.h | |
f1eed34a | 219 | index d7599564db..7f56364e73 100644 |
20209d8d TL |
220 | --- a/include/block/block-common.h |
221 | +++ b/include/block/block-common.h | |
f1eed34a | 222 | @@ -246,6 +246,8 @@ typedef enum { |
20209d8d TL |
223 | read-write fails */ |
224 | #define BDRV_O_IO_URING 0x40000 /* use io_uring instead of the thread pool */ | |
225 | ||
226 | +#define BDRV_O_CBW_DISCARD_SOURCE 0x80000 /* for copy-before-write filter */ | |
227 | + | |
228 | #define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_NO_FLUSH) | |
229 | ||
230 | ||
231 | diff --git a/include/block/block-copy.h b/include/block/block-copy.h | |
232 | index 8b41643bfa..bdc703bacd 100644 | |
233 | --- a/include/block/block-copy.h | |
234 | +++ b/include/block/block-copy.h | |
235 | @@ -27,6 +27,7 @@ typedef struct BlockCopyCallState BlockCopyCallState; | |
236 | BlockCopyState *block_copy_state_new(BdrvChild *source, BdrvChild *target, | |
237 | BlockDriverState *copy_bitmap_bs, | |
238 | const BdrvDirtyBitmap *bitmap, | |
239 | + bool discard_source, | |
240 | Error **errp); | |
241 | ||
242 | /* Function should be called prior any actual copy request */ | |
243 | diff --git a/include/block/block_int-global-state.h b/include/block/block_int-global-state.h | |
f1eed34a | 244 | index 57265a617a..df731688b4 100644 |
20209d8d TL |
245 | --- a/include/block/block_int-global-state.h |
246 | +++ b/include/block/block_int-global-state.h | |
247 | @@ -189,7 +189,7 @@ BlockJob *backup_job_create(const char *job_id, BlockDriverState *bs, | |
248 | MirrorSyncMode sync_mode, | |
249 | BdrvDirtyBitmap *sync_bitmap, | |
250 | BitmapSyncMode bitmap_mode, | |
251 | - bool compress, | |
252 | + bool compress, bool discard_source, | |
253 | const char *filter_node_name, | |
254 | BackupPerf *perf, | |
255 | BlockdevOnError on_source_error, | |
256 | diff --git a/qapi/block-core.json b/qapi/block-core.json | |
f1eed34a | 257 | index 7b977459fa..82960797dc 100644 |
20209d8d TL |
258 | --- a/qapi/block-core.json |
259 | +++ b/qapi/block-core.json | |
f1eed34a | 260 | @@ -1834,6 +1834,9 @@ |
20209d8d TL |
261 | # node specified by @drive. If this option is not given, a node |
262 | # name is autogenerated. (Since: 4.2) | |
263 | # | |
264 | +# @discard-source: Discard blocks on source which are already copied | |
265 | +# to the target. (Since 9.0) | |
266 | +# | |
267 | # @x-perf: Performance options. (Since 6.0) | |
268 | # | |
269 | # Features: | |
f1eed34a | 270 | @@ -1855,6 +1858,7 @@ |
20209d8d TL |
271 | '*on-target-error': 'BlockdevOnError', |
272 | '*auto-finalize': 'bool', '*auto-dismiss': 'bool', | |
273 | '*filter-node-name': 'str', | |
274 | + '*discard-source': 'bool', | |
275 | '*x-perf': { 'type': 'BackupPerf', | |
276 | 'features': [ 'unstable' ] } } } | |
277 |