Statistics
| Branch: | Revision:

root / blockjob.c @ 95d2994a

History | View | Annotate | Download (6.5 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 2f0c9fe6 Paolo Bonzini
#include "monitor.h"
30 2f0c9fe6 Paolo Bonzini
#include "block.h"
31 2f0c9fe6 Paolo Bonzini
#include "blockjob.h"
32 2f0c9fe6 Paolo Bonzini
#include "block_int.h"
33 2f0c9fe6 Paolo Bonzini
#include "qjson.h"
34 2f0c9fe6 Paolo Bonzini
#include "qemu-coroutine.h"
35 2f0c9fe6 Paolo Bonzini
#include "qmp-commands.h"
36 2f0c9fe6 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 2f0c9fe6 Paolo Bonzini
void block_job_complete(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 8acc72a4 Paolo Bonzini
void block_job_pause(BlockJob *job)
103 2f0c9fe6 Paolo Bonzini
{
104 8acc72a4 Paolo Bonzini
    job->paused = true;
105 8acc72a4 Paolo Bonzini
}
106 8acc72a4 Paolo Bonzini
107 8acc72a4 Paolo Bonzini
bool block_job_is_paused(BlockJob *job)
108 8acc72a4 Paolo Bonzini
{
109 8acc72a4 Paolo Bonzini
    return job->paused;
110 8acc72a4 Paolo Bonzini
}
111 8acc72a4 Paolo Bonzini
112 8acc72a4 Paolo Bonzini
void block_job_resume(BlockJob *job)
113 8acc72a4 Paolo Bonzini
{
114 8acc72a4 Paolo Bonzini
    job->paused = false;
115 32c81a4a Paolo Bonzini
    block_job_iostatus_reset(job);
116 2f0c9fe6 Paolo Bonzini
    if (job->co && !job->busy) {
117 2f0c9fe6 Paolo Bonzini
        qemu_coroutine_enter(job->co, NULL);
118 2f0c9fe6 Paolo Bonzini
    }
119 2f0c9fe6 Paolo Bonzini
}
120 2f0c9fe6 Paolo Bonzini
121 8acc72a4 Paolo Bonzini
void block_job_cancel(BlockJob *job)
122 8acc72a4 Paolo Bonzini
{
123 8acc72a4 Paolo Bonzini
    job->cancelled = true;
124 8acc72a4 Paolo Bonzini
    block_job_resume(job);
125 8acc72a4 Paolo Bonzini
}
126 8acc72a4 Paolo Bonzini
127 2f0c9fe6 Paolo Bonzini
bool block_job_is_cancelled(BlockJob *job)
128 2f0c9fe6 Paolo Bonzini
{
129 2f0c9fe6 Paolo Bonzini
    return job->cancelled;
130 2f0c9fe6 Paolo Bonzini
}
131 2f0c9fe6 Paolo Bonzini
132 32c81a4a Paolo Bonzini
void block_job_iostatus_reset(BlockJob *job)
133 32c81a4a Paolo Bonzini
{
134 32c81a4a Paolo Bonzini
    job->iostatus = BLOCK_DEVICE_IO_STATUS_OK;
135 32c81a4a Paolo Bonzini
}
136 32c81a4a Paolo Bonzini
137 2f0c9fe6 Paolo Bonzini
struct BlockCancelData {
138 2f0c9fe6 Paolo Bonzini
    BlockJob *job;
139 2f0c9fe6 Paolo Bonzini
    BlockDriverCompletionFunc *cb;
140 2f0c9fe6 Paolo Bonzini
    void *opaque;
141 2f0c9fe6 Paolo Bonzini
    bool cancelled;
142 2f0c9fe6 Paolo Bonzini
    int ret;
143 2f0c9fe6 Paolo Bonzini
};
144 2f0c9fe6 Paolo Bonzini
145 2f0c9fe6 Paolo Bonzini
static void block_job_cancel_cb(void *opaque, int ret)
146 2f0c9fe6 Paolo Bonzini
{
147 2f0c9fe6 Paolo Bonzini
    struct BlockCancelData *data = opaque;
148 2f0c9fe6 Paolo Bonzini
149 2f0c9fe6 Paolo Bonzini
    data->cancelled = block_job_is_cancelled(data->job);
150 2f0c9fe6 Paolo Bonzini
    data->ret = ret;
151 2f0c9fe6 Paolo Bonzini
    data->cb(data->opaque, ret);
152 2f0c9fe6 Paolo Bonzini
}
153 2f0c9fe6 Paolo Bonzini
154 2f0c9fe6 Paolo Bonzini
int block_job_cancel_sync(BlockJob *job)
155 2f0c9fe6 Paolo Bonzini
{
156 2f0c9fe6 Paolo Bonzini
    struct BlockCancelData data;
157 2f0c9fe6 Paolo Bonzini
    BlockDriverState *bs = job->bs;
158 2f0c9fe6 Paolo Bonzini
159 2f0c9fe6 Paolo Bonzini
    assert(bs->job == job);
160 2f0c9fe6 Paolo Bonzini
161 2f0c9fe6 Paolo Bonzini
    /* Set up our own callback to store the result and chain to
162 2f0c9fe6 Paolo Bonzini
     * the original callback.
163 2f0c9fe6 Paolo Bonzini
     */
164 2f0c9fe6 Paolo Bonzini
    data.job = job;
165 2f0c9fe6 Paolo Bonzini
    data.cb = job->cb;
166 2f0c9fe6 Paolo Bonzini
    data.opaque = job->opaque;
167 2f0c9fe6 Paolo Bonzini
    data.ret = -EINPROGRESS;
168 2f0c9fe6 Paolo Bonzini
    job->cb = block_job_cancel_cb;
169 2f0c9fe6 Paolo Bonzini
    job->opaque = &data;
170 2f0c9fe6 Paolo Bonzini
    block_job_cancel(job);
171 2f0c9fe6 Paolo Bonzini
    while (data.ret == -EINPROGRESS) {
172 2f0c9fe6 Paolo Bonzini
        qemu_aio_wait();
173 2f0c9fe6 Paolo Bonzini
    }
174 2f0c9fe6 Paolo Bonzini
    return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret;
175 2f0c9fe6 Paolo Bonzini
}
176 2f0c9fe6 Paolo Bonzini
177 2f0c9fe6 Paolo Bonzini
void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns)
178 2f0c9fe6 Paolo Bonzini
{
179 8acc72a4 Paolo Bonzini
    assert(job->busy);
180 8acc72a4 Paolo Bonzini
181 2f0c9fe6 Paolo Bonzini
    /* Check cancellation *before* setting busy = false, too!  */
182 8acc72a4 Paolo Bonzini
    if (block_job_is_cancelled(job)) {
183 8acc72a4 Paolo Bonzini
        return;
184 8acc72a4 Paolo Bonzini
    }
185 8acc72a4 Paolo Bonzini
186 8acc72a4 Paolo Bonzini
    job->busy = false;
187 8acc72a4 Paolo Bonzini
    if (block_job_is_paused(job)) {
188 8acc72a4 Paolo Bonzini
        qemu_coroutine_yield();
189 8acc72a4 Paolo Bonzini
    } else {
190 2f0c9fe6 Paolo Bonzini
        co_sleep_ns(clock, ns);
191 2f0c9fe6 Paolo Bonzini
    }
192 8acc72a4 Paolo Bonzini
    job->busy = true;
193 2f0c9fe6 Paolo Bonzini
}
194 30e628b7 Paolo Bonzini
195 30e628b7 Paolo Bonzini
BlockJobInfo *block_job_query(BlockJob *job)
196 30e628b7 Paolo Bonzini
{
197 30e628b7 Paolo Bonzini
    BlockJobInfo *info = g_new0(BlockJobInfo, 1);
198 32c81a4a Paolo Bonzini
    info->type      = g_strdup(job->job_type->job_type);
199 32c81a4a Paolo Bonzini
    info->device    = g_strdup(bdrv_get_device_name(job->bs));
200 32c81a4a Paolo Bonzini
    info->len       = job->len;
201 32c81a4a Paolo Bonzini
    info->busy      = job->busy;
202 32c81a4a Paolo Bonzini
    info->paused    = job->paused;
203 32c81a4a Paolo Bonzini
    info->offset    = job->offset;
204 32c81a4a Paolo Bonzini
    info->speed     = job->speed;
205 32c81a4a Paolo Bonzini
    info->io_status = job->iostatus;
206 30e628b7 Paolo Bonzini
    return info;
207 30e628b7 Paolo Bonzini
}
208 32c81a4a Paolo Bonzini
209 32c81a4a Paolo Bonzini
static void block_job_iostatus_set_err(BlockJob *job, int error)
210 32c81a4a Paolo Bonzini
{
211 32c81a4a Paolo Bonzini
    if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) {
212 32c81a4a Paolo Bonzini
        job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE :
213 32c81a4a Paolo Bonzini
                                          BLOCK_DEVICE_IO_STATUS_FAILED;
214 32c81a4a Paolo Bonzini
    }
215 32c81a4a Paolo Bonzini
}
216 32c81a4a Paolo Bonzini
217 32c81a4a Paolo Bonzini
218 32c81a4a Paolo Bonzini
BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs,
219 32c81a4a Paolo Bonzini
                                        BlockdevOnError on_err,
220 32c81a4a Paolo Bonzini
                                        int is_read, int error)
221 32c81a4a Paolo Bonzini
{
222 32c81a4a Paolo Bonzini
    BlockErrorAction action;
223 32c81a4a Paolo Bonzini
224 32c81a4a Paolo Bonzini
    switch (on_err) {
225 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_ENOSPC:
226 32c81a4a Paolo Bonzini
        action = (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT;
227 32c81a4a Paolo Bonzini
        break;
228 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_STOP:
229 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_STOP;
230 32c81a4a Paolo Bonzini
        break;
231 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_REPORT:
232 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_REPORT;
233 32c81a4a Paolo Bonzini
        break;
234 32c81a4a Paolo Bonzini
    case BLOCKDEV_ON_ERROR_IGNORE:
235 32c81a4a Paolo Bonzini
        action = BDRV_ACTION_IGNORE;
236 32c81a4a Paolo Bonzini
        break;
237 32c81a4a Paolo Bonzini
    default:
238 32c81a4a Paolo Bonzini
        abort();
239 32c81a4a Paolo Bonzini
    }
240 32c81a4a Paolo Bonzini
    bdrv_emit_qmp_error_event(job->bs, QEVENT_BLOCK_JOB_ERROR, action, is_read);
241 32c81a4a Paolo Bonzini
    if (action == BDRV_ACTION_STOP) {
242 32c81a4a Paolo Bonzini
        block_job_pause(job);
243 32c81a4a Paolo Bonzini
        block_job_iostatus_set_err(job, error);
244 32c81a4a Paolo Bonzini
        if (bs != job->bs) {
245 32c81a4a Paolo Bonzini
            bdrv_iostatus_set_err(bs, error);
246 32c81a4a Paolo Bonzini
        }
247 32c81a4a Paolo Bonzini
    }
248 32c81a4a Paolo Bonzini
    return action;
249 32c81a4a Paolo Bonzini
}