static int nbd_co_send_request(NbdClientSession *s, struct nbd_request *request, QEMUIOVector *qiov, int offset) { int rc, ret; qemu_co_mutex_lock(&s->send_mutex); s->send_coroutine = qemu_coroutine_self(); qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, s); if (qiov) { if (!s->is_unix) { socket_set_cork(s->sock, 1); } rc = nbd_send_request(s->sock, request); if (rc >= 0) { ret = qemu_co_sendv(s->sock, qiov->iov, qiov->niov, offset, request->len); if (ret != request->len) { rc = -EIO; } } if (!s->is_unix) { socket_set_cork(s->sock, 0); } } else { rc = nbd_send_request(s->sock, request); } qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, s); s->send_coroutine = NULL; qemu_co_mutex_unlock(&s->send_mutex); return rc; }
static void nbd_teardown_connection(NbdClientSession *client) { struct nbd_request request = { .type = NBD_CMD_DISC, .from = 0, .len = 0 }; nbd_send_request(client->sock, &request); /* finish any pending coroutines */ shutdown(client->sock, 2); nbd_recv_coroutines_enter_all(client); qemu_aio_set_fd_handler(client->sock, NULL, NULL, NULL); closesocket(client->sock); client->sock = -1; } void nbd_client_session_close(NbdClientSession *client) { if (!client->bs) { return; } nbd_teardown_connection(client); client->bs = NULL; } int nbd_client_session_init(NbdClientSession *client, BlockDriverState *bs, int sock, const char *export) { int ret; /* NBD handshake */ logout("session init %s\n", export); qemu_set_block(sock); ret = nbd_receive_negotiate(sock, export, &client->nbdflags, &client->size, &client->blocksize); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); closesocket(sock); return ret; } qemu_co_mutex_init(&client->send_mutex); qemu_co_mutex_init(&client->free_sema); client->bs = bs; client->sock = sock; /* Now that we're connected, set the socket to be non-blocking and * kick the reply mechanism. */ qemu_set_nonblock(sock); qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, client); logout("Established connection with NBD server\n"); return 0; }
static void prep_fetchline(void *opaque) { int *fetchable = opaque; qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL); *fetchable= 1; }
static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) { GlusterAIOCB *acb = (GlusterAIOCB *)arg; BlockDriverState *bs = acb->common.bs; BDRVGlusterState *s = bs->opaque; int retval; acb->ret = ret; retval = qemu_write_full(s->fds[GLUSTER_FD_WRITE], &acb, sizeof(acb)); if (retval != sizeof(acb)) { /* * Gluster AIO callback thread failed to notify the waiting * QEMU thread about IO completion. * * Complete this IO request and make the disk inaccessible for * subsequent reads and writes. */ error_report("Gluster failed to notify QEMU about IO completion"); qemu_mutex_lock_iothread(); /* We are in gluster thread context */ acb->common.cb(acb->common.opaque, -EIO); qemu_aio_release(acb); s->qemu_aio_count--; close(s->fds[GLUSTER_FD_READ]); close(s->fds[GLUSTER_FD_WRITE]); qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL, NULL); bs->drv = NULL; /* Make the disk inaccessible */ qemu_mutex_unlock_iothread(); } }
static void iscsi_close(BlockDriverState *bs) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), NULL, NULL, NULL, NULL); iscsi_destroy_context(iscsi); memset(iscsilun, 0, sizeof(IscsiLun)); }
static void iscsi_set_events(IscsiLun *iscsilun) { struct iscsi_context *iscsi = iscsilun->iscsi; qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), iscsi_process_read, (iscsi_which_events(iscsi) & POLLOUT) ? iscsi_process_write : NULL, iscsi_process_flush, iscsilun); }
static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, void *s, void *sp) { DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, fd); switch (action) { case CURL_POLL_IN: qemu_aio_set_fd_handler(fd, curl_multi_do, NULL, s); break; case CURL_POLL_OUT: qemu_aio_set_fd_handler(fd, NULL, curl_multi_do, s); break; case CURL_POLL_INOUT: qemu_aio_set_fd_handler(fd, curl_multi_do, curl_multi_do, s); break; case CURL_POLL_REMOVE: qemu_aio_set_fd_handler(fd, NULL, NULL, NULL); break; } return 0; }
static int qemu_gluster_open(BlockDriverState *bs, const char *filename, QDict *options, int bdrv_flags) { BDRVGlusterState *s = bs->opaque; int open_flags = O_BINARY; int ret = 0; GlusterConf *gconf = g_malloc0(sizeof(GlusterConf)); s->glfs = qemu_gluster_init(gconf, filename); if (!s->glfs) { ret = -errno; goto out; } if (bdrv_flags & BDRV_O_RDWR) { open_flags |= O_RDWR; } else { open_flags |= O_RDONLY; } if ((bdrv_flags & BDRV_O_NOCACHE)) { open_flags |= O_DIRECT; } s->fd = glfs_open(s->glfs, gconf->image, open_flags); if (!s->fd) { ret = -errno; goto out; } ret = qemu_pipe(s->fds); if (ret < 0) { ret = -errno; goto out; } fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], qemu_gluster_aio_event_reader, NULL, qemu_gluster_aio_flush_cb, s); out: qemu_gluster_gconf_free(gconf); if (!ret) { return ret; } if (s->fd) { glfs_close(s->fd); } if (s->glfs) { glfs_fini(s->glfs); } return ret; }
static void nbd_teardown_connection(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; struct nbd_request request; request.type = NBD_CMD_DISC; request.from = 0; request.len = 0; nbd_send_request(s->sock, &request); qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL, NULL); closesocket(s->sock); }
static int nbd_co_send_request(BDRVNBDState *s, struct nbd_request *request, struct iovec *iov, int offset) { int rc, ret; qemu_co_mutex_lock(&s->send_mutex); s->send_coroutine = qemu_coroutine_self(); qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, nbd_restart_write, nbd_have_request, s); rc = nbd_send_request(s->sock, request); if (rc >= 0 && iov) { ret = qemu_co_sendv(s->sock, iov, request->len, offset); if (ret != request->len) { return -EIO; } } qemu_aio_set_fd_handler(s->sock, nbd_reply_ready, NULL, nbd_have_request, s); s->send_coroutine = NULL; qemu_co_mutex_unlock(&s->send_mutex); return rc; }
static void qemu_rbd_close(BlockDriverState *bs) { BDRVRBDState *s = bs->opaque; close(s->fds[0]); close(s->fds[1]); qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], NULL, NULL, NULL, NULL); rbd_close(s->image); rados_ioctx_destroy(s->io_ctx); g_free(s->snap); rados_shutdown(s->cluster); }
static void qemu_gluster_close(BlockDriverState *bs) { BDRVGlusterState *s = bs->opaque; close(s->fds[GLUSTER_FD_READ]); close(s->fds[GLUSTER_FD_WRITE]); qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], NULL, NULL, NULL); if (s->fd) { glfs_close(s->fd); s->fd = NULL; } glfs_fini(s->glfs); }
static void iscsi_set_events(IscsiLun *iscsilun) { struct iscsi_context *iscsi = iscsilun->iscsi; int ev; /* We always register a read handler. */ ev = POLLIN; ev |= iscsi_which_events(iscsi); if (ev != iscsilun->events) { qemu_aio_set_fd_handler(iscsi_get_fd(iscsi), iscsi_process_read, (ev & POLLOUT) ? iscsi_process_write : NULL, iscsilun); } iscsilun->events = ev; }
static int nbd_establish_connection(BlockDriverState *bs) { BDRVNBDState *s = bs->opaque; int sock; int ret; off_t size; size_t blocksize; if (s->host_spec[0] == '/') { sock = unix_socket_outgoing(s->host_spec); } else { sock = tcp_socket_outgoing_spec(s->host_spec); } /* Failed to establish connection */ if (sock < 0) { logout("Failed to establish connection to NBD server\n"); return -errno; } /* NBD handshake */ ret = nbd_receive_negotiate(sock, s->export_name, &s->nbdflags, &size, &blocksize); if (ret < 0) { logout("Failed to negotiate with the NBD server\n"); closesocket(sock); return ret; } /* Now that we're connected, set the socket to be non-blocking and * kick the reply mechanism. */ socket_set_nonblock(sock); qemu_aio_set_fd_handler(sock, nbd_reply_ready, NULL, nbd_have_request, s); s->sock = sock; s->size = size; s->blocksize = blocksize; logout("Established connection with NBD server\n"); return 0; }
static coroutine_fn void set_fd_handler(BDRVSSHState *s) { int r; IOHandler *rd_handler = NULL, *wr_handler = NULL; Coroutine *co = qemu_coroutine_self(); r = libssh2_session_block_directions(s->session); if (r & LIBSSH2_SESSION_BLOCK_INBOUND) { rd_handler = restart_coroutine; } if (r & LIBSSH2_SESSION_BLOCK_OUTBOUND) { wr_handler = restart_coroutine; } DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock, rd_handler, wr_handler); qemu_aio_set_fd_handler(s->sock, rd_handler, wr_handler, return_true, co); }
static int posix_aio_init(void) { struct sigaction act; PosixAioState *s; int fds[2]; struct qemu_paioinit ai; if (posix_aio_state) return 0; s = qemu_malloc(sizeof(PosixAioState)); sigfillset(&act.sa_mask); act.sa_flags = 0; /* do not restart syscalls to interrupt select() */ act.sa_handler = aio_signal_handler; sigaction(SIGUSR2, &act, NULL); s->first_aio = NULL; if (pipe(fds) == -1) { fprintf(stderr, "failed to create pipe\n"); return -errno; } s->rfd = fds[0]; s->wfd = fds[1]; fcntl(s->rfd, F_SETFL, O_NONBLOCK); fcntl(s->wfd, F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->rfd, posix_aio_read, NULL, posix_aio_flush, s); memset(&ai, 0, sizeof(ai)); ai.aio_threads = 64; ai.aio_num = 64; qemu_paio_init(&ai); posix_aio_state = s; return 0; }
static int posix_aio_init(void) { sigset_t mask; PosixAioState *s; struct qemu_paioinit ai; if (posix_aio_state) return 0; s = qemu_malloc(sizeof(PosixAioState)); /* Make sure to block AIO signal */ sigemptyset(&mask); sigaddset(&mask, SIGUSR2); sigprocmask(SIG_BLOCK, &mask, NULL); s->first_aio = NULL; s->fd = qemu_signalfd(&mask); if (s->fd == -1) { fprintf(stderr, "failed to create signalfd\n"); return -errno; } fcntl(s->fd, F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fd, posix_aio_read, NULL, posix_aio_flush, s); memset(&ai, 0, sizeof(ai)); ai.aio_threads = 64; ai.aio_num = 64; qemu_paio_init(&ai); posix_aio_state = s; return 0; }
void *laio_init(void) { struct qemu_laio_state *s; s = g_malloc0(sizeof(*s)); s->efd = eventfd(0, 0); if (s->efd == -1) goto out_free_state; fcntl(s->efd, F_SETFL, O_NONBLOCK); if (io_setup(MAX_EVENTS, &s->ctx) != 0) goto out_close_efd; qemu_aio_set_fd_handler(s->efd, qemu_laio_completion_cb, NULL, qemu_laio_flush_cb, NULL, s); return s; out_close_efd: close(s->efd); out_free_state: g_free(s); return NULL; }
static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRBDState *s = bs->opaque; char pool[RBD_MAX_POOL_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; char clientname_buf[RBD_MAX_CONF_SIZE]; char *clientname; int r; if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), s->name, sizeof(s->name), conf, sizeof(conf)) < 0) { return -EINVAL; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); r = rados_create(&s->cluster, clientname); if (r < 0) { error_report("error initializing"); return r; } s->snap = NULL; if (snap_buf[0] != '\0') { s->snap = g_strdup(snap_buf); } if (strstr(conf, "conf=") == NULL) { /* try default location, but ignore failure */ rados_conf_read_file(s->cluster, NULL); } if (conf[0] != '\0') { r = qemu_rbd_set_conf(s->cluster, conf); if (r < 0) { error_report("error setting config options"); goto failed_shutdown; } } r = rados_connect(s->cluster); if (r < 0) { error_report("error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_report("error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_report("error reading header from %s", s->name); goto failed_open; } bs->read_only = (s->snap != NULL); s->event_reader_pos = 0; r = qemu_pipe(s->fds); if (r < 0) { error_report("error opening eventfd"); goto failed; } fcntl(s->fds[0], F_SETFL, O_NONBLOCK); fcntl(s->fds[1], F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader, NULL, qemu_rbd_aio_flush_cb, NULL, s); return 0; failed: rbd_close(s->image); failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); return r; }
static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRBDState *s = bs->opaque; char pool[RBD_MAX_POOL_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; char clientname_buf[RBD_MAX_CONF_SIZE]; char *clientname; int r; if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), s->name, sizeof(s->name), conf, sizeof(conf)) < 0) { return -EINVAL; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); r = rados_create(&s->cluster, clientname); if (r < 0) { error_report("error initializing"); return r; } s->snap = NULL; if (snap_buf[0] != '\0') { s->snap = g_strdup(snap_buf); } /* * Fallback to more conservative semantics if setting cache * options fails. Ignore errors from setting rbd_cache because the * only possible error is that the option does not exist, and * librbd defaults to no caching. If write through caching cannot * be set up, fall back to no caching. */ if (flags & BDRV_O_NOCACHE) { rados_conf_set(s->cluster, "rbd_cache", "false"); } else { rados_conf_set(s->cluster, "rbd_cache", "true"); } if (strstr(conf, "conf=") == NULL) { /* try default location, but ignore failure */ rados_conf_read_file(s->cluster, NULL); } if (conf[0] != '\0') { r = qemu_rbd_set_conf(s->cluster, conf); if (r < 0) { error_report("error setting config options"); goto failed_shutdown; } } r = rados_connect(s->cluster); if (r < 0) { error_report("error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_report("error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_report("error reading header from %s", s->name); goto failed_open; } bs->read_only = (s->snap != NULL); s->event_reader_pos = 0; r = qemu_pipe(s->fds); if (r < 0) { error_report("error opening eventfd"); goto failed; } fcntl(s->fds[0], F_SETFL, O_NONBLOCK); fcntl(s->fds[1], F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader, NULL, qemu_rbd_aio_flush_cb, s); return 0; failed: rbd_close(s->image); failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); return r; }
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); }
static int qemu_gluster_open(BlockDriverState *bs, QDict *options, int bdrv_flags) { BDRVGlusterState *s = bs->opaque; int open_flags = O_BINARY; int ret = 0; GlusterConf *gconf = g_malloc0(sizeof(GlusterConf)); QemuOpts *opts; Error *local_err = NULL; const char *filename; opts = qemu_opts_create_nofail(&runtime_opts); qemu_opts_absorb_qdict(opts, options, &local_err); if (error_is_set(&local_err)) { qerror_report_err(local_err); error_free(local_err); ret = -EINVAL; goto out; } filename = qemu_opt_get(opts, "filename"); s->glfs = qemu_gluster_init(gconf, filename); if (!s->glfs) { ret = -errno; goto out; } if (bdrv_flags & BDRV_O_RDWR) { open_flags |= O_RDWR; } else { open_flags |= O_RDONLY; } if ((bdrv_flags & BDRV_O_NOCACHE)) { open_flags |= O_DIRECT; } s->fd = glfs_open(s->glfs, gconf->image, open_flags); if (!s->fd) { ret = -errno; goto out; } ret = qemu_pipe(s->fds); if (ret < 0) { ret = -errno; goto out; } fcntl(s->fds[GLUSTER_FD_READ], F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fds[GLUSTER_FD_READ], qemu_gluster_aio_event_reader, NULL, s); out: qemu_opts_del(opts); qemu_gluster_gconf_free(gconf); if (!ret) { return ret; } if (s->fd) { glfs_close(s->fd); } if (s->glfs) { glfs_fini(s->glfs); } return ret; }
static coroutine_fn void clear_fd_handler(BDRVSSHState *s) { DPRINTF("s->sock=%d", s->sock); qemu_aio_set_fd_handler(s->sock, NULL, NULL, NULL, NULL); }