static int iscsi_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) { IscsiLun *iscsilun = bs->opaque; int status; switch (req) { case SG_GET_VERSION_NUM: *(int *)buf = 30000; break; case SG_GET_SCSI_ID: ((struct sg_scsi_id *)buf)->scsi_type = iscsilun->type; break; case SG_IO: status = -EINPROGRESS; iscsi_aio_ioctl(bs, req, buf, ioctl_cb, &status); while (status == -EINPROGRESS) { qemu_aio_wait(); } return 0; default: return -1; } return 0; }
static int do_co_write_zeroes(int64_t offset, int count, int *total) { Coroutine *co; CoWriteZeroes data = { .offset = offset, .count = count, .total = total, .done = false, }; co = qemu_coroutine_create(co_write_zeroes_entry); qemu_coroutine_enter(co, &data); while (!data.done) { qemu_aio_wait(); } if (data.ret < 0) { return data.ret; } else { return 1; } } static int do_write_compressed(char *buf, int64_t offset, int count, int *total) { int ret; ret = bdrv_write_compressed(bs, offset >> 9, (uint8_t *)buf, count >> 9); if (ret < 0) { return ret; } *total = count; return 1; }
static int do_co_write_zeroes(int64_t offset, int count, int *total) { Coroutine *co; CoWriteZeroes data = { .offset = offset, .count = count, .total = total, .done = false, }; co = qemu_coroutine_create(co_write_zeroes_entry); qemu_coroutine_enter(co, &data); while (!data.done) { qemu_aio_wait(); } if (data.ret < 0) { return data.ret; } else { return 1; } } static int do_load_vmstate(char *buf, int64_t offset, int count, int *total) { *total = bdrv_load_vmstate(bs, (uint8_t *)buf, offset, count); if (*total < 0) { return *total; } return 1; }
static int wait_break_f(int argc, char **argv) { while (!bdrv_debug_is_suspended(bs, argv[1])) { qemu_aio_wait(); } return 0; }
static void qemu_gluster_aio_cancel(BlockDriverAIOCB *blockacb) { GlusterAIOCB *acb = (GlusterAIOCB *)blockacb; bool finished = false; acb->finished = &finished; while (!finished) { qemu_aio_wait(); } }
int qed_read_l2_table_sync(BDRVQEDState *s, QEDRequest *request, uint64_t offset) { int ret = -EINPROGRESS; qed_read_l2_table(s, request, offset, qed_sync_cb, &ret); while (ret == -EINPROGRESS) { qemu_aio_wait(); } return ret; }
static void blkverify_aio_cancel(BlockDriverAIOCB *blockacb) { BlkverifyAIOCB *acb = (BlkverifyAIOCB *)blockacb; bool finished = false; /* Wait until request completes, invokes its callback, and frees itself */ acb->finished = &finished; while (!finished) { qemu_aio_wait(); } }
static void qed_aio_cancel(BlockDriverAIOCB *blockacb) { QEDAIOCB *acb = (QEDAIOCB *)blockacb; bool finished = false; /* Wait for the request to finish */ acb->finished = &finished; while (!finished) { qemu_aio_wait(); } }
/* * Cancel aio. Since we don't reference acb in a non qemu threads, * it is safe to access it here. */ static void qemu_rbd_aio_cancel(BlockDriverAIOCB *blockacb) { RBDAIOCB *acb = (RBDAIOCB *) blockacb; acb->cancelled = 1; while (acb->status == -EINPROGRESS) { qemu_aio_wait(); } qemu_aio_release(acb); }
int qed_read_l1_table_sync(BDRVQEDState *s) { int ret = -EINPROGRESS; qed_read_table(s, s->header.l1_table_offset, s->l1_table, qed_sync_cb, &ret); while (ret == -EINPROGRESS) { qemu_aio_wait(); } return ret; }
int qed_write_l2_table_sync(BDRVQEDState *s, QEDRequest *request, unsigned int index, unsigned int n, bool flush) { int ret = -EINPROGRESS; qed_write_l2_table(s, request, index, n, flush, qed_sync_cb, &ret); while (ret == -EINPROGRESS) { qemu_aio_wait(); } return ret; }
int qed_write_l1_table_sync(BDRVQEDState *s, unsigned int index, unsigned int n) { int ret = -EINPROGRESS; qed_write_l1_table(s, index, n, qed_sync_cb, &ret); while (ret == -EINPROGRESS) { qemu_aio_wait(); } return ret; }
static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) { int async_ret = NOT_DONE; bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, aio_rw_done, &async_ret); while (async_ret == NOT_DONE) { qemu_aio_wait(); } *total = qiov->size; return async_ret < 0 ? async_ret : 1; }
static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total) { int i, ret; struct multiwrite_async_ret async_ret = { .num_done = 0, .error = 0, }; *total = 0; for (i = 0; i < num_reqs; i++) { reqs[i].cb = multiwrite_cb; reqs[i].opaque = &async_ret; *total += reqs[i].qiov->size; } ret = bdrv_aio_multiwrite(bs, reqs, num_reqs); if (ret < 0) { return ret; } while (async_ret.num_done < num_reqs) { qemu_aio_wait(); } return async_ret.error < 0 ? async_ret.error : 1; } static void read_help(void) { printf( "\n" " reads a range of bytes from the given offset\n" "\n" " Example:\n" " 'read -v 512 1k' - dumps 1 kilobyte read from 512 bytes into the file\n" "\n" " Reads a segment of the currently open file, optionally dumping it to the\n" " standard output stream (with -v option) for subsequent inspection.\n" " -b, -- read from the VM state rather than the virtual disk\n" " -C, -- report statistics in a machine parsable format\n" " -l, -- length for pattern verification (only with -P)\n" " -p, -- use bdrv_pread to read the file\n" " -P, -- use a pattern to verify read data\n" " -q, -- quite mode, do not show I/O statistics\n" " -s, -- start offset for pattern verification (only with -P)\n" " -v, -- dump buffer to standard output\n" "\n"); }
static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total) { BlockDriverAIOCB *acb; int async_ret = NOT_DONE; acb = bdrv_aio_writev(bs, offset >> 9, qiov, qiov->size >> 9, aio_rw_done, &async_ret); if (!acb) return -EIO; while (async_ret == NOT_DONE) qemu_aio_wait(); *total = qiov->size; return async_ret < 0 ? async_ret : 1; }
static void iscsi_aio_cancel(BlockDriverAIOCB *blockacb) { IscsiAIOCB *acb = (IscsiAIOCB *)blockacb; IscsiLun *iscsilun = acb->iscsilun; if (acb->status != -EINPROGRESS) { return; } acb->canceled = 1; /* send a task mgmt call to the target to cancel the task on the target */ iscsi_task_mgmt_abort_task_async(iscsilun->iscsi, acb->task, iscsi_abort_task_cb, acb); while (acb->status == -EINPROGRESS) { qemu_aio_wait(); } }
int block_job_cancel_sync(BlockJob *job) { struct BlockCancelData data; BlockDriverState *bs = job->bs; assert(bs->job == job); /* Set up our own callback to store the result and chain to * the original callback. */ data.job = job; data.cb = job->cb; data.opaque = job->opaque; data.ret = -EINPROGRESS; job->cb = block_job_cancel_cb; job->opaque = &data; block_job_cancel(job); while (data.ret == -EINPROGRESS) { qemu_aio_wait(); } return (data.cancelled && data.ret == 0) ? -ECANCELED : data.ret; }
/* A non-blocking poll of the main AIO context (we cannot use aio_poll * because we do not know the AioContext). */ static void qemu_aio_wait_nonblocking(void) { qemu_notify_event(); qemu_aio_wait(); }
/* Wait until all aio and bh activity has finished */ static void qemu_aio_wait_all(void) { while (qemu_aio_wait()) { /* Do nothing */ } }
/* * We support iscsi url's on the form * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun> */ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = NULL; struct iscsi_url *iscsi_url = NULL; struct IscsiTask task; char *initiator_name = NULL; int ret; if ((BDRV_SECTOR_SIZE % 512) != 0) { error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. " "BDRV_SECTOR_SIZE(%lld) is not a multiple " "of 512", BDRV_SECTOR_SIZE); return -EINVAL; } iscsi_url = iscsi_parse_full_url(iscsi, filename); if (iscsi_url == NULL) { error_report("Failed to parse URL : %s %s", filename, iscsi_get_error(iscsi)); ret = -EINVAL; goto failed; } memset(iscsilun, 0, sizeof(IscsiLun)); initiator_name = parse_initiator_name(iscsi_url->target); iscsi = iscsi_create_context(initiator_name); if (iscsi == NULL) { error_report("iSCSI: Failed to create iSCSI context."); ret = -ENOMEM; goto failed; } if (iscsi_set_targetname(iscsi, iscsi_url->target)) { error_report("iSCSI: Failed to set target name."); ret = -EINVAL; goto failed; } if (iscsi_url->user != NULL) { ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd); if (ret != 0) { error_report("Failed to set initiator username and password"); ret = -EINVAL; goto failed; } } /* check if we got CHAP username/password via the options */ if (parse_chap(iscsi, iscsi_url->target) != 0) { error_report("iSCSI: Failed to set CHAP user/password"); ret = -EINVAL; goto failed; } if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) { error_report("iSCSI: Failed to set session type to normal."); ret = -EINVAL; goto failed; } iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C); /* check if we got HEADER_DIGEST via the options */ parse_header_digest(iscsi, iscsi_url->target); task.iscsilun = iscsilun; task.status = 0; task.complete = 0; task.bs = bs; iscsilun->iscsi = iscsi; iscsilun->lun = iscsi_url->lun; if (iscsi_full_connect_async(iscsi, iscsi_url->portal, iscsi_url->lun, iscsi_connect_cb, &task) != 0) { error_report("iSCSI: Failed to start async connect."); ret = -EINVAL; goto failed; } while (!task.complete) { iscsi_set_events(iscsilun); qemu_aio_wait(); } if (task.status != 0) { error_report("iSCSI: Failed to connect to LUN : %s", iscsi_get_error(iscsi)); ret = -EINVAL; goto failed; } if (iscsi_url != NULL) { iscsi_destroy_url(iscsi_url); } return 0; failed: if (initiator_name != NULL) { g_free(initiator_name); } if (iscsi_url != NULL) { iscsi_destroy_url(iscsi_url); } if (iscsi != NULL) { iscsi_destroy_context(iscsi); } memset(iscsilun, 0, sizeof(IscsiLun)); return ret; }
void command_loop(void) { int c, i, j = 0, done = 0, fetchable = 0, prompted = 0; char *input; char **v; const cmdinfo_t *ct; for (i = 0; !done && i < ncmdline; i++) { input = strdup(cmdline[i]); if (!input) { fprintf(stderr, _("cannot strdup command '%s': %s\n"), cmdline[i], strerror(errno)); exit(1); } v = breakline(input, &c); if (c) { ct = find_command(v[0]); if (ct) { if (ct->flags & CMD_FLAG_GLOBAL) { done = command(ct, c, v); } else { j = 0; while (!done && (j = args_command(j))) { done = command(ct, c, v); } } } else { fprintf(stderr, _("command \"%s\" not found\n"), v[0]); } } doneline(input, v); } if (cmdline) { g_free(cmdline); return; } while (!done) { if (!prompted) { printf("%s", get_prompt()); fflush(stdout); qemu_aio_set_fd_handler(STDIN_FILENO, prep_fetchline, NULL, NULL, NULL, &fetchable); prompted = 1; } qemu_aio_wait(); if (!fetchable) { continue; } input = fetchline(); if (input == NULL) { break; } v = breakline(input, &c); if (c) { ct = find_command(v[0]); if (ct) { done = command(ct, c, v); } else { fprintf(stderr, _("command \"%s\" not found\n"), v[0]); } } doneline(input, v); prompted = 0; fetchable = 0; } qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL); }