]> git.proxmox.com Git - qemu.git/blob - block/mirror.c
mirror: introduce mirror job
[qemu.git] / block / mirror.c
1 /*
2 * Image mirroring
3 *
4 * Copyright Red Hat, Inc. 2012
5 *
6 * Authors:
7 * Paolo Bonzini <pbonzini@redhat.com>
8 *
9 * This work is licensed under the terms of the GNU LGPL, version 2 or later.
10 * See the COPYING.LIB file in the top-level directory.
11 *
12 */
13
14 #include "trace.h"
15 #include "blockjob.h"
16 #include "block_int.h"
17 #include "qemu/ratelimit.h"
18
19 enum {
20 /*
21 * Size of data buffer for populating the image file. This should be large
22 * enough to process multiple clusters in a single call, so that populating
23 * contiguous regions of the image is efficient.
24 */
25 BLOCK_SIZE = 512 * BDRV_SECTORS_PER_DIRTY_CHUNK, /* in bytes */
26 };
27
28 #define SLICE_TIME 100000000ULL /* ns */
29
30 typedef struct MirrorBlockJob {
31 BlockJob common;
32 RateLimit limit;
33 BlockDriverState *target;
34 MirrorSyncMode mode;
35 int64_t sector_num;
36 uint8_t *buf;
37 } MirrorBlockJob;
38
39 static int coroutine_fn mirror_iteration(MirrorBlockJob *s)
40 {
41 BlockDriverState *source = s->common.bs;
42 BlockDriverState *target = s->target;
43 QEMUIOVector qiov;
44 int ret, nb_sectors;
45 int64_t end;
46 struct iovec iov;
47
48 end = s->common.len >> BDRV_SECTOR_BITS;
49 s->sector_num = bdrv_get_next_dirty(source, s->sector_num);
50 nb_sectors = MIN(BDRV_SECTORS_PER_DIRTY_CHUNK, end - s->sector_num);
51 bdrv_reset_dirty(source, s->sector_num, nb_sectors);
52
53 /* Copy the dirty cluster. */
54 iov.iov_base = s->buf;
55 iov.iov_len = nb_sectors * 512;
56 qemu_iovec_init_external(&qiov, &iov, 1);
57
58 trace_mirror_one_iteration(s, s->sector_num, nb_sectors);
59 ret = bdrv_co_readv(source, s->sector_num, nb_sectors, &qiov);
60 if (ret < 0) {
61 return ret;
62 }
63 return bdrv_co_writev(target, s->sector_num, nb_sectors, &qiov);
64 }
65
66 static void coroutine_fn mirror_run(void *opaque)
67 {
68 MirrorBlockJob *s = opaque;
69 BlockDriverState *bs = s->common.bs;
70 int64_t sector_num, end;
71 int ret = 0;
72 int n;
73 bool synced = false;
74
75 if (block_job_is_cancelled(&s->common)) {
76 goto immediate_exit;
77 }
78
79 s->common.len = bdrv_getlength(bs);
80 if (s->common.len < 0) {
81 block_job_completed(&s->common, s->common.len);
82 return;
83 }
84
85 end = s->common.len >> BDRV_SECTOR_BITS;
86 s->buf = qemu_blockalign(bs, BLOCK_SIZE);
87
88 if (s->mode != MIRROR_SYNC_MODE_NONE) {
89 /* First part, loop on the sectors and initialize the dirty bitmap. */
90 BlockDriverState *base;
91 base = s->mode == MIRROR_SYNC_MODE_FULL ? NULL : bs->backing_hd;
92 for (sector_num = 0; sector_num < end; ) {
93 int64_t next = (sector_num | (BDRV_SECTORS_PER_DIRTY_CHUNK - 1)) + 1;
94 ret = bdrv_co_is_allocated_above(bs, base,
95 sector_num, next - sector_num, &n);
96
97 if (ret < 0) {
98 goto immediate_exit;
99 }
100
101 assert(n > 0);
102 if (ret == 1) {
103 bdrv_set_dirty(bs, sector_num, n);
104 sector_num = next;
105 } else {
106 sector_num += n;
107 }
108 }
109 }
110
111 s->sector_num = -1;
112 for (;;) {
113 uint64_t delay_ns;
114 int64_t cnt;
115 bool should_complete;
116
117 cnt = bdrv_get_dirty_count(bs);
118 if (cnt != 0) {
119 ret = mirror_iteration(s);
120 if (ret < 0) {
121 goto immediate_exit;
122 }
123 cnt = bdrv_get_dirty_count(bs);
124 }
125
126 should_complete = false;
127 if (cnt == 0) {
128 trace_mirror_before_flush(s);
129 ret = bdrv_flush(s->target);
130 if (ret < 0) {
131 goto immediate_exit;
132 }
133
134 /* We're out of the streaming phase. From now on, if the job
135 * is cancelled we will actually complete all pending I/O and
136 * report completion. This way, block-job-cancel will leave
137 * the target in a consistent state.
138 */
139 synced = true;
140 s->common.offset = end * BDRV_SECTOR_SIZE;
141 should_complete = block_job_is_cancelled(&s->common);
142 cnt = bdrv_get_dirty_count(bs);
143 }
144
145 if (cnt == 0 && should_complete) {
146 /* The dirty bitmap is not updated while operations are pending.
147 * If we're about to exit, wait for pending operations before
148 * calling bdrv_get_dirty_count(bs), or we may exit while the
149 * source has dirty data to copy!
150 *
151 * Note that I/O can be submitted by the guest while
152 * mirror_populate runs.
153 */
154 trace_mirror_before_drain(s, cnt);
155 bdrv_drain_all();
156 cnt = bdrv_get_dirty_count(bs);
157 }
158
159 ret = 0;
160 trace_mirror_before_sleep(s, cnt, synced);
161 if (!synced) {
162 /* Publish progress */
163 s->common.offset = end * BDRV_SECTOR_SIZE - cnt * BLOCK_SIZE;
164
165 if (s->common.speed) {
166 delay_ns = ratelimit_calculate_delay(&s->limit, BDRV_SECTORS_PER_DIRTY_CHUNK);
167 } else {
168 delay_ns = 0;
169 }
170
171 /* Note that even when no rate limit is applied we need to yield
172 * with no pending I/O here so that qemu_aio_flush() returns.
173 */
174 block_job_sleep_ns(&s->common, rt_clock, delay_ns);
175 if (block_job_is_cancelled(&s->common)) {
176 break;
177 }
178 } else if (!should_complete) {
179 delay_ns = (cnt == 0 ? SLICE_TIME : 0);
180 block_job_sleep_ns(&s->common, rt_clock, delay_ns);
181 } else if (cnt == 0) {
182 /* The two disks are in sync. Exit and report successful
183 * completion.
184 */
185 assert(QLIST_EMPTY(&bs->tracked_requests));
186 s->common.cancelled = false;
187 break;
188 }
189 }
190
191 immediate_exit:
192 g_free(s->buf);
193 bdrv_set_dirty_tracking(bs, false);
194 bdrv_close(s->target);
195 bdrv_delete(s->target);
196 block_job_completed(&s->common, ret);
197 }
198
199 static void mirror_set_speed(BlockJob *job, int64_t speed, Error **errp)
200 {
201 MirrorBlockJob *s = container_of(job, MirrorBlockJob, common);
202
203 if (speed < 0) {
204 error_set(errp, QERR_INVALID_PARAMETER, "speed");
205 return;
206 }
207 ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME);
208 }
209
210 static BlockJobType mirror_job_type = {
211 .instance_size = sizeof(MirrorBlockJob),
212 .job_type = "mirror",
213 .set_speed = mirror_set_speed,
214 };
215
216 void mirror_start(BlockDriverState *bs, BlockDriverState *target,
217 int64_t speed, MirrorSyncMode mode,
218 BlockDriverCompletionFunc *cb,
219 void *opaque, Error **errp)
220 {
221 MirrorBlockJob *s;
222
223 s = block_job_create(&mirror_job_type, bs, speed, cb, opaque, errp);
224 if (!s) {
225 return;
226 }
227
228 s->target = target;
229 s->mode = mode;
230 bdrv_set_dirty_tracking(bs, true);
231 bdrv_set_enable_write_cache(s->target, true);
232 s->common.co = qemu_coroutine_create(mirror_run);
233 trace_mirror_start(bs, s, s->common.co, opaque);
234 qemu_coroutine_enter(s->common.co, s);
235 }