int libxl__datacopier_start(libxl__datacopier_state *dc) { int rc; STATE_AO_GC(dc->ao); libxl__datacopier_init(dc); assert(dc->readfd >= 0 || dc->writefd >= 0); assert(!(dc->readbuf && dc->bytes_to_read == -1)); dc->abrt.ao = ao; dc->abrt.callback = datacopier_abort; rc = libxl__ao_abortable_register(&dc->abrt); if (rc) goto out; if (dc->readfd >= 0) { rc = libxl__ev_fd_register(gc, &dc->toread, datacopier_readable, dc->readfd, POLLIN); if (rc) goto out; } if (dc->writefd >= 0) { rc = libxl__ev_fd_register(gc, &dc->towrite, datacopier_writable, dc->writefd, POLLOUT); if (rc) goto out; } return 0; out: libxl__datacopier_kill(dc); return rc; }
static void datacopier_check_state(libxl__egc *egc, libxl__datacopier_state *dc) { STATE_AO_GC(dc->ao); int rc; if (dc->used && !dc->readbuf) { if (!libxl__ev_fd_isregistered(&dc->towrite)) { rc = libxl__ev_fd_register(gc, &dc->towrite, datacopier_writable, dc->writefd, POLLOUT); if (rc) { LOG(ERROR, "unable to establish write event on %s" " during copy of %s", dc->writewhat, dc->copywhat); datacopier_callback(egc, dc, ERROR_FAIL, -1, EIO); return; } } } else if (!libxl__ev_fd_isregistered(&dc->toread) || dc->bytes_to_read == 0) { /* we have had eof */ datacopier_callback(egc, dc, 0, 0, 0); return; } else { /* nothing buffered, but still reading */ libxl__ev_fd_deregister(gc, &dc->towrite); } }
int libxl__datacopier_start(libxl__datacopier_state *dc) { int rc; STATE_AO_GC(dc->ao); libxl__datacopier_init(dc); rc = libxl__ev_fd_register(gc, &dc->toread, datacopier_readable, dc->readfd, POLLIN); if (rc) goto out; rc = libxl__ev_fd_register(gc, &dc->towrite, datacopier_writable, dc->writefd, POLLOUT); if (rc) goto out; return 0; out: libxl__datacopier_kill(dc); return rc; }
static void run_helper(libxl__egc *egc, libxl__save_helper_state *shs, const char *mode_arg, int stream_fd, const int *preserve_fds, int num_preserve_fds, const unsigned long *argnums, int num_argnums) { STATE_AO_GC(shs->ao); const char *args[4 + num_argnums]; const char **arg = args; int i, rc; /* Resources we must free */ libxl__carefd *childs_pipes[2] = { 0,0 }; /* Convenience aliases */ const uint32_t domid = shs->domid; shs->rc = 0; shs->completed = 0; shs->pipes[0] = shs->pipes[1] = 0; libxl__ev_fd_init(&shs->readable); libxl__ev_child_init(&shs->child); shs->stdin_what = GCSPRINTF("domain %"PRIu32" save/restore helper" " stdin pipe", domid); shs->stdout_what = GCSPRINTF("domain %"PRIu32" save/restore helper" " stdout pipe", domid); *arg++ = getenv("LIBXL_SAVE_HELPER") ?: PRIVATE_BINDIR "/" "libxl-save-helper"; *arg++ = mode_arg; const char **stream_fd_arg = arg++; for (i=0; i<num_argnums; i++) *arg++ = GCSPRINTF("%lu", argnums[i]); *arg++ = 0; assert(arg == args + ARRAY_SIZE(args)); libxl__carefd_begin(); int childfd; for (childfd=0; childfd<2; childfd++) { /* Setting up the pipe for the child's fd childfd */ int fds[2]; if (libxl_pipe(CTX,fds)) { rc = ERROR_FAIL; libxl__carefd_unlock(); goto out; } int childs_end = childfd==0 ? 0 /*read*/ : 1 /*write*/; int our_end = childfd==0 ? 1 /*write*/ : 0 /*read*/; childs_pipes[childfd] = libxl__carefd_record(CTX, fds[childs_end]); shs->pipes[childfd] = libxl__carefd_record(CTX, fds[our_end]); } libxl__carefd_unlock(); pid_t pid = libxl__ev_child_fork(gc, &shs->child, helper_exited); if (!pid) { if (stream_fd <= 2) { stream_fd = dup(stream_fd); if (stream_fd < 0) { LOGE(ERROR,"dup migration stream fd"); exit(-1); } } libxl_fd_set_cloexec(CTX, stream_fd, 0); *stream_fd_arg = GCSPRINTF("%d", stream_fd); for (i=0; i<num_preserve_fds; i++) if (preserve_fds[i] >= 0) { assert(preserve_fds[i] > 2); libxl_fd_set_cloexec(CTX, preserve_fds[i], 0); } libxl__exec(gc, libxl__carefd_fd(childs_pipes[0]), libxl__carefd_fd(childs_pipes[1]), -1, args[0], (char**)args, 0); } libxl__carefd_close(childs_pipes[0]); libxl__carefd_close(childs_pipes[1]); rc = libxl__ev_fd_register(gc, &shs->readable, helper_stdout_readable, libxl__carefd_fd(shs->pipes[1]), POLLIN|POLLPRI); if (rc) goto out; return; out: libxl__carefd_close(childs_pipes[0]); libxl__carefd_close(childs_pipes[1]); helper_failed(egc, shs, rc);; }