static void sysrq_handler(struct xenbus_watch *watch, const char *path, const char *token) { char sysrq_key = '\0'; struct xenbus_transaction xbt; int err; again: err = xenbus_transaction_start(&xbt); if (err) return; err = xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key); if (err < 0) { /* * The Xenstore watch fires directly after registering it and * after a suspend/resume cycle. So ENOENT is no error but * might happen in those cases. */ if (err != -ENOENT) pr_err("Error %d reading sysrq code in control/sysrq\n", err); xenbus_transaction_end(xbt, 1); return; } if (sysrq_key != '\0') xenbus_printf(xbt, "control", "sysrq", "%c", '\0'); err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (sysrq_key != '\0') handle_sysrq(sysrq_key); }
static int pcifront_publish_info(struct pcifront_device *pdev) { int err = 0; struct xenbus_transaction trans; err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info)); if (err < 0) goto out; pdev->gnt_ref = err; err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn); if (err) goto out; bind_caller_port_to_irqhandler(pdev->evtchn, pcifront_handler_aer, IRQF_SAMPLE_RANDOM, "pcifront", pdev); do_publish: err = xenbus_transaction_start(&trans); if (err) { xenbus_dev_fatal(pdev->xdev, err, "Error writing configuration for backend " "(start transaction)"); goto out; } err = xenbus_printf(trans, pdev->xdev->nodename, "pci-op-ref", "%u", pdev->gnt_ref); if (!err) err = xenbus_printf(trans, pdev->xdev->nodename, "event-channel", "%u", pdev->evtchn); if (!err) err = xenbus_printf(trans, pdev->xdev->nodename, "magic", XEN_PCI_MAGIC); if (err) { xenbus_transaction_end(trans, 1); xenbus_dev_fatal(pdev->xdev, err, "Error writing configuration for backend"); goto out; } else { err = xenbus_transaction_end(trans, 0); if (err == -EAGAIN) goto do_publish; else if (err) { xenbus_dev_fatal(pdev->xdev, err, "Error completing transaction " "for backend"); goto out; } } xenbus_switch_state(pdev->xdev, XenbusStateInitialised); dev_dbg(&pdev->xdev->dev, "publishing successful!\n"); out: return err; }
static int publish_frontend_name(struct xenbus_device *dev) { struct xenbus_transaction tr; int err; /* Publish the name of the frontend driver */ do { err = xenbus_transaction_start(&tr); if (err != 0) { EPRINTK("%s: transaction start failed\n", __FUNCTION__); return err; } err = xenbus_printf(tr, dev->nodename, "accel-frontend", "%s", frontend_name); if (err != 0) { EPRINTK("%s: xenbus_printf failed\n", __FUNCTION__); xenbus_transaction_end(tr, 1); return err; } err = xenbus_transaction_end(tr, 0); } while (err == -EAGAIN); if (err != 0) { EPRINTK("failed to end frontend name transaction\n"); return err; } return 0; }
static void connect(struct backend_info *be) { xenbus_transaction_t xbt; int err; struct xenbus_device *dev = be->dev; unsigned long ready = 1; again: err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(be->dev, err, "starting transaction"); return; } err = xenbus_printf(xbt, be->dev->nodename, "ready", "%lu", ready); if (err) { xenbus_dev_fatal(be->dev, err, "writing 'ready'"); goto abort; } err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) xenbus_dev_fatal(be->dev, err, "end of transaction"); err = xenbus_switch_state(dev, XenbusStateConnected); if (!err) be->tpmif->status = CONNECTED; return; abort: xenbus_transaction_end(xbt, 1); }
static void sysrq_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { char sysrq_key = '\0'; struct xenbus_transaction xbt; int err; again: err = xenbus_transaction_start(&xbt); if (err) return; if (!xenbus_scanf(xbt, "control", "sysrq", "%c", &sysrq_key)) { printk(KERN_ERR "Unable to read sysrq code in " "control/sysrq\n"); xenbus_transaction_end(xbt, 1); return; } if (sysrq_key != '\0') xenbus_printf(xbt, "control", "sysrq", "%c", '\0'); err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; #ifdef CONFIG_MAGIC_SYSRQ if (sysrq_key != '\0') handle_sysrq(sysrq_key, NULL, NULL); #endif }
static int talk_to_backend(struct xenbus_device *dev, struct usbfront_info *info) { const char *message; struct xenbus_transaction xbt; int err; err = setup_rings(dev, info); if (err) goto out; again: err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); goto destroy_ring; } err = xenbus_printf(xbt, dev->nodename, "urb-ring-ref", "%u", info->urb_ring_ref); if (err) { message = "writing urb-ring-ref"; goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, "conn-ring-ref", "%u", info->conn_ring_ref); if (err) { message = "writing conn-ring-ref"; goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", irq_to_evtchn_port(info->irq)); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) goto again; xenbus_dev_fatal(dev, err, "completing transaction"); goto destroy_ring; } return 0; abort_transaction: xenbus_transaction_end(xbt, 1); xenbus_dev_fatal(dev, err, "%s", message); destroy_ring: destroy_rings(info); out: return err; }
/* Common code used when first setting up, and when resuming. */ static int talk_to_ixpback(struct xenbus_device *dev, struct ixpfront_info *info) { const char *message = NULL; struct xenbus_transaction xbt; int err; /* Create shared ring, alloc event channel. */ err = setup_ixpring(dev, info); if (err) goto out; again: err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); goto destroy_ixpring; } err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u", info->ring_ref); if (err) { message = "writing ring-ref"; goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", info->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, dev->nodename, "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); if (err) { message = "writing protocol"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0); if (err) { if (err == -EAGAIN) goto again; xenbus_dev_fatal(dev, err, "completing transaction"); goto destroy_ixpring; } xenbus_switch_state(dev, XenbusStateInitialised); return 0; abort_transaction: xenbus_transaction_end(xbt, 1); if (message) xenbus_dev_fatal(dev, err, "%s", message); destroy_ixpring: ixp_free(info, 0); out: return err; }
/* Write to the xenbus info needed by backend */ static int pcifront_publish_info(struct pcifront_device *pdev) { int err = 0; struct xenbus_transaction *trans; err = xenbus_grant_ring(pdev->xdev, virt_to_mfn(pdev->sh_info)); if (err < 0) { WPRINTF("error granting access to ring page\n"); goto out; } pdev->gnt_ref = err; err = xenbus_alloc_evtchn(pdev->xdev, &pdev->evtchn); if (err) goto out; do_publish: trans = xenbus_transaction_start(); if (IS_ERR(trans)) { xenbus_dev_fatal(pdev->xdev, err, "Error writing configuration for backend " "(start transaction)"); goto out; } err = xenbus_printf(trans, pdev->xdev->nodename, "pci-op-ref", "%u", pdev->gnt_ref); if (!err) err = xenbus_printf(trans, pdev->xdev->nodename, "event-channel", "%u", pdev->evtchn); if (!err) err = xenbus_printf(trans, pdev->xdev->nodename, "magic", XEN_PCI_MAGIC); if (!err) err = xenbus_switch_state(pdev->xdev, trans, XenbusStateInitialised); if (err) { xenbus_transaction_end(trans, 1); xenbus_dev_fatal(pdev->xdev, err, "Error writing configuration for backend"); goto out; } else { err = xenbus_transaction_end(trans, 0); if (err == -EAGAIN) goto do_publish; else if (err) { xenbus_dev_fatal(pdev->xdev, err, "Error completing transaction for backend"); goto out; } } out: return err; }
/*ARGSUSED*/ static void xen_shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { char *str; xenbus_transaction_t xbt; int err, shutdown_code = SHUTDOWN_INVALID; unsigned int slen; again: err = xenbus_transaction_start(&xbt); if (err) return; if (xenbus_read(xbt, "control", "shutdown", (void *)&str, &slen)) { (void) xenbus_transaction_end(xbt, 1); return; } SUSPEND_DEBUG("%d: xen_shutdown_handler: \"%s\"\n", CPU->cpu_id, str); /* * If this is a watch fired from our write below, check out early to * avoid an infinite loop. */ if (strcmp(str, "") == 0) { (void) xenbus_transaction_end(xbt, 0); kmem_free(str, slen); return; } else if (strcmp(str, "poweroff") == 0) { shutdown_code = SHUTDOWN_POWEROFF; } else if (strcmp(str, "reboot") == 0) { shutdown_code = SHUTDOWN_REBOOT; } else if (strcmp(str, "suspend") == 0) { shutdown_code = SHUTDOWN_SUSPEND; } else if (strcmp(str, "halt") == 0) { shutdown_code = SHUTDOWN_HALT; } else { printf("Ignoring shutdown request: %s\n", str); } /* * XXPV Should we check the value of xenbus_write() too, or are all * errors automatically folded into xenbus_transaction_end() ?? */ (void) xenbus_write(xbt, "control", "shutdown", ""); err = xenbus_transaction_end(xbt, 0); if (err == EAGAIN) { SUSPEND_DEBUG("%d: trying again\n", CPU->cpu_id); kmem_free(str, slen); goto again; } kmem_free(str, slen); if (shutdown_code != SHUTDOWN_INVALID) { (void) taskq_dispatch(xen_shutdown_tq, xen_shutdown, (void *)(intptr_t)shutdown_code, 0); } }
/** * Entry point to this code when a new device is created. Allocate the basic * structures, and watch the store waiting for the hotplug scripts to tell us * the device's handle. Switch to InitWait. */ static int netback_probe(struct xenbus_device *dev, const struct xenbus_device_id *id) { const char *message; xenbus_transaction_t xbt; int err; struct backend_info *be = kzalloc(sizeof(struct backend_info), GFP_KERNEL); if (!be) { xenbus_dev_fatal(dev, -ENOMEM, "allocating backend structure"); return -ENOMEM; } be->dev = dev; dev->data = be; err = xenbus_watch_path2(dev, dev->nodename, "handle", &be->backend_watch, backend_changed); if (err) goto fail; do { err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); goto fail; } err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", 1); if (err) { message = "writing feature-sg"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0); } while (err == -EAGAIN); if (err) { xenbus_dev_fatal(dev, err, "completing transaction"); goto fail; } err = xenbus_switch_state(dev, XenbusStateInitWait); if (err) { goto fail; } return 0; abort_transaction: xenbus_transaction_end(xbt, 1); xenbus_dev_fatal(dev, err, "%s", message); fail: DPRINTK("failed"); netback_remove(dev); return err; }
static void shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { char *str; struct xenbus_transaction xbt; int err; static struct shutdown_handler handlers[] = { { "poweroff", do_poweroff }, { "halt", do_poweroff }, { "reboot", do_reboot }, #ifdef CONFIG_HIBERNATE_CALLBACKS { "suspend", do_suspend }, #endif {NULL, NULL}, }; static struct shutdown_handler *handler; if (shutting_down != SHUTDOWN_INVALID) return; again: err = xenbus_transaction_start(&xbt); if (err) return; str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); /* Ignore read errors and empty reads. */ if (XENBUS_IS_ERR_READ(str)) { xenbus_transaction_end(xbt, 1); return; } for (handler = &handlers[0]; handler->command; handler++) { if (strcmp(str, handler->command) == 0) break; } /* Only acknowledge commands which we are prepared to handle. */ if (handler->cb) xenbus_write(xbt, "control", "shutdown", ""); err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) { kfree(str); goto again; } if (handler->cb) { handler->cb(); } else { pr_info("Ignoring shutdown request: %s\n", str); shutting_down = SHUTDOWN_INVALID; } kfree(str); }
/** * Write the physical details regarding the block device to the store, and * switch to Connected state. */ static void connect(struct backend_info *be) { xenbus_transaction_t xbt; int err; struct xenbus_device *dev = be->dev; DPRINTK("%s", dev->otherend); /* Supply the information about the device the frontend needs */ again: err = xenbus_transaction_start(&xbt); if (err) { xenbus_dev_fatal(dev, err, "starting transaction"); return; } err = xenbus_printf(xbt, dev->nodename, "sectors", "%lu", vbd_size(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sectors", dev->nodename); goto abort; } /* FIXME: use a typename instead */ err = xenbus_printf(xbt, dev->nodename, "info", "%u", vbd_info(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/info", dev->nodename); goto abort; } err = xenbus_printf(xbt, dev->nodename, "sector-size", "%lu", vbd_secsize(&be->blkif->vbd)); if (err) { xenbus_dev_fatal(dev, err, "writing %s/sector-size", dev->nodename); goto abort; } err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) xenbus_dev_fatal(dev, err, "ending transaction"); err = xenbus_switch_state(dev, XenbusStateConnected); if (err) xenbus_dev_fatal(dev, err, "switching to Connected state", dev->nodename); return; abort: xenbus_transaction_end(xbt, 1); }
static void shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { extern void ctrl_alt_del(void); char *str; struct xenbus_transaction xbt; int err, new_state = SHUTDOWN_INVALID; if ((shutting_down != SHUTDOWN_INVALID) && (shutting_down != SHUTDOWN_RESUMING)) return; again: err = xenbus_transaction_start(&xbt); if (err) return; str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); /* Ignore read errors and empty reads. */ if (XENBUS_IS_ERR_READ(str)) { xenbus_transaction_end(xbt, 1); return; } /*将其清空后,如果热迁移时suspend失败则会导致迁移挂死,去掉后suspend失败后则会迁移超时*/ //xenbus_write(xbt, "control", "shutdown", ""); err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) { kfree(str); goto again; } printk(KERN_WARNING "%s(%d): receive shutdown request %s\n", __FUNCTION__, __LINE__, str); if (strcmp(str, "poweroff") == 0) new_state = SHUTDOWN_POWEROFF; else if (strcmp(str, "reboot") == 0) ctrl_alt_del(); else if (strcmp(str, "suspend") == 0) new_state = SHUTDOWN_SUSPEND; else if (strcmp(str, "halt") == 0) new_state = SHUTDOWN_HALT; else printk("Ignoring shutdown request: %s\n", str); switch_shutdown_state(new_state); kfree(str); }
static int xenkbd_connect_backend(struct xenbus_device *dev, struct xenkbd_info *info) { int ret, evtchn; struct xenbus_transaction xbt; ret = xenbus_alloc_evtchn(dev, &evtchn); if (ret) return ret; ret = bind_evtchn_to_irqhandler(evtchn, input_handler, 0, dev->devicetype, info); if (ret < 0) { xenbus_free_evtchn(dev, evtchn); xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler"); return ret; } info->irq = ret; again: ret = xenbus_transaction_start(&xbt); if (ret) { xenbus_dev_fatal(dev, ret, "starting transaction"); return ret; } ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu", virt_to_mfn(info->page)); if (ret) goto error_xenbus; ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", evtchn); if (ret) goto error_xenbus; ret = xenbus_transaction_end(xbt, 0); if (ret) { if (ret == -EAGAIN) goto again; xenbus_dev_fatal(dev, ret, "completing transaction"); return ret; } xenbus_switch_state(dev, XenbusStateInitialised); return 0; error_xenbus: xenbus_transaction_end(xbt, 1); xenbus_dev_fatal(dev, ret, "writing xenstore"); return ret; }
static void shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { char *str; struct xenbus_transaction xbt; int err; if (shutting_down != SHUTDOWN_INVALID) return; again: err = xenbus_transaction_start(&xbt); if (err) return; str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); /* Ignore read errors and empty reads. */ if (XENBUS_IS_ERR_READ(str)) { xenbus_transaction_end(xbt, 1); return; } xenbus_write(xbt, "control", "shutdown", ""); err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) { kfree(str); goto again; } if (strcmp(str, "poweroff") == 0 || strcmp(str, "halt") == 0) { shutting_down = SHUTDOWN_POWEROFF; orderly_poweroff(false); } else if (strcmp(str, "reboot") == 0) { shutting_down = SHUTDOWN_POWEROFF; /* ? */ ctrl_alt_del(); #ifdef CONFIG_PM_SLEEP } else if (strcmp(str, "suspend") == 0) { do_suspend(); #endif } else { printk(KERN_INFO "Ignoring shutdown request: %s\n", str); shutting_down = SHUTDOWN_INVALID; } kfree(str); }
static void shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { extern void ctrl_alt_del(void); char *str; struct xenbus_transaction xbt; int err; if (shutting_down != SHUTDOWN_INVALID) return; again: err = xenbus_transaction_start(&xbt); if (err) return; str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); /* Ignore read errors and empty reads. */ if (XENBUS_IS_ERR_READ(str)) { xenbus_transaction_end(xbt, 1); return; } xenbus_write(xbt, "control", "shutdown", ""); err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) { kfree(str); goto again; } if (strcmp(str, "poweroff") == 0) shutting_down = SHUTDOWN_POWEROFF; else if (strcmp(str, "reboot") == 0) ctrl_alt_del(); else if (strcmp(str, "suspend") == 0) shutting_down = SHUTDOWN_SUSPEND; else if (strcmp(str, "halt") == 0) shutting_down = SHUTDOWN_HALT; else { printk("Ignoring shutdown request: %s\n", str); shutting_down = SHUTDOWN_INVALID; } if (shutting_down != SHUTDOWN_INVALID) schedule_work(&shutdown_work); kfree(str); }
/* Write a grant ref and ec port to xenstore in a transaction for whatever * your pThing is. Also some non-transaction read/write stuff. */ static NTSTATUS GrantAndEventChannelInATransaction(CHAR *pFrontendPath, struct THING *pThing) { NTSTATUS Status; CHAR *pMyData; xenbus_transaction_t Xbt; do { xenbus_transaction_start(&Xbt); xenbus_write_grant_ref(Xbt, pFrontendPath, "ring-ref", pThing->RingGrantRef); xenbus_write_evtchn_port(Xbt, pFrontendPath, "event-channel", pThing->EvtchnPort); Status = xenbus_transaction_end(Xbt, 0); } while (Status == STATUS_RETRY); if (Status != STATUS_SUCCESS) { DbgPrint("Failed to end transaction, 0x%08x.\n", Status); /* Handle failure */ } /* A write and read w/o a transaction */ xenbus_write(XBT_NIL, "drivers/mydriver", "1.2.3.4"); Status = xenbus_read(XBT_NIL, "drivers/mydriver/mydata", &pMyData); if (NT_SUCCESS(Status)) { DbgPrint("Read MyData: %s\n", pMyData); XmFreeMemory(pMyData); } /* ... */ }
static void shutdown_handler(struct xenbus_watch *watch, const char *path, const char *token) { char *str; struct xenbus_transaction xbt; int err; int idx; if (shutting_down != SHUTDOWN_INVALID) return; again: err = xenbus_transaction_start(&xbt); if (err) return; str = (char *)xenbus_read(xbt, "control", "shutdown", NULL); /* Ignore read errors and empty reads. */ if (XENBUS_IS_ERR_READ(str)) { xenbus_transaction_end(xbt, 1); return; } for (idx = 0; idx < ARRAY_SIZE(shutdown_handlers); idx++) { if (strcmp(str, shutdown_handlers[idx].command) == 0) break; } /* Only acknowledge commands which we are prepared to handle. */ if (idx < ARRAY_SIZE(shutdown_handlers)) xenbus_write(xbt, "control", "shutdown", ""); err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) { kfree(str); goto again; } if (idx < ARRAY_SIZE(shutdown_handlers)) { shutdown_handlers[idx].cb(); } else { pr_info("Ignoring shutdown request: %s\n", str); shutting_down = SHUTDOWN_INVALID; } kfree(str); }
/*ARGSUSED*/ static void xen_sysrq_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { xenbus_transaction_t xbt; char key = '\0'; int ret; retry: if (xenbus_transaction_start(&xbt)) { cmn_err(CE_WARN, "failed to start sysrq transaction"); return; } if ((ret = xenbus_scanf(xbt, "control", "sysrq", "%c", &key)) != 0) { /* * ENOENT happens in response to our own xenbus_rm. * XXPV - this happens spuriously on boot? */ if (ret != ENOENT) cmn_err(CE_WARN, "failed to read sysrq: %d", ret); goto out; } if ((ret = xenbus_rm(xbt, "control", "sysrq")) != 0) { cmn_err(CE_WARN, "failed to reset sysrq: %d", ret); goto out; } if (xenbus_transaction_end(xbt, 0) == EAGAIN) goto retry; /* * Somewhat arbitrary - on Linux this means 'reboot'. We could just * accept any key, but this might increase the risk of sending a * harmless sysrq to the wrong domain... */ if (key == 'b') (void) xen_debug_handler(NULL); else cmn_err(CE_WARN, "Ignored sysrq %c", key); return; out: (void) xenbus_transaction_end(xbt, 1); }
static int unpublish_frontend_name(struct xenbus_device *dev) { struct xenbus_transaction tr; int err; do { err = xenbus_transaction_start(&tr); if (err != 0) break; err = xenbus_rm(tr, dev->nodename, "accel-frontend"); if (err != 0) { xenbus_transaction_end(tr, 1); break; } err = xenbus_transaction_end(tr, 0); } while (err == -EAGAIN); return err; }
static int __xenbus_switch_state(struct xenbus_device *dev, enum xenbus_state state, int depth) { /* We check whether the state is currently set to the given value, and if not, then the state is set. We don't want to unconditionally write the given state, because we don't want to fire watches unnecessarily. Furthermore, if the node has gone, we don't write to it, as the device will be tearing down, and we don't want to resurrect that directory. Note that, because of this cached value of our state, this function will not take a caller's Xenstore transaction (something it was trying to in the past) because dev->state would not get reset if the transaction was aborted. */ struct xenbus_transaction xbt; int current_state; int err, abort; if (state == dev->state) return 0; again: abort = 1; err = xenbus_transaction_start(&xbt); if (err) { xenbus_switch_fatal(dev, depth, err, "starting transaction"); return 0; } err = xenbus_scanf(xbt, dev->nodename, "state", "%d", ¤t_state); if (err != 1) goto abort; err = xenbus_printf(xbt, dev->nodename, "state", "%d", state); if (err) { xenbus_switch_fatal(dev, depth, err, "writing new state"); goto abort; } abort = 0; abort: err = xenbus_transaction_end(xbt, abort); if (err) { if (err == -EAGAIN && !abort) goto again; xenbus_switch_fatal(dev, depth, err, "ending transaction"); } else dev->state = state; return 0; }
void vbd_resize(blkif_t *blkif) { struct vbd *vbd = &blkif->vbd; struct xenbus_transaction xbt; int err; struct xenbus_device *dev = blkback_xenbus(blkif->be); unsigned long long new_size = vbd_size(vbd); printk(KERN_INFO "VBD Resize: new size %Lu\n", new_size); vbd->size = new_size; again: err = xenbus_transaction_start(&xbt); if (err) { printk(KERN_WARNING "Error starting transaction"); return; } err = xenbus_printf(xbt, dev->nodename, "sectors", "%Lu", vbd_size(vbd)); if (err) { printk(KERN_WARNING "Error writing new size"); goto abort; } /* * Write the current state; we will use this to synchronize * the front-end. If the current state is "connected" the * front-end will get the new size information online. */ err = xenbus_printf(xbt, dev->nodename, "state", "%d", dev->state); if (err) { printk(KERN_WARNING "Error writing the state"); goto abort; } err = xenbus_transaction_end(xbt, 0); if (err == -EAGAIN) goto again; if (err) printk(KERN_WARNING "Error ending transaction"); abort: xenbus_transaction_end(xbt, 1); }
static int publish_xenbus(struct tpmfront_dev* dev) { xenbus_transaction_t xbt; int retry; char* err; /* Write the grant reference and event channel to xenstore */ again: if((err = xenbus_transaction_start(&xbt))) { TPMFRONT_ERR("Unable to start xenbus transaction, error was %s\n", err); free(err); return -1; } if((err = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u", (unsigned int) dev->ring_ref))) { TPMFRONT_ERR("Unable to write %s/ring-ref, error was %s\n", dev->nodename, err); free(err); goto abort_transaction; } if((err = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", (unsigned int) dev->evtchn))) { TPMFRONT_ERR("Unable to write %s/event-channel, error was %s\n", dev->nodename, err); free(err); goto abort_transaction; } if((err = xenbus_transaction_end(xbt, 0, &retry))) { TPMFRONT_ERR("Unable to complete xenbus transaction, error was %s\n", err); free(err); return -1; } if(retry) { goto again; } return 0; abort_transaction: if((err = xenbus_transaction_end(xbt, 1, &retry))) { free(err); } return -1; }
void net_accel_update_state(struct xenbus_device *dev, int state) { struct xenbus_transaction tr; int err; DPRINTK("%s: setting accelstate to %s\n", __FUNCTION__, xenbus_strstate(state)); if (xenbus_exists(XBT_NIL, dev->nodename, "")) { VPRINTK("%s: nodename %s\n", __FUNCTION__, dev->nodename); again: err = xenbus_transaction_start(&tr); if (err == 0) err = xenbus_printf(tr, dev->nodename, "accelstate", "%d", state); if (err != 0) { xenbus_transaction_end(tr, 1); } else { err = xenbus_transaction_end(tr, 0); if (err == -EAGAIN) goto again; } } }
static char * get_config(char *cmdline) { xenbus_transaction_t txn; char *cfg; int retry; cfg = rumprun_config_path(cmdline); if (cfg != NULL) return cfg; if (xenbus_transaction_start(&txn)) return jsonordie(); if (xenbus_read(txn, "rumprun/cfg", &cfg) != NULL) cfg = jsonordie(); xenbus_transaction_end(txn, 0, &retry); return cfg; }
char *xenbus_switch_state(xenbus_transaction_t xbt, const char* path, XenbusState state) { char *current_state; char *msg = NULL; char *msg2 = NULL; char value[2]; XenbusState rs; int xbt_flag = 0; int retry = 0; do { if (xbt == XBT_NIL) { msg = xenbus_transaction_start(&xbt); if (msg) goto exit; xbt_flag = 1; } msg = xenbus_read(xbt, path, ¤t_state); if (msg) goto exit; rs = (XenbusState) (current_state[0] - '0'); free(current_state); if (rs == state) { msg = NULL; goto exit; } snprintf(value, 2, "%d", state); msg = xenbus_write(xbt, path, value); exit: if (xbt_flag) { msg2 = xenbus_transaction_end(xbt, 0, &retry); xbt = XBT_NIL; } if (msg == NULL && msg2 != NULL) msg = msg2; } while (retry); return msg; }
NTSTATUS v2v_accept(struct v2v_channel *channel) { NTSTATUS status = STATUS_SUCCESS; xenbus_transaction_t xbt = {0}; enum v2v_endpoint_state remote_state; XM_ASSERT(channel != NULL); for (;;) { xenbus_transaction_start(&xbt); status = v2v_get_remote_state_internal(xbt, channel, &remote_state); switch (remote_state) { case v2v_state_unready: case v2v_state_disconnected: case v2v_state_crashed: xenbus_transaction_end(xbt, 1); KeWaitForSingleObject(&channel->control_event, Executive, KernelMode, FALSE, NULL); break; case v2v_state_listening: xenbus_transaction_end(xbt, 1); return STATUS_POSSIBLE_DEADLOCK; case v2v_state_disconnecting: xenbus_transaction_end(xbt, 1); return STATUS_VIRTUAL_CIRCUIT_CLOSED; case v2v_state_unknown: xenbus_transaction_end(xbt, 1); return status; /* return the error from get state call */ case v2v_state_connected: status = v2v_change_local_state(channel, xbt, v2v_state_connected); if (!NT_SUCCESS(status)) { xenbus_transaction_end(xbt, 1); return status; } status = xenbus_transaction_end(xbt, 0); if (NT_SUCCESS(status)) { channel->u.temple.accepted = TRUE; return STATUS_SUCCESS; } if (status != STATUS_RETRY) return status; break; /* try again */ } } }
struct kbdfront_dev *init_kbdfront(char *_nodename, int abs_pointer) { xenbus_transaction_t xbt; char* err; char* message=NULL; struct xenkbd_page *s; int retry=0; char* msg = NULL; char* nodename = _nodename ? _nodename : "device/vkbd/0"; struct kbdfront_dev *dev; char path[strlen(nodename) + strlen("/backend-id") + 1]; printk("******************* KBDFRONT for %s **********\n\n\n", nodename); dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); #ifdef HAVE_LIBC dev->fd = -1; #endif snprintf(path, sizeof(path), "%s/backend-id", nodename); dev->dom = xenbus_read_integer(path); evtchn_alloc_unbound(dev->dom, kbdfront_handler, dev, &dev->evtchn); dev->page = s = (struct xenkbd_page*) alloc_page(); memset(s,0,PAGE_SIZE); dev->events = NULL; s->in_cons = s->in_prod = 0; s->out_cons = s->out_prod = 0; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); free(err); } err = xenbus_printf(xbt, nodename, "page-ref","%lu", virt_to_mfn(s)); if (err) { message = "writing page-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } if (abs_pointer) { err = xenbus_printf(xbt, nodename, "request-abs-pointer", "1"); if (err) { message = "writing event-channel"; goto abort_transaction; } } snprintf(path, sizeof(path), "%s/state", nodename); err = xenbus_switch_state(xbt, path, XenbusStateInitialised); if (err) { printk("error writing initialized: %s\n", err); free(err); } err = xenbus_transaction_end(xbt, 0, &retry); free(err); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: free(err); err = xenbus_transaction_end(xbt, 1, &retry); printk("Abort transaction %s\n", message); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); if (msg) { printk("Error %s when reading the backend path %s\n", msg, path); goto error; } printk("backend at %s\n", dev->backend); { XenbusState state; char path[strlen(dev->backend) + strlen("/state") + 1]; char frontpath[strlen(nodename) + strlen("/state") + 1]; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); err = NULL; state = xenbus_read_integer(path); while (err == NULL && state < XenbusStateConnected) err = xenbus_wait_for_state_change(path, &state, &dev->events); if (state != XenbusStateConnected) { printk("backend not available, state=%d\n", state); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } printk("%s connected\n", dev->backend); snprintf(frontpath, sizeof(frontpath), "%s/state", nodename); if((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected)) != NULL) { printk("error switching state: %s\n", err); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } } unmask_evtchn(dev->evtchn); printk("************************** KBDFRONT\n"); return dev; error: free(msg); free(err); free_kbdfront(dev); return NULL; }
struct fbfront_dev *init_fbfront(char *_nodename, unsigned long *mfns, int width, int height, int depth, int stride, int n) { xenbus_transaction_t xbt; char* err; char* message=NULL; struct xenfb_page *s; int retry=0; char* msg=NULL; int i, j; struct fbfront_dev *dev; int max_pd; unsigned long mapped; char* nodename = _nodename ? _nodename : "device/vfb/0"; char path[strlen(nodename) + 1 + 10 + 1]; printk("******************* FBFRONT for %s **********\n\n\n", nodename); dev = malloc(sizeof(*dev)); memset(dev, 0, sizeof(*dev)); dev->nodename = strdup(nodename); #ifdef HAVE_LIBC dev->fd = -1; #endif snprintf(path, sizeof(path), "%s/backend-id", nodename); dev->dom = xenbus_read_integer(path); evtchn_alloc_unbound(dev->dom, fbfront_handler, dev, &dev->evtchn); dev->page = s = (struct xenfb_page*) alloc_page(); memset(s,0,PAGE_SIZE); s->in_cons = s->in_prod = 0; s->out_cons = s->out_prod = 0; dev->width = s->width = width; dev->height = s->height = height; dev->depth = s->depth = depth; dev->stride = s->line_length = stride; dev->mem_length = s->mem_length = n * PAGE_SIZE; dev->offset = 0; dev->events = NULL; max_pd = sizeof(s->pd) / sizeof(s->pd[0]); mapped = 0; for (i = 0; mapped < n && i < max_pd; i++) { unsigned long *pd = (unsigned long *) alloc_page(); for (j = 0; mapped < n && j < PAGE_SIZE / sizeof(unsigned long); j++) pd[j] = mfns[mapped++]; for ( ; j < PAGE_SIZE / sizeof(unsigned long); j++) pd[j] = 0; s->pd[i] = virt_to_mfn(pd); } for ( ; i < max_pd; i++) s->pd[i] = 0; again: err = xenbus_transaction_start(&xbt); if (err) { printk("starting transaction\n"); free(err); } err = xenbus_printf(xbt, nodename, "page-ref","%lu", virt_to_mfn(s)); if (err) { message = "writing page-ref"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "event-channel", "%u", dev->evtchn); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); if (err) { message = "writing event-channel"; goto abort_transaction; } err = xenbus_printf(xbt, nodename, "feature-update", "1"); if (err) { message = "writing event-channel"; goto abort_transaction; } snprintf(path, sizeof(path), "%s/state", nodename); err = xenbus_switch_state(xbt, path, XenbusStateInitialised); if (err) { message = "switching state"; goto abort_transaction; } err = xenbus_transaction_end(xbt, 0, &retry); free(err); if (retry) { goto again; printk("completing transaction\n"); } goto done; abort_transaction: free(err); err = xenbus_transaction_end(xbt, 1, &retry); printk("Abort transaction %s\n", message); goto error; done: snprintf(path, sizeof(path), "%s/backend", nodename); msg = xenbus_read(XBT_NIL, path, &dev->backend); if (msg) { printk("Error %s when reading the backend path %s\n", msg, path); goto error; } printk("backend at %s\n", dev->backend); { XenbusState state; char path[strlen(dev->backend) + strlen("/request-update") + 1]; char frontpath[strlen(nodename) + strlen("/state") + 1]; snprintf(path, sizeof(path), "%s/state", dev->backend); xenbus_watch_path_token(XBT_NIL, path, path, &dev->events); err = NULL; state = xenbus_read_integer(path); while (err == NULL && state < XenbusStateConnected) err = xenbus_wait_for_state_change(path, &state, &dev->events); if (state != XenbusStateConnected) { printk("backend not available, state=%d\n", state); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } printk("%s connected\n", dev->backend); snprintf(path, sizeof(path), "%s/request-update", dev->backend); dev->request_update = xenbus_read_integer(path); snprintf(frontpath, sizeof(frontpath), "%s/state", nodename); if ((err = xenbus_switch_state(XBT_NIL, frontpath, XenbusStateConnected)) != NULL) { printk("error switching state: %s\n", err); free(err); err = xenbus_unwatch_path_token(XBT_NIL, path, path); goto error; } } unmask_evtchn(dev->evtchn); printk("************************** FBFRONT\n"); return dev; error: free(msg); free(err); free_fbfront(dev); return NULL; }
/* caller must clean up in case of errors */ static int setup_ring(struct xenbus_device *dev, struct tpm_private *priv) { struct xenbus_transaction xbt; const char *message = NULL; int rv; grant_ref_t gref; priv->shr = (void *)__get_free_page(GFP_KERNEL|__GFP_ZERO); if (!priv->shr) { xenbus_dev_fatal(dev, -ENOMEM, "allocating shared ring"); return -ENOMEM; } rv = xenbus_grant_ring(dev, priv->shr, 1, &gref); if (rv < 0) return rv; priv->ring_ref = gref; rv = xenbus_alloc_evtchn(dev, &priv->evtchn); if (rv) return rv; rv = bind_evtchn_to_irqhandler(priv->evtchn, tpmif_interrupt, 0, "tpmif", priv); if (rv <= 0) { xenbus_dev_fatal(dev, rv, "allocating TPM irq"); return rv; } priv->irq = rv; again: rv = xenbus_transaction_start(&xbt); if (rv) { xenbus_dev_fatal(dev, rv, "starting transaction"); return rv; } rv = xenbus_printf(xbt, dev->nodename, "ring-ref", "%u", priv->ring_ref); if (rv) { message = "writing ring-ref"; goto abort_transaction; } rv = xenbus_printf(xbt, dev->nodename, "event-channel", "%u", priv->evtchn); if (rv) { message = "writing event-channel"; goto abort_transaction; } rv = xenbus_printf(xbt, dev->nodename, "feature-protocol-v2", "1"); if (rv) { message = "writing feature-protocol-v2"; goto abort_transaction; } rv = xenbus_transaction_end(xbt, 0); if (rv == -EAGAIN) goto again; if (rv) { xenbus_dev_fatal(dev, rv, "completing transaction"); return rv; } xenbus_switch_state(dev, XenbusStateInitialised); return 0; abort_transaction: xenbus_transaction_end(xbt, 1); if (message) xenbus_dev_error(dev, rv, "%s", message); return rv; }