Statistics
| Branch: | Revision:

root / blockjob.c @ 8cfd0495

History | View | Annotate | Download (7.6 kB)

1 2f0c9fe6 Paolo Bonzini
/*
2 2f0c9fe6 Paolo Bonzini
 * QEMU System Emulator block driver
3 2f0c9fe6 Paolo Bonzini
 *
4 2f0c9fe6 Paolo Bonzini
 * Copyright (c) 2011 IBM Corp.
5 2f0c9fe6 Paolo Bonzini
 * Copyright (c) 2012 Red Hat, Inc.
6 2f0c9fe6 Paolo Bonzini
 *
7 2f0c9fe6 Paolo Bonzini
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 2f0c9fe6 Paolo Bonzini
 * of this software and associated documentation files (the "Software"), to deal
9 2f0c9fe6 Paolo Bonzini
 * in the Software without restriction, including without limitation the rights
10 2f0c9fe6 Paolo Bonzini
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 2f0c9fe6 Paolo Bonzini
 * copies of the Software, and to permit persons to whom the Software is
12 2f0c9fe6 Paolo Bonzini
 * furnished to do so, subject to the following conditions:
13 2f0c9fe6 Paolo Bonzini
 *
14 2f0c9fe6 Paolo Bonzini
 * The above copyright notice and this permission notice shall be included in
15 2f0c9fe6 Paolo Bonzini
 * all copies or substantial portions of the Software.
16 2f0c9fe6 Paolo Bonzini
 *
17 2f0c9fe6 Paolo Bonzini
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 2f0c9fe6 Paolo Bonzini
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 2f0c9fe6 Paolo Bonzini
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 2f0c9fe6 Paolo Bonzini
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 2f0c9fe6 Paolo Bonzini
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 2f0c9fe6 Paolo Bonzini
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 2f0c9fe6 Paolo Bonzini
 * THE SOFTWARE.
24 2f0c9fe6 Paolo Bonzini
 */
25 2f0c9fe6 Paolo Bonzini
26 2f0c9fe6 Paolo Bonzini
#include "config-host.h"
27 2f0c9fe6 Paolo Bonzini
#include "qemu-common.h"
28 2f0c9fe6 Paolo Bonzini
#include "trace.h"
29 83c9089e Paolo Bonzini
#include "monitor/monitor.h"
30 737e150e Paolo Bonzini
#include "block/block.h"
31 737e150e Paolo Bonzini
#include "block/blockjob.h"
32 737e150e Paolo Bonzini
#include "block/block_int.h"
33 7b1b5d19 Paolo Bonzini
#include "qapi/qmp/qjson.h"
34 737e150e Paolo Bonzini
#include "block/coroutine.h"
35 2f0c9fe6 Paolo Bonzini
#include "qmp-commands.h"
36 1de7afc9 Paolo Bonzini
#include "qemu/timer.h"
37 2f0c9fe6 Paolo Bonzini
38 2f0c9fe6 Paolo Bonzini
void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs,
39 2f0c9fe6 Paolo Bonzini
                       int64_t speed, BlockDriverCompletionFunc *cb,
40 2f0c9fe6 Paolo Bonzini
                       void *opaque, Error **errp)
41 2f0c9fe6 Paolo Bonzini
{
42 2f0c9fe6 Paolo Bonzini
    BlockJob *job;
43 2f0c9fe6 Paolo Bonzini
44 2f0c9fe6 Paolo Bonzini
    if (bs->job || bdrv_in_use(bs)) {
45 2f0c9fe6 Paolo Bonzini
        error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs));
46 2f0c9fe6 Paolo Bonzini
        return NULL;
47 2f0c9fe6 Paolo Bonzini
    }
48 2f0c9fe6 Paolo Bonzini
    bdrv_set_in_use(bs, 1);
49 2f0c9fe6 Paolo Bonzini
50 2f0c9fe6 Paolo Bonzini
    job = g_malloc0(job_type->instance_size);
51 2f0c9fe6 Paolo Bonzini
    job->job_type      = job_type;
52 2f0c9fe6 Paolo Bonzini
    job->bs            = bs;
53 2f0c9fe6 Paolo Bonzini
    job->cb            = cb;
54 2f0c9fe6 Paolo Bonzini
    job->opaque        = opaque;
55 2f0c9fe6 Paolo Bonzini
    job->busy          = true;
56 2f0c9fe6 Paolo Bonzini
    bs->job = job;
57 2f0c9fe6 Paolo Bonzini
58 2f0c9fe6 Paolo Bonzini
    /* Only set speed when necessary to avoid NotSupported error */
59 2f0c9fe6 Paolo Bonzini
    if (speed != 0) {
60 2f0c9fe6 Paolo Bonzini
        Error *local_err = NULL;
61 2f0c9fe6 Paolo Bonzini
62 2f0c9fe6 Paolo Bonzini
        block_job_set_speed(job, speed, &local_err);
63 2f0c9fe6 Paolo Bonzini
        if (error_is_set(&local_err)) {
64 2f0c9fe6 Paolo Bonzini
            bs->job = NULL;
65 2f0c9fe6 Paolo Bonzini
            g_free(job);
66 2f0c9fe6 Paolo Bonzini
            bdrv_set_in_use(bs, 0);
67 2f0c9fe6 Paolo Bonzini
            error_propagate(errp, local_err);
68 2f0c9fe6 Paolo Bonzini
            return NULL;
69 2f0c9fe6 Paolo Bonzini
        }
70 2f0c9fe6 Paolo Bonzini
    }
71 2f0c9fe6 Paolo Bonzini
    return job;
72 2f0c9fe6 Paolo Bonzini
}
73 2f0c9fe6 Paolo Bonzini
74 65f46322 Paolo Bonzini
void block_job_completed(BlockJob *job, int ret)
75 2f0c9fe6 Paolo Bonzini
{
76 2f0c9fe6 Paolo Bonzini
    BlockDriverState *bs = job->bs;
77 2f0c9fe6 Paolo Bonzini
78 2f0c9fe6 Paolo Bonzini
    assert(bs->job == job);
79 2f0c9fe6 Paolo Bonzini
    job->cb(job->opaque, ret);
80 2f0c9fe6 Paolo Bonzini
    bs->job = NULL;
81 2f0c9fe6 Paolo Bonzini
    g_free(job);
82 2f0c9fe6 Paolo Bonzini
    bdrv_set_in_use(bs, 0);
83 2f0c9fe6 Paolo Bonzini
}
84 2f0c9fe6 Paolo Bonzini
85 2f0c9fe6 Paolo Bonzini
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
86 2f0c9fe6 Paolo Bonzini
{
87 2f0c9fe6 Paolo Bonzini
    Error *local_err = NULL;
88 2f0c9fe6 Paolo Bonzini
89 2f0c9fe6 Paolo Bonzini
    if (!job->job_type->set_speed) {
90 2f0c9fe6 Paolo Bonzini
        error_set(errp, QERR_NOT_SUPPORTED);
91 2f0c9fe6 Paolo Bonzini
        return;
92 2f0c9fe6 Paolo Bonzini
    }
93 2f0c9fe6 Paolo Bonzini
    job->job_type->set_speed(job, speed, &local_err);
94 2f0c9fe6 Paolo Bonzini
    if (error_is_set(&local_err)) {
95 2f0c9fe6 Paolo Bonzini
        error_propagate(errp, local_err);
96 2f0c9fe6 Paolo Bonzini
        return;
97 2f0c9fe6 Paolo Bonzini
    }
98 2f0c9fe6 Paolo Bonzini
99 2f0c9fe6 Paolo Bonzini
    job->speed = speed;
100 2f0c9fe6 Paolo Bonzini
}
101 2f0c9fe6 Paolo Bonzini
102 aeae883b Paolo Bonzini
void block_job_complete(BlockJob *job, Error **errp)
103 aeae883b Paolo Bonzini
{
104 aeae883b Paolo Bonzini
    if (job->paused || job->cancelled || !job->job_type->complete) {
105 aeae883b Paolo Bonzini
        error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
106 aeae883b Paolo Bonzini
        return;
107 aeae883b Paolo Bonzini
    }
108 aeae883b Paolo Bonzini
109 aeae883b Paolo Bonzini
    job->job_type->complete(job, errp);
110 aeae883b Paolo Bonzini
}
111 aeae883b Paolo Bonzini
112 8acc72a4 Paolo Bonzini
void block_job_pause(BlockJob *job)
113 2f0c9fe6 Paolo Bonzini
{
114 8acc72a4 Paolo Bonzini
    job->paused = true;
115 8acc72a4 Paolo Bonzini
}
116 8acc72a4 Paolo Bonzini
117 8acc72a4 Paolo Bonzini
bool block_job_is_paused(BlockJob *job)
118 8acc72a4 Paolo Bonzini
{
119 8acc72a4 Paolo Bonzini
    return job->paused;
120 8acc72a4 Paolo Bonzini
}
121 8acc72a4 Paolo Bonzini
122 8acc72a4 Paolo Bonzini
void block_job_resume(BlockJob *job)
123 8acc72a4 Paolo Bonzini
{
124 8acc72a4 Paolo Bonzini
    job->paused = false;
125 32c81a4a Paolo Bonzini
    block_job_iostatus_reset(job);
126 2f0c9fe6 Paolo Bonzini
    if (job->co && !job->busy) {
127 2f0c9fe6 Paolo Bonzini
        qemu_coroutine_enter(job->co, NULL);
128 2f0c9fe6 Paolo Bonzini
    }
129 2f0c9fe6 Paolo Bonzini
}
130 2f0c9fe6 Paolo Bonzini
131 8acc72a4 Paolo Bonzini
void block_job_cancel(BlockJob *job)
132 8acc72a4 Paolo Bonzini
{
133 8acc72a4 Paolo Bonzini
    job->cancelled = true;
134 8acc72a4 Paolo Bonzini
    block_job_resume(job);
135 8acc72a4 Paolo Bonzini
}
136 8acc72a4 Paolo Bonzini
137 2f0c9fe6 Paolo Bonzini
bool block_job_is_cancelled(BlockJob *job)
138 2f0c9fe6 Paolo Bonzini
{
139 2f0c9fe6 Paolo Bonzini
    return job->cancelled;
140 2f0c9fe6 Paolo Bonzini
}
141 2f0c9fe6 Paolo Bonzini
142 32c81a4a Paolo Bonzini
void block_job_iostatus_reset(BlockJob *job)
143 32c81a4a Paolo Bonzini
{
144 32c81a4a Paolo Bonzini
    job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
145 3bd293c3 Paolo Bonzini
    if (job->job_type->iostatus_reset) {
146 3bd293c3 Paolo Bonzini
        job->job_type->iostatus_reset(job);
147 3bd293c3 Paolo Bonzini
    }
148 32c81a4a Paolo Bonzini
}
149 32c81a4a Paolo Bonzini
150 2f0c9fe6 Paolo Bonzini
struct BlockCancelData {
151 2f0c9fe6 Paolo Bonzini
    BlockJob *job;
152 2f0c9fe6 Paolo Bonzini
    BlockDriverCompletionFunc *cb;
153 2f0c9fe6 Paolo Bonzini
    void *opaque;
154 2f0c9fe6 Paolo Bonzini
    bool cancelled;
155 2f0c9fe6 Paolo Bonzini
    int ret;
156 2f0c9fe6 Paolo Bonzini
};
157 2f0c9fe6 Paolo Bonzini
158 2f0c9fe6 Paolo Bonzini
static void block_job_cancel_cb(void *opaque, int ret)
159 2f0c9fe6 Paolo Bonzini
{
160 2f0c9fe6 Paolo Bonzini
    struct BlockCancelData *data = opaque;
161 2f0c9fe6 Paolo Bonzini
162 2f0c9fe6 Paolo Bonzini
    data->cancelled = block_job_is_cancelled(data->job);
163 2f0c9fe6 Paolo Bonzini
    data->ret = ret;
164 2f0c9fe6 Paolo Bonzini
    data->cb(data->opaque, ret);
165 2f0c9fe6 Paolo Bonzini
}
166 2f0c9fe6 Paolo Bonzini
167 2f0c9fe6 Paolo Bonzini
int block_job_cancel_sync(BlockJob *job)
168 2f0c9fe6 Paolo Bonzini
{
169 2f0c9fe6 Paolo Bonzini
    struct BlockCancelData data;
170 2f0c9fe6 Paolo Bonzini
    BlockDriverState *bs = job->bs;
171 2f0c9fe6 Paolo Bonzini
172 2f0c9fe6 Paolo Bonzini
    assert(bs->job == job);
173 2f0c9fe6 Paolo Bonzini
174 2f0c9fe6 Paolo Bonzini
    /* Set up our own callback to store the result and chain to
175 2f0c9fe6 Paolo Bonzini
     * the original callback.
176 2f0c9fe6 Paolo Bonzini
     */
177 2f0c9fe6 Paolo Bonzini
    data.job = job;
178 2f0c9fe6 Paolo Bonzini
    data.cb = job->cb;
179 2f0c9fe6 Paolo Bonzini
    data.opaque = job->opaque;
180 2f0c9fe6 Paolo Bonzini
    data.ret = -EINPROGRESS;
181 2f0c9fe6 Paolo Bonzini
    job->cb = block_job_cancel_cb;
182 2f0c9fe6 Paolo Bonzini
    job->opaque = &data;
183 2f0c9fe6 Paolo Bonzini
    block_job_cancel(job);
184 2f0c9fe6 Paolo Bonzini
    while (data.ret == -EINPROGRESS) {
185 2f0c9fe6 Paolo Bonzini
        qemu_aio_wait();
186 2f0c9fe6 Paolo Bonzini
    }
187 2f0c9fe6 Paolo Bonzini
    return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
188 2f0c9fe6 Paolo Bonzini
}
189 2f0c9fe6 Paolo Bonzini
190 7483d1e5 Alex Bligh
void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns)
191 2f0c9fe6 Paolo Bonzini
{
192 8acc72a4 Paolo Bonzini
    assert(job->busy);
193 8acc72a4 Paolo Bonzini
194 2f0c9fe6 Paolo Bonzini
    /* Check cancellation *before* setting busy = false, too!  */
195 8acc72a4 Paolo Bonzini
    if (block_job_is_cancelled(job)) {
196 8acc72a4 Paolo Bonzini
        return;
197 8acc72a4 Paolo Bonzini
    }
198 8acc72a4 Paolo Bonzini
199 8acc72a4 Paolo Bonzini
    job->busy = false;
200 8acc72a4 Paolo Bonzini
    if (block_job_is_paused(job)) {
201 8acc72a4 Paolo Bonzini
        qemu_coroutine_yield();
202 8acc72a4 Paolo Bonzini
    } else {
203 7483d1e5 Alex Bligh
        co_sleep_ns(type, ns);
204 2f0c9fe6 Paolo Bonzini
    }
205 8acc72a4 Paolo Bonzini
    job->busy = true;
206 2f0c9fe6 Paolo Bonzini
}
207 30e628b7 Paolo Bonzini
208 30e628b7 Paolo Bonzini
BlockJobInfo *block_job_query(BlockJob *job)
209 30e628b7 Paolo Bonzini
{
210 30e628b7 Paolo Bonzini
    BlockJobInfo *info = g_new0(BlockJobInfo, 1);
211 32c81a4a Paolo Bonzini
    info->type      = g_strdup(job->job_type->job_type);
212 32c81a4a Paolo Bonzini
    info->device    = g_strdup(bdrv_get_device_name(job->bs));
213 32c81a4a Paolo Bonzini
    info->len       = job->len;
214 32c81a4a Paolo Bonzini
    info->busy      = job->busy;
215 32c81a4a Paolo Bonzini
    info->paused    = job->paused;
216 32c81a4a Paolo Bonzini
    info->offset    = job->offset;
217 32c81a4a Paolo Bonzini
    info->speed     = job->speed;
218 32c81a4a Paolo Bonzini
    info->io_status = job->iostatus;
219 30e628b7 Paolo Bonzini
    return info;
220 30e628b7 Paolo Bonzini
}
221 32c81a4a Paolo Bonzini
222 32c81a4a Paolo Bonzini
static void block_job_iostatus_set_err(BlockJob *job, int error)
223 32c81a4a Paolo Bonzini
{
224 32c81a4a Paolo Bonzini
    if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
225 32c81a4a Paolo Bonzini
        job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
226 32c81a4a Paolo Bonzini
                                          BLOCK_DEVICE_IO_STATUS_FAILED;
227 32c81a4a Paolo Bonzini
    }
228 32c81a4a Paolo Bonzini
}
229 32c81a4a Paolo Bonzini
230 32c81a4a Paolo Bonzini
231 a66a2a36 Paolo Bonzini
QObject *qobject_from_block_job(BlockJob *job)
232 a66a2a36 Paolo Bonzini
{
233 a66a2a36 Paolo Bonzini
    return qobject_from_jsonf("{ 'type': %s,"
234 a66a2a36 Paolo Bonzini
                              "'device': %s,"
235 a66a2a36 Paolo Bonzini
                              "'len': %" PRId64 ","
236 a66a2a36 Paolo Bonzini
                              "'offset': %" PRId64 ","
237 a66a2a36 Paolo Bonzini
                              "'speed': %" PRId64 " }",
238 a66a2a36 Paolo Bonzini
                              job->job_type->job_type,
239 a66a2a36 Paolo Bonzini
                              bdrv_get_device_name(job->bs),
240 a66a2a36 Paolo Bonzini
                              job->len,
241 a66a2a36 Paolo Bonzini
                              job->offset,
242 a66a2a36 Paolo Bonzini
                              job->speed);
243 a66a2a36 Paolo Bonzini
}
244 a66a2a36 Paolo Bonzini
245 a66a2a36 Paolo Bonzini
void block_job_ready(BlockJob *job)
246 a66a2a36 Paolo Bonzini
{
247 a66a2a36 Paolo Bonzini
    QObject *data = qobject_from_block_job(job);
248 a66a2a36 Paolo Bonzini
    monitor_protocol_event(QEVENT_BLOCK_JOB_READY, data);
249 a66a2a36 Paolo Bonzini
    qobject_decref(data);
250 a66a2a36 Paolo Bonzini
}
251 a66a2a36 Paolo Bonzini
252 32c81a4a Paolo Bonzini
BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
253 32c81a4a Paolo Bonzini
                                        BlockdevOnError on_err,
254 32c81a4a Paolo Bonzini
                                        int is_read, int error)
255 32c81a4a Paolo Bonzini
{
256 32c81a4a Paolo Bonzini
    BlockErrorAction action;
257 32c81a4a Paolo Bonzini
258 32c81a4a Paolo Bonzini
    switch (on_err) {
259 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_ENOSPC:
260 32c81a4a Paolo Bonzini
        action = (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT;
261 32c81a4a Paolo Bonzini
        break;
262 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_STOP:
263 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_STOP;
264 32c81a4a Paolo Bonzini
        break;
265 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_REPORT:
266 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_REPORT;
267 32c81a4a Paolo Bonzini
        break;
268 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_IGNORE:
269 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_IGNORE;
270 32c81a4a Paolo Bonzini
        break;
271 32c81a4a Paolo Bonzini
    default:
272 32c81a4a Paolo Bonzini
        abort();
273 32c81a4a Paolo Bonzini
    }
274 32c81a4a Paolo Bonzini
    bdrv_emit_qmp_error_event(job->bs, QEVENT_BLOCK_JOB_ERROR, action, is_read);
275 32c81a4a Paolo Bonzini
    if (action == BDRV_ACTION_STOP) {
276 32c81a4a Paolo Bonzini
        block_job_pause(job);
277 32c81a4a Paolo Bonzini
        block_job_iostatus_set_err(job, error);
278 32c81a4a Paolo Bonzini
        if (bs != job->bs) {
279 32c81a4a Paolo Bonzini
            bdrv_iostatus_set_err(bs, error);
280 32c81a4a Paolo Bonzini
        }
281 32c81a4a Paolo Bonzini
    }
282 32c81a4a Paolo Bonzini
    return action;
283 32c81a4a Paolo Bonzini
}