1 /* 2 * Live block commit 3 * 4 * Copyright Red Hat, Inc. 2012 5 * 6 * Authors: 7 * Jeff Cody <jcody@redhat.com> 8 * Based on stream.c by Stefan Hajnoczi 9 * 10 * This work is licensed under the terms of the GNU LGPL, version 2 or later. 11 * See the COPYING.LIB file in the top-level directory. 12 * 13 */ 14 15 #include "qemu/osdep.h" 16 #include "trace.h" 17 #include "block/block_int.h" 18 #include "block/blockjob.h" 19 #include "qapi/qmp/qerror.h" 20 #include "qemu/ratelimit.h" 21 #include "sysemu/block-backend.h" 22 23 enum { 24 /* 25 * Size of data buffer for populating the image file. This should be large 26 * enough to process multiple clusters in a single call, so that populating 27 * contiguous regions of the image is efficient. 28 */ 29 COMMIT_BUFFER_SIZE = 512 * 1024, /* in bytes */ 30 }; 31 32 #define SLICE_TIME 100000000ULL /* ns */ 33 34 typedef struct CommitBlockJob { 35 BlockJob common; 36 RateLimit limit; 37 BlockDriverState *active; 38 BlockDriverState *top; 39 BlockDriverState *base; 40 BlockdevOnError on_error; 41 int base_flags; 42 int orig_overlay_flags; 43 char *backing_file_str; 44 } CommitBlockJob; 45 46 static int coroutine_fn commit_populate(BlockDriverState *bs, 47 BlockDriverState *base, 48 int64_t sector_num, int nb_sectors, 49 void *buf) 50 { 51 int ret = 0; 52 53 ret = bdrv_read(bs, sector_num, buf, nb_sectors); 54 if (ret) { 55 return ret; 56 } 57 58 ret = bdrv_write(base, sector_num, buf, nb_sectors); 59 if (ret) { 60 return ret; 61 } 62 63 return 0; 64 } 65 66 typedef struct { 67 int ret; 68 } CommitCompleteData; 69 70 static void commit_complete(BlockJob *job, void *opaque) 71 { 72 CommitBlockJob *s = container_of(job, CommitBlockJob, common); 73 CommitCompleteData *data = opaque; 74 BlockDriverState *active = s->active; 75 BlockDriverState *top = s->top; 76 BlockDriverState *base = s->base; 77 BlockDriverState *overlay_bs; 78 int ret = data->ret; 79 80 if (!block_job_is_cancelled(&s->common) && ret == 0) { 81 /* success */ 82 ret = bdrv_drop_intermediate(active, top, base, s->backing_file_str); 83 } 84 85 /* restore base open flags here if appropriate (e.g., change the base back 86 * to r/o). These reopens do not need to be atomic, since we won't abort 87 * even on failure here */ 88 if (s->base_flags != bdrv_get_flags(base)) { 89 bdrv_reopen(base, s->base_flags, NULL); 90 } 91 overlay_bs = bdrv_find_overlay(active, top); 92 if (overlay_bs && s->orig_overlay_flags != bdrv_get_flags(overlay_bs)) { 93 bdrv_reopen(overlay_bs, s->orig_overlay_flags, NULL); 94 } 95 g_free(s->backing_file_str); 96 block_job_completed(&s->common, ret); 97 g_free(data); 98 } 99 100 static void coroutine_fn commit_run(void *opaque) 101 { 102 CommitBlockJob *s = opaque; 103 CommitCompleteData *data; 104 BlockDriverState *top = s->top; 105 BlockDriverState *base = s->base; 106 int64_t sector_num, end; 107 int ret = 0; 108 int n = 0; 109 void *buf = NULL; 110 int bytes_written = 0; 111 int64_t base_len; 112 113 ret = s->common.len = bdrv_getlength(top); 114 115 116 if (s->common.len < 0) { 117 goto out; 118 } 119 120 ret = base_len = bdrv_getlength(base); 121 if (base_len < 0) { 122 goto out; 123 } 124 125 if (base_len < s->common.len) { 126 ret = bdrv_truncate(base, s->common.len); 127 if (ret) { 128 goto out; 129 } 130 } 131 132 end = s->common.len >> BDRV_SECTOR_BITS; 133 buf = qemu_blockalign(top, COMMIT_BUFFER_SIZE); 134 135 for (sector_num = 0; sector_num < end; sector_num += n) { 136 uint64_t delay_ns = 0; 137 bool copy; 138 139 wait: 140 /* Note that even when no rate limit is applied we need to yield 141 * with no pending I/O here so that bdrv_drain_all() returns. 142 */ 143 block_job_sleep_ns(&s->common, QEMU_CLOCK_REALTIME, delay_ns); 144 if (block_job_is_cancelled(&s->common)) { 145 break; 146 } 147 /* Copy if allocated above the base */ 148 ret = bdrv_is_allocated_above(top, base, sector_num, 149 COMMIT_BUFFER_SIZE / BDRV_SECTOR_SIZE, 150 &n); 151 copy = (ret == 1); 152 trace_commit_one_iteration(s, sector_num, n, ret); 153 if (copy) { 154 if (s->common.speed) { 155 delay_ns = ratelimit_calculate_delay(&s->limit, n); 156 if (delay_ns > 0) { 157 goto wait; 158 } 159 } 160 ret = commit_populate(top, base, sector_num, n, buf); 161 bytes_written += n * BDRV_SECTOR_SIZE; 162 } 163 if (ret < 0) { 164 if (s->on_error == BLOCKDEV_ON_ERROR_STOP || 165 s->on_error == BLOCKDEV_ON_ERROR_REPORT|| 166 (s->on_error == BLOCKDEV_ON_ERROR_ENOSPC && ret == -ENOSPC)) { 167 goto out; 168 } else { 169 n = 0; 170 continue; 171 } 172 } 173 /* Publish progress */ 174 s->common.offset += n * BDRV_SECTOR_SIZE; 175 } 176 177 ret = 0; 178 179 out: 180 qemu_vfree(buf); 181 182 data = g_malloc(sizeof(*data)); 183 data->ret = ret; 184 block_job_defer_to_main_loop(&s->common, commit_complete, data); 185 } 186 187 static void commit_set_speed(BlockJob *job, int64_t speed, Error **errp) 188 { 189 CommitBlockJob *s = container_of(job, CommitBlockJob, common); 190 191 if (speed < 0) { 192 error_setg(errp, QERR_INVALID_PARAMETER, "speed"); 193 return; 194 } 195 ratelimit_set_speed(&s->limit, speed / BDRV_SECTOR_SIZE, SLICE_TIME); 196 } 197 198 static const BlockJobDriver commit_job_driver = { 199 .instance_size = sizeof(CommitBlockJob), 200 .job_type = BLOCK_JOB_TYPE_COMMIT, 201 .set_speed = commit_set_speed, 202 }; 203 204 void commit_start(BlockDriverState *bs, BlockDriverState *base, 205 BlockDriverState *top, int64_t speed, 206 BlockdevOnError on_error, BlockCompletionFunc *cb, 207 void *opaque, const char *backing_file_str, Error **errp) 208 { 209 CommitBlockJob *s; 210 BlockReopenQueue *reopen_queue = NULL; 211 int orig_overlay_flags; 212 int orig_base_flags; 213 BlockDriverState *overlay_bs; 214 Error *local_err = NULL; 215 216 if ((on_error == BLOCKDEV_ON_ERROR_STOP || 217 on_error == BLOCKDEV_ON_ERROR_ENOSPC) && 218 (!bs->blk || !blk_iostatus_is_enabled(bs->blk))) { 219 error_setg(errp, "Invalid parameter combination"); 220 return; 221 } 222 223 assert(top != bs); 224 if (top == base) { 225 error_setg(errp, "Invalid files for merge: top and base are the same"); 226 return; 227 } 228 229 overlay_bs = bdrv_find_overlay(bs, top); 230 231 if (overlay_bs == NULL) { 232 error_setg(errp, "Could not find overlay image for %s:", top->filename); 233 return; 234 } 235 236 orig_base_flags = bdrv_get_flags(base); 237 orig_overlay_flags = bdrv_get_flags(overlay_bs); 238 239 /* convert base & overlay_bs to r/w, if necessary */ 240 if (!(orig_overlay_flags & BDRV_O_RDWR)) { 241 reopen_queue = bdrv_reopen_queue(reopen_queue, overlay_bs, NULL, 242 orig_overlay_flags | BDRV_O_RDWR); 243 } 244 if (!(orig_base_flags & BDRV_O_RDWR)) { 245 reopen_queue = bdrv_reopen_queue(reopen_queue, base, NULL, 246 orig_base_flags | BDRV_O_RDWR); 247 } 248 if (reopen_queue) { 249 bdrv_reopen_multiple(reopen_queue, &local_err); 250 if (local_err != NULL) { 251 error_propagate(errp, local_err); 252 return; 253 } 254 } 255 256 257 s = block_job_create(&commit_job_driver, bs, speed, cb, opaque, errp); 258 if (!s) { 259 return; 260 } 261 262 s->base = base; 263 s->top = top; 264 s->active = bs; 265 266 s->base_flags = orig_base_flags; 267 s->orig_overlay_flags = orig_overlay_flags; 268 269 s->backing_file_str = g_strdup(backing_file_str); 270 271 s->on_error = on_error; 272 s->common.co = qemu_coroutine_create(commit_run); 273 274 trace_commit_start(bs, base, top, s, s->common.co, opaque); 275 qemu_coroutine_enter(s->common.co, s); 276 } 277