1 /* 2 * QEMU System Emulator block driver 3 * 4 * Copyright (c) 2011 IBM Corp. 5 * Copyright (c) 2012 Red Hat, Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include "config-host.h" 27 #include "qemu-common.h" 28 #include "trace.h" 29 #include "block/block.h" 30 #include "block/blockjob.h" 31 #include "block/block_int.h" 32 #include "qapi/qmp/qerror.h" 33 #include "qapi/qmp/qjson.h" 34 #include "qemu/coroutine.h" 35 #include "qmp-commands.h" 36 #include "qemu/timer.h" 37 #include "qapi-event.h" 38 39 void *block_job_create(const BlockJobDriver *driver, BlockDriverState *bs, 40 int64_t speed, BlockCompletionFunc *cb, 41 void *opaque, Error **errp) 42 { 43 BlockJob *job; 44 45 if (bs->job) { 46 error_setg(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs)); 47 return NULL; 48 } 49 bdrv_ref(bs); 50 job = g_malloc0(driver->instance_size); 51 error_setg(&job->blocker, "block device is in use by block job: %s", 52 BlockJobType_lookup[driver->job_type]); 53 bdrv_op_block_all(bs, job->blocker); 54 bdrv_op_unblock(bs, BLOCK_OP_TYPE_DATAPLANE, job->blocker); 55 56 job->driver = driver; 57 job->id = g_strdup(bdrv_get_device_name(bs)); 58 job->bs = bs; 59 job->cb = cb; 60 job->opaque = opaque; 61 job->busy = true; 62 bs->job = job; 63 64 /* Only set speed when necessary to avoid NotSupported error */ 65 if (speed != 0) { 66 Error *local_err = NULL; 67 68 block_job_set_speed(job, speed, &local_err); 69 if (local_err) { 70 block_job_release(bs); 71 error_propagate(errp, local_err); 72 return NULL; 73 } 74 } 75 return job; 76 } 77 78 void block_job_release(BlockDriverState *bs) 79 { 80 BlockJob *job = bs->job; 81 82 bs->job = NULL; 83 bdrv_op_unblock_all(bs, job->blocker); 84 error_free(job->blocker); 85 g_free(job->id); 86 g_free(job); 87 } 88 89 void block_job_completed(BlockJob *job, int ret) 90 { 91 BlockDriverState *bs = job->bs; 92 93 assert(bs->job == job); 94 job->cb(job->opaque, ret); 95 block_job_release(bs); 96 } 97 98 void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) 99 { 100 Error *local_err = NULL; 101 102 if (!job->driver->set_speed) { 103 error_setg(errp, QERR_UNSUPPORTED); 104 return; 105 } 106 job->driver->set_speed(job, speed, &local_err); 107 if (local_err) { 108 error_propagate(errp, local_err); 109 return; 110 } 111 112 job->speed = speed; 113 } 114 115 void block_job_complete(BlockJob *job, Error **errp) 116 { 117 if (job->pause_count || job->cancelled || !job->driver->complete) { 118 error_setg(errp, QERR_BLOCK_JOB_NOT_READY, job->id); 119 return; 120 } 121 122 job->driver->complete(job, errp); 123 } 124 125 void block_job_pause(BlockJob *job) 126 { 127 job->pause_count++; 128 } 129 130 bool block_job_is_paused(BlockJob *job) 131 { 132 return job->pause_count > 0; 133 } 134 135 void block_job_resume(BlockJob *job) 136 { 137 assert(job->pause_count > 0); 138 job->pause_count--; 139 if (job->pause_count) { 140 return; 141 } 142 block_job_enter(job); 143 } 144 145 void block_job_enter(BlockJob *job) 146 { 147 block_job_iostatus_reset(job); 148 if (job->co && !job->busy) { 149 qemu_coroutine_enter(job->co, NULL); 150 } 151 } 152 153 void block_job_cancel(BlockJob *job) 154 { 155 job->cancelled = true; 156 block_job_enter(job); 157 } 158 159 bool block_job_is_cancelled(BlockJob *job) 160 { 161 return job->cancelled; 162 } 163 164 void block_job_iostatus_reset(BlockJob *job) 165 { 166 job->iostatus = BLOCK_DEVICE_IO_STATUS_OK; 167 if (job->driver->iostatus_reset) { 168 job->driver->iostatus_reset(job); 169 } 170 } 171 172 struct BlockFinishData { 173 BlockJob *job; 174 BlockCompletionFunc *cb; 175 void *opaque; 176 bool cancelled; 177 int ret; 178 }; 179 180 static void block_job_finish_cb(void *opaque, int ret) 181 { 182 struct BlockFinishData *data = opaque; 183 184 data->cancelled = block_job_is_cancelled(data->job); 185 data->ret = ret; 186 data->cb(data->opaque, ret); 187 } 188 189 static int block_job_finish_sync(BlockJob *job, 190 void (*finish)(BlockJob *, Error **errp), 191 Error **errp) 192 { 193 struct BlockFinishData data; 194 BlockDriverState *bs = job->bs; 195 Error *local_err = NULL; 196 197 assert(bs->job == job); 198 199 /* Set up our own callback to store the result and chain to 200 * the original callback. 201 */ 202 data.job = job; 203 data.cb = job->cb; 204 data.opaque = job->opaque; 205 data.ret = -EINPROGRESS; 206 job->cb = block_job_finish_cb; 207 job->opaque = &data; 208 finish(job, &local_err); 209 if (local_err) { 210 error_propagate(errp, local_err); 211 return -EBUSY; 212 } 213 while (data.ret == -EINPROGRESS) { 214 aio_poll(bdrv_get_aio_context(bs), true); 215 } 216 return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret; 217 } 218 219 /* A wrapper around block_job_cancel() taking an Error ** parameter so it may be 220 * used with block_job_finish_sync() without the need for (rather nasty) 221 * function pointer casts there. */ 222 static void block_job_cancel_err(BlockJob *job, Error **errp) 223 { 224 block_job_cancel(job); 225 } 226 227 int block_job_cancel_sync(BlockJob *job) 228 { 229 return block_job_finish_sync(job, &block_job_cancel_err, NULL); 230 } 231 232 int block_job_complete_sync(BlockJob *job, Error **errp) 233 { 234 return block_job_finish_sync(job, &block_job_complete, errp); 235 } 236 237 void block_job_sleep_ns(BlockJob *job, QEMUClockType type, int64_t ns) 238 { 239 assert(job->busy); 240 241 /* Check cancellation *before* setting busy = false, too! */ 242 if (block_job_is_cancelled(job)) { 243 return; 244 } 245 246 job->busy = false; 247 if (block_job_is_paused(job)) { 248 qemu_coroutine_yield(); 249 } else { 250 co_aio_sleep_ns(bdrv_get_aio_context(job->bs), type, ns); 251 } 252 job->busy = true; 253 } 254 255 void block_job_yield(BlockJob *job) 256 { 257 assert(job->busy); 258 259 /* Check cancellation *before* setting busy = false, too! */ 260 if (block_job_is_cancelled(job)) { 261 return; 262 } 263 264 job->busy = false; 265 qemu_coroutine_yield(); 266 job->busy = true; 267 } 268 269 BlockJobInfo *block_job_query(BlockJob *job) 270 { 271 BlockJobInfo *info = g_new0(BlockJobInfo, 1); 272 info->type = g_strdup(BlockJobType_lookup[job->driver->job_type]); 273 info->device = g_strdup(job->id); 274 info->len = job->len; 275 info->busy = job->busy; 276 info->paused = job->pause_count > 0; 277 info->offset = job->offset; 278 info->speed = job->speed; 279 info->io_status = job->iostatus; 280 info->ready = job->ready; 281 return info; 282 } 283 284 static void block_job_iostatus_set_err(BlockJob *job, int error) 285 { 286 if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { 287 job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE : 288 BLOCK_DEVICE_IO_STATUS_FAILED; 289 } 290 } 291 292 void block_job_event_cancelled(BlockJob *job) 293 { 294 qapi_event_send_block_job_cancelled(job->driver->job_type, 295 job->id, 296 job->len, 297 job->offset, 298 job->speed, 299 &error_abort); 300 } 301 302 void block_job_event_completed(BlockJob *job, const char *msg) 303 { 304 qapi_event_send_block_job_completed(job->driver->job_type, 305 job->id, 306 job->len, 307 job->offset, 308 job->speed, 309 !!msg, 310 msg, 311 &error_abort); 312 } 313 314 void block_job_event_ready(BlockJob *job) 315 { 316 job->ready = true; 317 318 qapi_event_send_block_job_ready(job->driver->job_type, 319 job->id, 320 job->len, 321 job->offset, 322 job->speed, &error_abort); 323 } 324 325 BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, 326 BlockdevOnError on_err, 327 int is_read, int error) 328 { 329 BlockErrorAction action; 330 331 switch (on_err) { 332 case BLOCKDEV_ON_ERROR_ENOSPC: 333 action = (error == ENOSPC) ? 334 BLOCK_ERROR_ACTION_STOP : BLOCK_ERROR_ACTION_REPORT; 335 break; 336 case BLOCKDEV_ON_ERROR_STOP: 337 action = BLOCK_ERROR_ACTION_STOP; 338 break; 339 case BLOCKDEV_ON_ERROR_REPORT: 340 action = BLOCK_ERROR_ACTION_REPORT; 341 break; 342 case BLOCKDEV_ON_ERROR_IGNORE: 343 action = BLOCK_ERROR_ACTION_IGNORE; 344 break; 345 default: 346 abort(); 347 } 348 qapi_event_send_block_job_error(job->id, 349 is_read ? IO_OPERATION_TYPE_READ : 350 IO_OPERATION_TYPE_WRITE, 351 action, &error_abort); 352 if (action == BLOCK_ERROR_ACTION_STOP) { 353 /* make the pause user visible, which will be resumed from QMP. */ 354 job->user_paused = true; 355 block_job_pause(job); 356 block_job_iostatus_set_err(job, error); 357 if (bs != job->bs) { 358 bdrv_iostatus_set_err(bs, error); 359 } 360 } 361 return action; 362 } 363 364 typedef struct { 365 BlockJob *job; 366 QEMUBH *bh; 367 AioContext *aio_context; 368 BlockJobDeferToMainLoopFn *fn; 369 void *opaque; 370 } BlockJobDeferToMainLoopData; 371 372 static void block_job_defer_to_main_loop_bh(void *opaque) 373 { 374 BlockJobDeferToMainLoopData *data = opaque; 375 AioContext *aio_context; 376 377 qemu_bh_delete(data->bh); 378 379 /* Prevent race with block_job_defer_to_main_loop() */ 380 aio_context_acquire(data->aio_context); 381 382 /* Fetch BDS AioContext again, in case it has changed */ 383 aio_context = bdrv_get_aio_context(data->job->bs); 384 aio_context_acquire(aio_context); 385 386 data->fn(data->job, data->opaque); 387 388 aio_context_release(aio_context); 389 390 aio_context_release(data->aio_context); 391 392 g_free(data); 393 } 394 395 void block_job_defer_to_main_loop(BlockJob *job, 396 BlockJobDeferToMainLoopFn *fn, 397 void *opaque) 398 { 399 BlockJobDeferToMainLoopData *data = g_malloc(sizeof(*data)); 400 data->job = job; 401 data->bh = qemu_bh_new(block_job_defer_to_main_loop_bh, data); 402 data->aio_context = bdrv_get_aio_context(job->bs); 403 data->fn = fn; 404 data->opaque = opaque; 405 406 qemu_bh_schedule(data->bh); 407 } 408