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 "monitor.h" 30 #include "block.h" 31 #include "blockjob.h" 32 #include "block_int.h" 33 #include "qjson.h" 34 #include "qemu-coroutine.h" 35 #include "qmp-commands.h" 36 #include "qemu-timer.h" 37 38 void *block_job_create(const BlockJobType *job_type, BlockDriverState *bs, 39 int64_t speed, BlockDriverCompletionFunc *cb, 40 void *opaque, Error **errp) 41 { 42 BlockJob *job; 43 44 if (bs->job || bdrv_in_use(bs)) { 45 error_set(errp, QERR_DEVICE_IN_USE, bdrv_get_device_name(bs)); 46 return NULL; 47 } 48 bdrv_set_in_use(bs, 1); 49 50 job = g_malloc0(job_type->instance_size); 51 job->job_type = job_type; 52 job->bs = bs; 53 job->cb = cb; 54 job->opaque = opaque; 55 job->busy = true; 56 bs->job = job; 57 58 /* Only set speed when necessary to avoid NotSupported error */ 59 if (speed != 0) { 60 Error *local_err = NULL; 61 62 block_job_set_speed(job, speed, &local_err); 63 if (error_is_set(&local_err)) { 64 bs->job = NULL; 65 g_free(job); 66 bdrv_set_in_use(bs, 0); 67 error_propagate(errp, local_err); 68 return NULL; 69 } 70 } 71 return job; 72 } 73 74 void block_job_complete(BlockJob *job, int ret) 75 { 76 BlockDriverState *bs = job->bs; 77 78 assert(bs->job == job); 79 job->cb(job->opaque, ret); 80 bs->job = NULL; 81 g_free(job); 82 bdrv_set_in_use(bs, 0); 83 } 84 85 void block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) 86 { 87 Error *local_err = NULL; 88 89 if (!job->job_type->set_speed) { 90 error_set(errp, QERR_NOT_SUPPORTED); 91 return; 92 } 93 job->job_type->set_speed(job, speed, &local_err); 94 if (error_is_set(&local_err)) { 95 error_propagate(errp, local_err); 96 return; 97 } 98 99 job->speed = speed; 100 } 101 102 void block_job_pause(BlockJob *job) 103 { 104 job->paused = true; 105 } 106 107 bool block_job_is_paused(BlockJob *job) 108 { 109 return job->paused; 110 } 111 112 void block_job_resume(BlockJob *job) 113 { 114 job->paused = false; 115 block_job_iostatus_reset(job); 116 if (job->co && !job->busy) { 117 qemu_coroutine_enter(job->co, NULL); 118 } 119 } 120 121 void block_job_cancel(BlockJob *job) 122 { 123 job->cancelled = true; 124 block_job_resume(job); 125 } 126 127 bool block_job_is_cancelled(BlockJob *job) 128 { 129 return job->cancelled; 130 } 131 132 void block_job_iostatus_reset(BlockJob *job) 133 { 134 job->iostatus = BLOCK_DEVICE_IO_STATUS_OK; 135 } 136 137 struct BlockCancelData { 138 BlockJob *job; 139 BlockDriverCompletionFunc *cb; 140 void *opaque; 141 bool cancelled; 142 int ret; 143 }; 144 145 static void block_job_cancel_cb(void *opaque, int ret) 146 { 147 struct BlockCancelData *data = opaque; 148 149 data->cancelled = block_job_is_cancelled(data->job); 150 data->ret = ret; 151 data->cb(data->opaque, ret); 152 } 153 154 int block_job_cancel_sync(BlockJob *job) 155 { 156 struct BlockCancelData data; 157 BlockDriverState *bs = job->bs; 158 159 assert(bs->job == job); 160 161 /* Set up our own callback to store the result and chain to 162 * the original callback. 163 */ 164 data.job = job; 165 data.cb = job->cb; 166 data.opaque = job->opaque; 167 data.ret = -EINPROGRESS; 168 job->cb = block_job_cancel_cb; 169 job->opaque = &data; 170 block_job_cancel(job); 171 while (data.ret == -EINPROGRESS) { 172 qemu_aio_wait(); 173 } 174 return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret; 175 } 176 177 void block_job_sleep_ns(BlockJob *job, QEMUClock *clock, int64_t ns) 178 { 179 assert(job->busy); 180 181 /* Check cancellation *before* setting busy = false, too! */ 182 if (block_job_is_cancelled(job)) { 183 return; 184 } 185 186 job->busy = false; 187 if (block_job_is_paused(job)) { 188 qemu_coroutine_yield(); 189 } else { 190 co_sleep_ns(clock, ns); 191 } 192 job->busy = true; 193 } 194 195 BlockJobInfo *block_job_query(BlockJob *job) 196 { 197 BlockJobInfo *info = g_new0(BlockJobInfo, 1); 198 info->type = g_strdup(job->job_type->job_type); 199 info->device = g_strdup(bdrv_get_device_name(job->bs)); 200 info->len = job->len; 201 info->busy = job->busy; 202 info->paused = job->paused; 203 info->offset = job->offset; 204 info->speed = job->speed; 205 info->io_status = job->iostatus; 206 return info; 207 } 208 209 static void block_job_iostatus_set_err(BlockJob *job, int error) 210 { 211 if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { 212 job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE : 213 BLOCK_DEVICE_IO_STATUS_FAILED; 214 } 215 } 216 217 218 BlockErrorAction block_job_error_action(BlockJob *job, BlockDriverState *bs, 219 BlockdevOnError on_err, 220 int is_read, int error) 221 { 222 BlockErrorAction action; 223 224 switch (on_err) { 225 case BLOCKDEV_ON_ERROR_ENOSPC: 226 action = (error == ENOSPC) ? BDRV_ACTION_STOP : BDRV_ACTION_REPORT; 227 break; 228 case BLOCKDEV_ON_ERROR_STOP: 229 action = BDRV_ACTION_STOP; 230 break; 231 case BLOCKDEV_ON_ERROR_REPORT: 232 action = BDRV_ACTION_REPORT; 233 break; 234 case BLOCKDEV_ON_ERROR_IGNORE: 235 action = BDRV_ACTION_IGNORE; 236 break; 237 default: 238 abort(); 239 } 240 bdrv_emit_qmp_error_event(job->bs, QEVENT_BLOCK_JOB_ERROR, action, is_read); 241 if (action == BDRV_ACTION_STOP) { 242 block_job_pause(job); 243 block_job_iostatus_set_err(job, error); 244 if (bs != job->bs) { 245 bdrv_iostatus_set_err(bs, error); 246 } 247 } 248 return action; 249 } 250