static void mirror_iteration_done(MirrorOp *op, int ret) { MirrorBlockJob *s = op->s; struct iovec *iov; int64_t chunk_num; int i, nb_chunks, sectors_per_chunk; trace_mirror_iteration_done(s, op->sector_num, op->nb_sectors, ret); s->in_flight--; iov = op->qiov.iov; for (i = 0; i < op->qiov.niov; i++) { MirrorBuffer *buf = (MirrorBuffer *) iov[i].iov_base; QSIMPLEQ_INSERT_TAIL(&s->buf_free, buf, next); s->buf_free_count++; } sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS; chunk_num = op->sector_num / sectors_per_chunk; nb_chunks = op->nb_sectors / sectors_per_chunk; bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks); if (s->cow_bitmap && ret >= 0) { bitmap_set(s->cow_bitmap, chunk_num, nb_chunks); } g_slice_free(MirrorOp, op); qemu_coroutine_enter(s->common.co, NULL); }
void coroutine_fn qemu_co_queue_wait(CoQueue *queue) { Coroutine *self = qemu_coroutine_self(); QSIMPLEQ_INSERT_TAIL(&queue->entries, self, co_queue_next); qemu_coroutine_yield(); assert(qemu_in_coroutine()); }
void enqueue_async_event(NVMEState *n, uint8_t event_type, uint8_t event_info, uint8_t log_page) { AsyncEvent *event = (AsyncEvent *)qemu_malloc(sizeof(AsyncEvent)); event->result.event_type = event_type; event->result.event_info = event_info; event->result.log_page = log_page; QSIMPLEQ_INSERT_TAIL(&(n->async_queue), event, entry); qemu_mod_timer(n->async_event_timer, qemu_get_clock_ns(vm_clock) + 20000); }
static void mirror_free_init(MirrorBlockJob *s) { int granularity = s->granularity; size_t buf_size = s->buf_size; uint8_t *buf = s->buf; assert(s->buf_free_count == 0); QSIMPLEQ_INIT(&s->buf_free); while (buf_size != 0) { MirrorBuffer *cur = (MirrorBuffer *)buf; QSIMPLEQ_INSERT_TAIL(&s->buf_free, cur, next); s->buf_free_count++; buf_size -= granularity; buf += granularity; } }
static bool qemu_co_queue_do_restart(CoQueue *queue, bool single) { Coroutine *self = qemu_coroutine_self(); Coroutine *next; if (QSIMPLEQ_EMPTY(&queue->entries)) { return false; } while ((next = QSIMPLEQ_FIRST(&queue->entries)) != NULL) { QSIMPLEQ_REMOVE_HEAD(&queue->entries, co_queue_next); QSIMPLEQ_INSERT_TAIL(&self->co_queue_wakeup, next, co_queue_next); trace_qemu_co_queue_next(next); if (single) { break; } } return true; }
static void mirror_iteration_done(MirrorOp *op, int ret) { MirrorBlockJob *s = op->s; struct iovec *iov; int64_t chunk_num; int i, nb_chunks, sectors_per_chunk; trace_mirror_iteration_done(s, op->sector_num, op->nb_sectors, ret); s->in_flight--; s->sectors_in_flight -= op->nb_sectors; iov = op->qiov.iov; for (i = 0; i < op->qiov.niov; i++) { MirrorBuffer *buf = (MirrorBuffer *) iov[i].iov_base; QSIMPLEQ_INSERT_TAIL(&s->buf_free, buf, next); s->buf_free_count++; } sectors_per_chunk = s->granularity >> BDRV_SECTOR_BITS; chunk_num = op->sector_num / sectors_per_chunk; nb_chunks = op->nb_sectors / sectors_per_chunk; bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks); if (ret >= 0) { if (s->cow_bitmap) { bitmap_set(s->cow_bitmap, chunk_num, nb_chunks); } s->common.offset += (uint64_t)op->nb_sectors * BDRV_SECTOR_SIZE; } qemu_iovec_destroy(&op->qiov); g_slice_free(MirrorOp, op); /* Enter coroutine when it is not sleeping. The coroutine sleeps to * rate-limit itself. The coroutine will eventually resume since there is * a sleep timeout so don't wake it early. */ if (s->common.busy) { qemu_coroutine_enter(s->common.co, NULL); } }
static void mirror_iteration_done(MirrorOp *op, int ret) { MirrorBlockJob *s = op->s; struct iovec *iov; int64_t chunk_num; int i, nb_chunks; trace_mirror_iteration_done(s, op->offset, op->bytes, ret); s->in_flight--; s->bytes_in_flight -= op->bytes; iov = op->qiov.iov; for (i = 0; i < op->qiov.niov; i++) { MirrorBuffer *buf = (MirrorBuffer *) iov[i].iov_base; QSIMPLEQ_INSERT_TAIL(&s->buf_free, buf, next); s->buf_free_count++; } chunk_num = op->offset / s->granularity; nb_chunks = DIV_ROUND_UP(op->bytes, s->granularity); bitmap_clear(s->in_flight_bitmap, chunk_num, nb_chunks); if (ret >= 0) { if (s->cow_bitmap) { bitmap_set(s->cow_bitmap, chunk_num, nb_chunks); } if (!s->initial_zeroing_ongoing) { block_job_progress_update(&s->common, op->bytes); } } qemu_iovec_destroy(&op->qiov); g_free(op); if (s->waiting_for_io) { qemu_coroutine_enter(s->common.co); } }
/* bitmap_list_load * Get bitmap list from qcow2 image. Actually reads bitmap directory, * checks it and convert to bitmap list. */ static Qcow2BitmapList *bitmap_list_load(BlockDriverState *bs, uint64_t offset, uint64_t size, Error **errp) { int ret; BDRVQcow2State *s = bs->opaque; uint8_t *dir, *dir_end; Qcow2BitmapDirEntry *e; uint32_t nb_dir_entries = 0; Qcow2BitmapList *bm_list = NULL; if (size == 0) { error_setg(errp, "Requested bitmap directory size is zero"); return NULL; } if (size > QCOW2_MAX_BITMAP_DIRECTORY_SIZE) { error_setg(errp, "Requested bitmap directory size is too big"); return NULL; } dir = g_try_malloc(size); if (dir == NULL) { error_setg(errp, "Failed to allocate space for bitmap directory"); return NULL; } dir_end = dir + size; ret = bdrv_pread(bs->file, offset, dir, size); if (ret < 0) { error_setg_errno(errp, -ret, "Failed to read bitmap directory"); goto fail; } bm_list = bitmap_list_new(); for (e = (Qcow2BitmapDirEntry *)dir; e < (Qcow2BitmapDirEntry *)dir_end; e = next_dir_entry(e)) { Qcow2Bitmap *bm; if ((uint8_t *)(e + 1) > dir_end) { goto broken_dir; } if (++nb_dir_entries > s->nb_bitmaps) { error_setg(errp, "More bitmaps found than specified in header" " extension"); goto fail; } bitmap_dir_entry_to_cpu(e); if ((uint8_t *)next_dir_entry(e) > dir_end) { goto broken_dir; } if (e->extra_data_size != 0) { error_setg(errp, "Bitmap extra data is not supported"); goto fail; } ret = check_dir_entry(bs, e); if (ret < 0) { error_setg(errp, "Bitmap '%.*s' doesn't satisfy the constraints", e->name_size, dir_entry_name_field(e)); goto fail; } bm = g_new0(Qcow2Bitmap, 1); bm->table.offset = e->bitmap_table_offset; bm->table.size = e->bitmap_table_size; bm->flags = e->flags; bm->granularity_bits = e->granularity_bits; bm->name = dir_entry_copy_name(e); QSIMPLEQ_INSERT_TAIL(bm_list, bm, entry); } if (nb_dir_entries != s->nb_bitmaps) { error_setg(errp, "Less bitmaps found than specified in header" " extension"); goto fail; } if ((uint8_t *)e != dir_end) { goto broken_dir; } g_free(dir); return bm_list; broken_dir: ret = -EINVAL; error_setg(errp, "Broken bitmap directory"); fail: g_free(dir); bitmap_list_free(bm_list); return NULL; }