Statistics
| Branch: | Revision:

root / block / commit.c @ dc7588c1

History | View | Annotate | Download (7.3 kB)

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