Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
    }
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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);;
}