Statistics
| Branch: | Revision:

root / blockjob.c @ 34b5d2c6

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 fa510ebf Fam Zheng
    bdrv_ref(bs);
49 2f0c9fe6 Paolo Bonzini
    bdrv_set_in_use(bs, 1);
50 2f0c9fe6 Paolo Bonzini
51 2f0c9fe6 Paolo Bonzini
    job = g_malloc0(job_type->instance_size);
52 2f0c9fe6 Paolo Bonzini
    job->job_type      = job_type;
53 2f0c9fe6 Paolo Bonzini
    job->bs            = bs;
54 2f0c9fe6 Paolo Bonzini
    job->cb            = cb;
55 2f0c9fe6 Paolo Bonzini
    job->opaque        = opaque;
56 2f0c9fe6 Paolo Bonzini
    job->busy          = true;
57 2f0c9fe6 Paolo Bonzini
    bs->job = job;
58 2f0c9fe6 Paolo Bonzini
59 2f0c9fe6 Paolo Bonzini
    /* Only set speed when necessary to avoid NotSupported error */
60 2f0c9fe6 Paolo Bonzini
    if (speed != 0) {
61 2f0c9fe6 Paolo Bonzini
        Error *local_err = NULL;
62 2f0c9fe6 Paolo Bonzini
63 2f0c9fe6 Paolo Bonzini
        block_job_set_speed(job, speed, &local_err);
64 2f0c9fe6 Paolo Bonzini
        if (error_is_set(&local_err)) {
65 2f0c9fe6 Paolo Bonzini
            bs->job = NULL;
66 2f0c9fe6 Paolo Bonzini
            g_free(job);
67 2f0c9fe6 Paolo Bonzini
            bdrv_set_in_use(bs, 0);
68 2f0c9fe6 Paolo Bonzini
            error_propagate(errp, local_err);
69 2f0c9fe6 Paolo Bonzini
            return NULL;
70 2f0c9fe6 Paolo Bonzini
        }
71 2f0c9fe6 Paolo Bonzini
    }
72 2f0c9fe6 Paolo Bonzini
    return job;
73 2f0c9fe6 Paolo Bonzini
}
74 2f0c9fe6 Paolo Bonzini
75 65f46322 Paolo Bonzini
void block_job_completed(BlockJob *job, int ret)
76 2f0c9fe6 Paolo Bonzini
{
77 2f0c9fe6 Paolo Bonzini
    BlockDriverState *bs = job->bs;
78 2f0c9fe6 Paolo Bonzini
79 2f0c9fe6 Paolo Bonzini
    assert(bs->job == job);
80 2f0c9fe6 Paolo Bonzini
    job->cb(job->opaque, ret);
81 2f0c9fe6 Paolo Bonzini
    bs->job = NULL;
82 2f0c9fe6 Paolo Bonzini
    g_free(job);
83 2f0c9fe6 Paolo Bonzini
    bdrv_set_in_use(bs, 0);
84 2f0c9fe6 Paolo Bonzini
}
85 2f0c9fe6 Paolo Bonzini
86 2f0c9fe6 Paolo Bonzini
void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp)
87 2f0c9fe6 Paolo Bonzini
{
88 2f0c9fe6 Paolo Bonzini
    Error *local_err = NULL;
89 2f0c9fe6 Paolo Bonzini
90 2f0c9fe6 Paolo Bonzini
    if (!job->job_type->set_speed) {
91 2f0c9fe6 Paolo Bonzini
        error_set(errp, QERR_NOT_SUPPORTED);
92 2f0c9fe6 Paolo Bonzini
        return;
93 2f0c9fe6 Paolo Bonzini
    }
94 2f0c9fe6 Paolo Bonzini
    job->job_type->set_speed(job, speed, &local_err);
95 2f0c9fe6 Paolo Bonzini
    if (error_is_set(&local_err)) {
96 2f0c9fe6 Paolo Bonzini
        error_propagate(errp, local_err);
97 2f0c9fe6 Paolo Bonzini
        return;
98 2f0c9fe6 Paolo Bonzini
    }
99 2f0c9fe6 Paolo Bonzini
100 2f0c9fe6 Paolo Bonzini
    job->speed = speed;
101 2f0c9fe6 Paolo Bonzini
}
102 2f0c9fe6 Paolo Bonzini
103 aeae883b Paolo Bonzini
void block_job_complete(BlockJob *job, Error **errp)
104 aeae883b Paolo Bonzini
{
105 aeae883b Paolo Bonzini
    if (job->paused || job->cancelled || !job->job_type->complete) {
106 aeae883b Paolo Bonzini
        error_set(errp, QERR_BLOCK_JOB_NOT_READY, job->bs->device_name);
107 aeae883b Paolo Bonzini
        return;
108 aeae883b Paolo Bonzini
    }
109 aeae883b Paolo Bonzini
110 aeae883b Paolo Bonzini
    job->job_type->complete(job, errp);
111 aeae883b Paolo Bonzini
}
112 aeae883b Paolo Bonzini
113 8acc72a4 Paolo Bonzini
void block_job_pause(BlockJob *job)
114 2f0c9fe6 Paolo Bonzini
{
115 8acc72a4 Paolo Bonzini
    job->paused = true;
116 8acc72a4 Paolo Bonzini
}
117 8acc72a4 Paolo Bonzini
118 8acc72a4 Paolo Bonzini
bool block_job_is_paused(BlockJob *job)
119 8acc72a4 Paolo Bonzini
{
120 8acc72a4 Paolo Bonzini
    return job->paused;
121 8acc72a4 Paolo Bonzini
}
122 8acc72a4 Paolo Bonzini
123 8acc72a4 Paolo Bonzini
void block_job_resume(BlockJob *job)
124 8acc72a4 Paolo Bonzini
{
125 8acc72a4 Paolo Bonzini
    job->paused = false;
126 32c81a4a Paolo Bonzini
    block_job_iostatus_reset(job);
127 2f0c9fe6 Paolo Bonzini
    if (job->co && !job->busy) {
128 2f0c9fe6 Paolo Bonzini
        qemu_coroutine_enter(job->co, NULL);
129 2f0c9fe6 Paolo Bonzini
    }
130 2f0c9fe6 Paolo Bonzini
}
131 2f0c9fe6 Paolo Bonzini
132 8acc72a4 Paolo Bonzini
void block_job_cancel(BlockJob *job)
133 8acc72a4 Paolo Bonzini
{
134 8acc72a4 Paolo Bonzini
    job->cancelled = true;
135 8acc72a4 Paolo Bonzini
    block_job_resume(job);
136 8acc72a4 Paolo Bonzini
}
137 8acc72a4 Paolo Bonzini
138 2f0c9fe6 Paolo Bonzini
bool block_job_is_cancelled(BlockJob *job)
139 2f0c9fe6 Paolo Bonzini
{
140 2f0c9fe6 Paolo Bonzini
    return job->cancelled;
141 2f0c9fe6 Paolo Bonzini
}
142 2f0c9fe6 Paolo Bonzini
143 32c81a4a Paolo Bonzini
void block_job_iostatus_reset(BlockJob *job)
144 32c81a4a Paolo Bonzini
{
145 32c81a4a Paolo Bonzini
    job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
146 3bd293c3 Paolo Bonzini
    if (job->job_type->iostatus_reset) {
147 3bd293c3 Paolo Bonzini
        job->job_type->iostatus_reset(job);
148 3bd293c3 Paolo Bonzini
    }
149 32c81a4a Paolo Bonzini
}
150 32c81a4a Paolo Bonzini
151 2f0c9fe6 Paolo Bonzini
struct BlockCancelData {
152 2f0c9fe6 Paolo Bonzini
    BlockJob *job;
153 2f0c9fe6 Paolo Bonzini
    BlockDriverCompletionFunc *cb;
154 2f0c9fe6 Paolo Bonzini
    void *opaque;
155 2f0c9fe6 Paolo Bonzini
    bool cancelled;
156 2f0c9fe6 Paolo Bonzini
    int ret;
157 2f0c9fe6 Paolo Bonzini
};
158 2f0c9fe6 Paolo Bonzini
159 2f0c9fe6 Paolo Bonzini
static void block_job_cancel_cb(void *opaque, int ret)
160 2f0c9fe6 Paolo Bonzini
{
161 2f0c9fe6 Paolo Bonzini
    struct BlockCancelData *data = opaque;
162 2f0c9fe6 Paolo Bonzini
163 2f0c9fe6 Paolo Bonzini
    data->cancelled = block_job_is_cancelled(data->job);
164 2f0c9fe6 Paolo Bonzini
    data->ret = ret;
165 2f0c9fe6 Paolo Bonzini
    data->cb(data->opaque, ret);
166 2f0c9fe6 Paolo Bonzini
}
167 2f0c9fe6 Paolo Bonzini
168 2f0c9fe6 Paolo Bonzini
int block_job_cancel_sync(BlockJob *job)
169 2f0c9fe6 Paolo Bonzini
{
170 2f0c9fe6 Paolo Bonzini
    struct BlockCancelData data;
171 2f0c9fe6 Paolo Bonzini
    BlockDriverState *bs = job->bs;
172 2f0c9fe6 Paolo Bonzini
173 2f0c9fe6 Paolo Bonzini
    assert(bs->job == job);
174 2f0c9fe6 Paolo Bonzini
175 2f0c9fe6 Paolo Bonzini
    /* Set up our own callback to store the result and chain to
176 2f0c9fe6 Paolo Bonzini
     * the original callback.
177 2f0c9fe6 Paolo Bonzini
     */
178 2f0c9fe6 Paolo Bonzini
    data.job = job;
179 2f0c9fe6 Paolo Bonzini
    data.cb = job->cb;
180 2f0c9fe6 Paolo Bonzini
    data.opaque = job->opaque;
181 2f0c9fe6 Paolo Bonzini
    data.ret = -EINPROGRESS;
182 2f0c9fe6 Paolo Bonzini
    job->cb = block_job_cancel_cb;
183 2f0c9fe6 Paolo Bonzini
    job->opaque = &data;
184 2f0c9fe6 Paolo Bonzini
    block_job_cancel(job);
185 2f0c9fe6 Paolo Bonzini
    while (data.ret == -EINPROGRESS) {
186 2f0c9fe6 Paolo Bonzini
        qemu_aio_wait();
187 2f0c9fe6 Paolo Bonzini
    }
188 2f0c9fe6 Paolo Bonzini
    return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
189 2f0c9fe6 Paolo Bonzini
}
190 2f0c9fe6 Paolo Bonzini
191 7483d1e5 Alex Bligh
void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns)
192 2f0c9fe6 Paolo Bonzini
{
193 8acc72a4 Paolo Bonzini
    assert(job->busy);
194 8acc72a4 Paolo Bonzini
195 2f0c9fe6 Paolo Bonzini
    /* Check cancellation *before* setting busy = false, too!  */
196 8acc72a4 Paolo Bonzini
    if (block_job_is_cancelled(job)) {
197 8acc72a4 Paolo Bonzini
        return;
198 8acc72a4 Paolo Bonzini
    }
199 8acc72a4 Paolo Bonzini
200 8acc72a4 Paolo Bonzini
    job->busy = false;
201 8acc72a4 Paolo Bonzini
    if (block_job_is_paused(job)) {
202 8acc72a4 Paolo Bonzini
        qemu_coroutine_yield();
203 8acc72a4 Paolo Bonzini
    } else {
204 7483d1e5 Alex Bligh
        co_sleep_ns(type, ns);
205 2f0c9fe6 Paolo Bonzini
    }
206 8acc72a4 Paolo Bonzini
    job->busy = true;
207 2f0c9fe6 Paolo Bonzini
}
208 30e628b7 Paolo Bonzini
209 30e628b7 Paolo Bonzini
BlockJobInfo *block_job_query(BlockJob *job)
210 30e628b7 Paolo Bonzini
{
211 30e628b7 Paolo Bonzini
    BlockJobInfo *info = g_new0(BlockJobInfo, 1);
212 32c81a4a Paolo Bonzini
    info->type      = g_strdup(job->job_type->job_type);
213 32c81a4a Paolo Bonzini
    info->device    = g_strdup(bdrv_get_device_name(job->bs));
214 32c81a4a Paolo Bonzini
    info->len       = job->len;
215 32c81a4a Paolo Bonzini
    info->busy      = job->busy;
216 32c81a4a Paolo Bonzini
    info->paused    = job->paused;
217 32c81a4a Paolo Bonzini
    info->offset    = job->offset;
218 32c81a4a Paolo Bonzini
    info->speed     = job->speed;
219 32c81a4a Paolo Bonzini
    info->io_status = job->iostatus;
220 30e628b7 Paolo Bonzini
    return info;
221 30e628b7 Paolo Bonzini
}
222 32c81a4a Paolo Bonzini
223 32c81a4a Paolo Bonzini
static void block_job_iostatus_set_err(BlockJob *job, int error)
224 32c81a4a Paolo Bonzini
{
225 32c81a4a Paolo Bonzini
    if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
226 32c81a4a Paolo Bonzini
        job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
227 32c81a4a Paolo Bonzini
                                          BLOCK_DEVICE_IO_STATUS_FAILED;
228 32c81a4a Paolo Bonzini
    }
229 32c81a4a Paolo Bonzini
}
230 32c81a4a Paolo Bonzini
231 32c81a4a Paolo Bonzini
232 a66a2a36 Paolo Bonzini
QObject *qobject_from_block_job(BlockJob *job)
233 a66a2a36 Paolo Bonzini
{
234 a66a2a36 Paolo Bonzini
    return qobject_from_jsonf("{ 'type': %s,"
235 a66a2a36 Paolo Bonzini
                              "'device': %s,"
236 a66a2a36 Paolo Bonzini
                              "'len': %" PRId64 ","
237 a66a2a36 Paolo Bonzini
                              "'offset': %" PRId64 ","
238 a66a2a36 Paolo Bonzini
                              "'speed': %" PRId64 " }",
239 a66a2a36 Paolo Bonzini
                              job->job_type->job_type,
240 a66a2a36 Paolo Bonzini
                              bdrv_get_device_name(job->bs),
241 a66a2a36 Paolo Bonzini
                              job->len,
242 a66a2a36 Paolo Bonzini
                              job->offset,
243 a66a2a36 Paolo Bonzini
                              job->speed);
244 a66a2a36 Paolo Bonzini
}
245 a66a2a36 Paolo Bonzini
246 a66a2a36 Paolo Bonzini
void block_job_ready(BlockJob *job)
247 a66a2a36 Paolo Bonzini
{
248 a66a2a36 Paolo Bonzini
    QObject *data = qobject_from_block_job(job);
249 a66a2a36 Paolo Bonzini
    monitor_protocol_event(QEVENT_BLOCK_JOB_READY, data);
250 a66a2a36 Paolo Bonzini
    qobject_decref(data);
251 a66a2a36 Paolo Bonzini
}
252 a66a2a36 Paolo Bonzini
253 32c81a4a Paolo Bonzini
BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
254 32c81a4a Paolo Bonzini
                                        BlockdevOnError on_err,
255 32c81a4a Paolo Bonzini
                                        int is_read, int error)
256 32c81a4a Paolo Bonzini
{
257 32c81a4a Paolo Bonzini
    BlockErrorAction action;
258 32c81a4a Paolo Bonzini
259 32c81a4a Paolo Bonzini
    switch (on_err) {
260 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_ENOSPC:
261 32c81a4a Paolo Bonzini
        action = (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT;
262 32c81a4a Paolo Bonzini
        break;
263 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_STOP:
264 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_STOP;
265 32c81a4a Paolo Bonzini
        break;
266 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_REPORT:
267 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_REPORT;
268 32c81a4a Paolo Bonzini
        break;
269 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_IGNORE:
270 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_IGNORE;
271 32c81a4a Paolo Bonzini
        break;
272 32c81a4a Paolo Bonzini
    default:
273 32c81a4a Paolo Bonzini
        abort();
274 32c81a4a Paolo Bonzini
    }
275 32c81a4a Paolo Bonzini
    bdrv_emit_qmp_error_event(job->bs, QEVENT_BLOCK_JOB_ERROR, action, is_read);
276 32c81a4a Paolo Bonzini
    if (action == BDRV_ACTION_STOP) {
277 32c81a4a Paolo Bonzini
        block_job_pause(job);
278 32c81a4a Paolo Bonzini
        block_job_iostatus_set_err(job, error);
279 32c81a4a Paolo Bonzini
        if (bs != job->bs) {
280 32c81a4a Paolo Bonzini
            bdrv_iostatus_set_err(bs, error);
281 32c81a4a Paolo Bonzini
        }
282 32c81a4a Paolo Bonzini
    }
283 32c81a4a Paolo Bonzini
    return action;
284 32c81a4a Paolo Bonzini
}