static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch *watch, const char *watch_path, const char *event_path) { libxl__logdirty_switch *lds = CONTAINER_OF(watch, *lds, watch); STATE_AO_GC(lds->ao); const char *got; xs_transaction_t t = 0; int rc; for (;;) { rc = libxl__xs_transaction_start(gc, &t); if (rc) goto out; rc = libxl__xs_read_checked(gc, t, lds->ret_path, &got); if (rc) goto out; if (!got) { rc = +1; goto out; } if (strcmp(got, lds->cmd)) { LOG(ERROR,"logdirty switch: sent command `%s' but got reply `%s'" " (xenstore paths `%s' / `%s')", lds->cmd, got, lds->cmd_path, lds->ret_path); rc = ERROR_FAIL; goto out; } rc = libxl__xs_rm_checked(gc, t, lds->cmd_path); if (rc) goto out; rc = libxl__xs_rm_checked(gc, t, lds->ret_path); if (rc) goto out; rc = libxl__xs_transaction_commit(gc, &t); if (!rc) break; if (rc<0) goto out; } out: /* rc < 0: error * rc == 0: ok, we are done * rc == +1: need to keep waiting */ libxl__xs_transaction_abort(gc, &t); if (rc <= 0) { if (rc < 0) LOG(ERROR,"logdirty switch: failed (rc=%d)",rc); switch_logdirty_done(egc,lds,rc); } }
void xswait_xswatch_callback(libxl__egc *egc, libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path) { EGC_GC; libxl__xswait_state *xswa = CONTAINER_OF(xsw, *xswa, watch_ev); int rc; const char *data; if (xswa->path[0] == '@') { data = 0; } else { rc = libxl__xs_read_checked(gc, XBT_NULL, xswa->path, &data); if (rc) { xswait_report_error(egc, xswa, rc); return; } } xswa->callback(egc, xswa, 0, data); }
/* * If the device has a vifname, then use that instead of * the vifX.Y format. * it must ONLY be used for remus because if driver domains * were in use it would constitute a security vulnerability. */ static const char *get_vifname(libxl__checkpoint_device *dev, const libxl_device_nic *nic) { const char *vifname = NULL; const char *path; int rc; STATE_AO_GC(dev->cds->ao); /* Convenience aliases */ const uint32_t domid = dev->cds->domid; path = GCSPRINTF("%s/backend/vif/%d/%d/vifname", libxl__xs_get_dompath(gc, 0), domid, nic->devid); rc = libxl__xs_read_checked(gc, XBT_NULL, path, &vifname); if (!rc && !vifname) { vifname = libxl__device_nic_devname(gc, domid, nic->devid, nic->nictype); } return vifname; }
static void domain_suspend_switch_qemu_xen_traditional_logdirty (libxl__egc *egc, int domid, unsigned enable, libxl__logdirty_switch *lds) { STATE_AO_GC(lds->ao); int rc; xs_transaction_t t = 0; const char *got; if (!lds->cmd_path) { uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid); lds->cmd_path = DEVICE_MODEL_XS_PATH(gc, dm_domid, domid, "/logdirty/cmd"); lds->ret_path = DEVICE_MODEL_XS_PATH(gc, dm_domid, domid, "/logdirty/ret"); } lds->cmd = enable ? "enable" : "disable"; rc = libxl__ev_xswatch_register(gc, &lds->watch, switch_logdirty_xswatch, lds->ret_path); if (rc) goto out; rc = libxl__ev_time_register_rel(ao, &lds->timeout, switch_logdirty_timeout, 10*1000); if (rc) goto out; for (;;) { rc = libxl__xs_transaction_start(gc, &t); if (rc) goto out; rc = libxl__xs_read_checked(gc, t, lds->cmd_path, &got); if (rc) goto out; if (got) { const char *got_ret; rc = libxl__xs_read_checked(gc, t, lds->ret_path, &got_ret); if (rc) goto out; if (!got_ret || strcmp(got, got_ret)) { LOG(ERROR,"controlling logdirty: qemu was already sent" " command `%s' (xenstore path `%s') but result is `%s'", got, lds->cmd_path, got_ret ? got_ret : "<none>"); rc = ERROR_FAIL; goto out; } rc = libxl__xs_rm_checked(gc, t, lds->cmd_path); if (rc) goto out; } rc = libxl__xs_rm_checked(gc, t, lds->ret_path); if (rc) goto out; rc = libxl__xs_write_checked(gc, t, lds->cmd_path, lds->cmd); if (rc) goto out; rc = libxl__xs_transaction_commit(gc, &t); if (!rc) break; if (rc<0) goto out; } /* OK, wait for some callback */ return; out: LOG(ERROR,"logdirty switch failed (rc=%d), abandoning suspend",rc); libxl__xs_transaction_abort(gc, &t); switch_logdirty_done(egc,lds,rc); }
/* * In return, the script writes the name of REMUS_IFB device (during setup) * to be used for output buffering into XENBUS_PATH/ifb */ static void netbuf_setup_script_cb(libxl__egc *egc, libxl__async_exec_state *aes, int rc, int status) { libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes); libxl__checkpoint_device *dev = CONTAINER_OF(aodev, *dev, aodev); libxl__remus_device_nic *remus_nic = dev->concrete_data; libxl__checkpoint_devices_state *cds = dev->cds; libxl__remus_state *rs = cds->concrete_data; const char *out_path_base, *hotplug_error = NULL; STATE_AO_GC(cds->ao); /* Convenience aliases */ const uint32_t domid = cds->domid; const int devid = remus_nic->devid; const char *const vif = remus_nic->vif; const char **const ifb = &remus_nic->ifb; if (status && !rc) rc = ERROR_FAIL; if (rc) goto out; /* * we need to get ifb first because it's needed for teardown */ rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/remus/netbuf/%d/ifb", libxl__xs_libxl_path(gc, domid), devid), ifb); if (rc) goto out; if (!(*ifb)) { LOGD(ERROR, domid, "Cannot get ifb dev name for domain %u dev %s", domid, vif); rc = ERROR_FAIL; goto out; } out_path_base = GCSPRINTF("%s/remus/netbuf/%d", libxl__xs_libxl_path(gc, domid), devid); rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/hotplug-error", out_path_base), &hotplug_error); if (rc) goto out; if (hotplug_error) { LOGD(ERROR, domid, "netbuf script %s setup failed for vif %s: %s", rs->netbufscript, vif, hotplug_error); rc = ERROR_FAIL; goto out; } if (status) { rc = ERROR_FAIL; goto out; } LOGD(DEBUG, domid, "%s will buffer packets from vif %s", *ifb, vif); rc = init_qdisc(cds, remus_nic); out: aodev->rc = rc; aodev->callback(egc, aodev); }
static int libxl__device_nic_from_xenstore(libxl__gc *gc, const char *libxl_path, libxl_device_nic *nic) { const char *tmp; int rc; libxl_device_nic_init(nic); rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/handle", libxl_path), &tmp); if (rc) goto out; if (tmp) nic->devid = atoi(tmp); else nic->devid = 0; /* nic->mtu = */ rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/mac", libxl_path), &tmp); if (rc) goto out; if (tmp) { rc = libxl__parse_mac(tmp, nic->mac); if (rc) goto out; } else { memset(nic->mac, 0, sizeof(nic->mac)); } rc = libxl__xs_read_checked(NOGC, XBT_NULL, GCSPRINTF("%s/ip", libxl_path), (const char **)(&nic->ip)); if (rc) goto out; rc = libxl__xs_read_checked(NOGC, XBT_NULL, GCSPRINTF("%s/bridge", libxl_path), (const char **)(&nic->bridge)); if (rc) goto out; rc = libxl__xs_read_checked(NOGC, XBT_NULL, GCSPRINTF("%s/script", libxl_path), (const char **)(&nic->script)); if (rc) goto out; rc = libxl__xs_read_checked(NOGC, XBT_NULL, GCSPRINTF("%s/forwarddev", libxl_path), (const char **)(&nic->coloft_forwarddev)); if (rc) goto out; /* vif_ioemu nics use the same xenstore entries as vif interfaces */ rc = libxl__xs_read_checked(gc, XBT_NULL, GCSPRINTF("%s/type", libxl_path), &tmp); if (rc) goto out; if (tmp) { rc = libxl_nic_type_from_string(tmp, &nic->nictype); if (rc) goto out; } else { nic->nictype = LIBXL_NIC_TYPE_VIF; } nic->model = NULL; /* XXX Only for TYPE_IOEMU */ nic->ifname = NULL; /* XXX Only for TYPE_IOEMU */ rc = 0; out: return rc; }