summaryrefslogtreecommitdiffstats
path: root/sys/xen/xenbus
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-12-29 06:31:03 +0000
committerkmacy <kmacy@FreeBSD.org>2008-12-29 06:31:03 +0000
commit9198d09682e0ff9e4b99c1a500c60ec311f33516 (patch)
tree78f4ff4cfc0d598fd6e8ccc01fa628fc8ded089f /sys/xen/xenbus
parente46dfc4a1843e8da9da2fceed45ebc43d45d62b1 (diff)
downloadFreeBSD-src-9198d09682e0ff9e4b99c1a500c60ec311f33516.zip
FreeBSD-src-9198d09682e0ff9e4b99c1a500c60ec311f33516.tar.gz
merge 186535, 186537, and 186538 from releng_7_xen
Log: - merge in latest xenbus from dfr's xenhvm - fix race condition in xs_read_reply by converting tsleep to mtx_sleep Log: unmask evtchn in bind_{virq, ipi}_to_irq Log: - remove code for handling case of not being able to sleep - eliminate tsleep - make sleeps atomic
Diffstat (limited to 'sys/xen/xenbus')
-rw-r--r--sys/xen/xenbus/xenbus_client.c183
-rw-r--r--sys/xen/xenbus/xenbus_comms.c317
-rw-r--r--sys/xen/xenbus/xenbus_comms.h116
-rw-r--r--sys/xen/xenbus/xenbus_dev.c133
-rw-r--r--sys/xen/xenbus/xenbus_probe.c118
-rw-r--r--sys/xen/xenbus/xenbus_probe_backend.c5
-rw-r--r--sys/xen/xenbus/xenbus_xs.c1307
-rw-r--r--sys/xen/xenbus/xenbusvar.h65
8 files changed, 1057 insertions, 1187 deletions
diff --git a/sys/xen/xenbus/xenbus_client.c b/sys/xen/xenbus/xenbus_client.c
index d8a1a3f..740d664 100644
--- a/sys/xen/xenbus/xenbus_client.c
+++ b/sys/xen/xenbus/xenbus_client.c
@@ -44,19 +44,14 @@ __FBSDID("$FreeBSD$");
#include <sys/libkern.h>
#include <machine/xen/xen-os.h>
-#include <machine/xen/evtchn.h>
+#include <xen/hypervisor.h>
+#include <xen/evtchn.h>
#include <xen/gnttab.h>
#include <xen/xenbus/xenbusvar.h>
#include <machine/stdarg.h>
-
-#define EXPORT_SYMBOL(x)
-#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
-#define kfree(ptr) free(ptr, M_DEVBUF)
-#define BUG_ON PANIC_IF
-
-
-const char *xenbus_strstate(XenbusState state)
+const char *
+xenbus_strstate(XenbusState state)
{
static const char *const name[] = {
[ XenbusStateUnknown ] = "Unknown",
@@ -67,121 +62,108 @@ const char *xenbus_strstate(XenbusState state)
[ XenbusStateClosing ] = "Closing",
[ XenbusStateClosed ] = "Closed",
};
- return (state < (XenbusStateClosed + 1)) ? name[state] : "INVALID";
+
+ return ((state < (XenbusStateClosed + 1)) ? name[state] : "INVALID");
}
int
-xenbus_watch_path(device_t dev, char *path,
- struct xenbus_watch *watch,
- void (*callback)(struct xenbus_watch *,
- const char **, unsigned int))
+xenbus_watch_path(device_t dev, char *path, struct xenbus_watch *watch,
+ void (*callback)(struct xenbus_watch *, const char **, unsigned int))
{
- int err;
+ int error;
watch->node = path;
watch->callback = callback;
- err = register_xenbus_watch(watch);
+ error = register_xenbus_watch(watch);
- if (err) {
+ if (error) {
watch->node = NULL;
watch->callback = NULL;
- xenbus_dev_fatal(dev, err, "adding watch on %s", path);
+ xenbus_dev_fatal(dev, error, "adding watch on %s", path);
}
- return err;
+ return (error);
}
-EXPORT_SYMBOL(xenbus_watch_path);
-
-int xenbus_watch_path2(device_t dev, const char *path,
- const char *path2, struct xenbus_watch *watch,
- void (*callback)(struct xenbus_watch *,
- const char **, unsigned int))
+int
+xenbus_watch_path2(device_t dev, const char *path,
+ const char *path2, struct xenbus_watch *watch,
+ void (*callback)(struct xenbus_watch *, const char **, unsigned int))
{
- int err;
- char *state =
- kmalloc(strlen(path) + 1 + strlen(path2) + 1, GFP_KERNEL);
- if (!state) {
- xenbus_dev_fatal(dev, -ENOMEM, "allocating path for watch");
- return -ENOMEM;
- }
+ int error;
+ char *state = malloc(strlen(path) + 1 + strlen(path2) + 1,
+ M_DEVBUF, M_WAITOK);
+
strcpy(state, path);
strcat(state, "/");
strcat(state, path2);
- err = xenbus_watch_path(dev, state, watch, callback);
-
- if (err) {
- kfree(state);
+ error = xenbus_watch_path(dev, state, watch, callback);
+ if (error) {
+ free(state, M_DEVBUF);
}
- return err;
+
+ return (error);
}
-EXPORT_SYMBOL(xenbus_watch_path2);
/**
* Return the path to the error node for the given device, or NULL on failure.
* If the value returned is non-NULL, then it is the caller's to kfree.
*/
-static char *error_path(device_t dev)
+static char *
+error_path(device_t dev)
{
- char *path_buffer = kmalloc(strlen("error/")
- + strlen(xenbus_get_node(dev)) +
- 1, GFP_KERNEL);
- if (path_buffer == NULL) {
- return NULL;
- }
+ char *path_buffer = malloc(strlen("error/")
+ + strlen(xenbus_get_node(dev)) + 1, M_DEVBUF, M_WAITOK);
strcpy(path_buffer, "error/");
strcpy(path_buffer + strlen("error/"), xenbus_get_node(dev));
- return path_buffer;
+ return (path_buffer);
}
-static void _dev_error(device_t dev, int err, const char *fmt,
- va_list ap)
+static void
+_dev_error(device_t dev, int err, const char *fmt, va_list ap)
{
int ret;
unsigned int len;
char *printf_buffer = NULL, *path_buffer = NULL;
#define PRINTF_BUFFER_SIZE 4096
- printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
- if (printf_buffer == NULL)
- goto fail;
+ printf_buffer = malloc(PRINTF_BUFFER_SIZE, M_DEVBUF, M_WAITOK);
- len = sprintf(printf_buffer, "%i ", -err);
+ len = sprintf(printf_buffer, "%i ", err);
ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
- BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
+ KASSERT(len + ret <= PRINTF_BUFFER_SIZE-1, ("xenbus error message too big"));
#if 0
dev_err(&dev->dev, "%s\n", printf_buffer);
#endif
path_buffer = error_path(dev);
if (path_buffer == NULL) {
- printk("xenbus: failed to write error node for %s (%s)\n",
+ printf("xenbus: failed to write error node for %s (%s)\n",
xenbus_get_node(dev), printf_buffer);
goto fail;
}
if (xenbus_write(XBT_NIL, path_buffer, "error", printf_buffer) != 0) {
- printk("xenbus: failed to write error node for %s (%s)\n",
+ printf("xenbus: failed to write error node for %s (%s)\n",
xenbus_get_node(dev), printf_buffer);
goto fail;
}
fail:
if (printf_buffer)
- kfree(printf_buffer);
+ free(printf_buffer, M_DEVBUF);
if (path_buffer)
- kfree(path_buffer);
+ free(path_buffer, M_DEVBUF);
}
-
-void xenbus_dev_error(device_t dev, int err, const char *fmt,
- ...)
+void
+xenbus_dev_error(device_t dev, int err, const char *fmt, ...)
{
va_list ap;
@@ -189,11 +171,9 @@ void xenbus_dev_error(device_t dev, int err, const char *fmt,
_dev_error(dev, err, fmt, ap);
va_end(ap);
}
-EXPORT_SYMBOL(xenbus_dev_error);
-
-void xenbus_dev_fatal(device_t dev, int err, const char *fmt,
- ...)
+void
+xenbus_dev_fatal(device_t dev, int err, const char *fmt, ...)
{
va_list ap;
@@ -203,21 +183,26 @@ void xenbus_dev_fatal(device_t dev, int err, const char *fmt,
xenbus_set_state(dev, XenbusStateClosing);
}
-EXPORT_SYMBOL(xenbus_dev_fatal);
-
-int xenbus_grant_ring(device_t dev, unsigned long ring_mfn)
+int
+xenbus_grant_ring(device_t dev, unsigned long ring_mfn, int *refp)
{
- int err = gnttab_grant_foreign_access(
- xenbus_get_otherend_id(dev), ring_mfn, 0);
- if (err < 0)
- xenbus_dev_fatal(dev, err, "granting access to ring page");
- return err;
-}
-EXPORT_SYMBOL(xenbus_grant_ring);
+ int error;
+ grant_ref_t ref;
+
+ error = gnttab_grant_foreign_access(
+ xenbus_get_otherend_id(dev), ring_mfn, 0, &ref);
+ if (error) {
+ xenbus_dev_fatal(dev, error, "granting access to ring page");
+ return (error);
+ }
+ *refp = ref;
+ return (0);
+}
-int xenbus_alloc_evtchn(device_t dev, int *port)
+int
+xenbus_alloc_evtchn(device_t dev, int *port)
{
struct evtchn_alloc_unbound alloc_unbound;
int err;
@@ -228,16 +213,16 @@ int xenbus_alloc_evtchn(device_t dev, int *port)
err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound,
&alloc_unbound);
- if (err)
- xenbus_dev_fatal(dev, err, "allocating event channel");
- else
- *port = alloc_unbound.port;
- return err;
+ if (err) {
+ xenbus_dev_fatal(dev, -err, "allocating event channel");
+ return (-err);
+ }
+ *port = alloc_unbound.port;
+ return (0);
}
-EXPORT_SYMBOL(xenbus_alloc_evtchn);
-
-int xenbus_free_evtchn(device_t dev, int port)
+int
+xenbus_free_evtchn(device_t dev, int port)
{
struct evtchn_close close;
int err;
@@ -245,32 +230,22 @@ int xenbus_free_evtchn(device_t dev, int port)
close.port = port;
err = HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
- if (err)
- xenbus_dev_error(dev, err, "freeing event channel %d", port);
- return err;
+ if (err) {
+ xenbus_dev_error(dev, -err, "freeing event channel %d", port);
+ return (-err);
+ }
+ return (0);
}
-EXPORT_SYMBOL(xenbus_free_evtchn);
-
-XenbusState xenbus_read_driver_state(const char *path)
+XenbusState
+xenbus_read_driver_state(const char *path)
{
XenbusState result;
+ int error;
- int err = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
- if (err)
+ error = xenbus_gather(XBT_NIL, path, "state", "%d", &result, NULL);
+ if (error)
result = XenbusStateClosed;
- return result;
+ return (result);
}
-EXPORT_SYMBOL(xenbus_read_driver_state);
-
-
-/*
- * Local variables:
- * c-file-style: "linux"
- * indent-tabs-mode: t
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- */
diff --git a/sys/xen/xenbus/xenbus_comms.c b/sys/xen/xenbus/xenbus_comms.c
index 90f0ea9..2f03955 100644
--- a/sys/xen/xenbus/xenbus_comms.c
+++ b/sys/xen/xenbus/xenbus_comms.c
@@ -33,217 +33,194 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/bus.h>
-#include <sys/time.h>
-#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/syslog.h>
-#include <sys/proc.h>
-#include <sys/kernel.h>
#include <machine/xen/xen-os.h>
-#include <machine/xen/hypervisor.h>
-#include <machine/xen/evtchn.h>
-#include <machine/xen/xen_intr.h>
-#include <xen/xenbus/xenbus_comms.h>
-#include <xen/interface/io/xs_wire.h>
+#include <xen/hypervisor.h>
-static int xenbus_irq;
+#include <xen/xen_intr.h>
+#include <xen/evtchn.h>
+#include <xen/interface/io/xs_wire.h>
+#include <xen/xenbus/xenbus_comms.h>
-extern void xenbus_probe(void *);
-extern int xenstored_ready;
-#if 0
-static DECLARE_WORK(probe_work, xenbus_probe, NULL);
-#endif
-int xb_wait;
-extern char *xen_store;
-#define wake_up wakeup
-#define xb_waitq xb_wait
-#define pr_debug(a,b,c)
+static unsigned int xenstore_irq;
-static inline struct xenstore_domain_interface *xenstore_domain_interface(void)
+static inline struct xenstore_domain_interface *
+xenstore_domain_interface(void)
{
- return (struct xenstore_domain_interface *)xen_store;
+
+ return (struct xenstore_domain_interface *)xen_store;
}
static void
-wake_waiting(void * arg __attribute__((unused)))
+xb_intr(void * arg __attribute__((unused)))
{
-#if 0
- if (unlikely(xenstored_ready == 0)) {
- xenstored_ready = 1;
- schedule_work(&probe_work);
- }
-#endif
- wakeup(&xb_wait);
-}
-static int check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
-{
- return ((prod - cons) <= XENSTORE_RING_SIZE);
+ wakeup(xen_store);
}
-static void *get_output_chunk(XENSTORE_RING_IDX cons,
- XENSTORE_RING_IDX prod,
- char *buf, uint32_t *len)
+static int
+xb_check_indexes(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod)
{
- *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
- if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
- *len = XENSTORE_RING_SIZE - (prod - cons);
- return buf + MASK_XENSTORE_IDX(prod);
-}
-static const void *get_input_chunk(XENSTORE_RING_IDX cons,
- XENSTORE_RING_IDX prod,
- const char *buf, uint32_t *len)
-{
- *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
- if ((prod - cons) < *len)
- *len = prod - cons;
- return buf + MASK_XENSTORE_IDX(cons);
+ return ((prod - cons) <= XENSTORE_RING_SIZE);
}
-int xb_write(const void *tdata, unsigned len)
+static void *
+xb_get_output_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod,
+ char *buf, uint32_t *len)
{
- struct xenstore_domain_interface *intf = xenstore_domain_interface();
- XENSTORE_RING_IDX cons, prod;
- const char *data = (const char *)tdata;
-
- while (len != 0) {
- void *dst;
- unsigned int avail;
-
- wait_event_interruptible(&xb_waitq,
- (intf->req_prod - intf->req_cons) !=
- XENSTORE_RING_SIZE);
-
- /* Read indexes, then verify. */
- cons = intf->req_cons;
- prod = intf->req_prod;
- mb();
- if (!check_indexes(cons, prod)) {
- intf->req_cons = intf->req_prod = 0;
- return -EIO;
- }
-
- dst = get_output_chunk(cons, prod, intf->req, &avail);
- if (avail == 0)
- continue;
- if (avail > len)
- avail = len;
- mb();
-
- memcpy(dst, data, avail);
- data += avail;
- len -= avail;
-
- /* Other side must not see new header until data is there. */
- wmb();
- intf->req_prod += avail;
- /* This implies mb() before other side sees interrupt. */
- notify_remote_via_evtchn(xen_start_info->store_evtchn);
- }
-
- return 0;
+ *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod);
+ if ((XENSTORE_RING_SIZE - (prod - cons)) < *len)
+ *len = XENSTORE_RING_SIZE - (prod - cons);
+ return (buf + MASK_XENSTORE_IDX(prod));
}
-#ifdef notyet
-int xb_data_to_read(void)
+static const void *
+xb_get_input_chunk(XENSTORE_RING_IDX cons, XENSTORE_RING_IDX prod,
+ const char *buf, uint32_t *len)
{
- struct xenstore_domain_interface *intf = xen_store_interface;
- return (intf->rsp_cons != intf->rsp_prod);
-}
-int xb_wait_for_data_to_read(void)
-{
- return wait_event_interruptible(xb_waitq, xb_data_to_read());
+ *len = XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(cons);
+ if ((prod - cons) < *len)
+ *len = prod - cons;
+ return (buf + MASK_XENSTORE_IDX(cons));
}
-#endif
-
-int xb_read(void *tdata, unsigned len)
+int
+xb_write(const void *tdata, unsigned len, struct lock_object *lock)
{
- struct xenstore_domain_interface *intf = xenstore_domain_interface();
- XENSTORE_RING_IDX cons, prod;
- char *data = (char *)tdata;
-
- while (len != 0) {
- unsigned int avail;
- const char *src;
-
- wait_event_interruptible(&xb_waitq,
- intf->rsp_cons != intf->rsp_prod);
-
- /* Read indexes, then verify. */
- cons = intf->rsp_cons;
- prod = intf->rsp_prod;
- if (!check_indexes(cons, prod)) {
- intf->rsp_cons = intf->rsp_prod = 0;
- return -EIO;
- }
-
- src = get_input_chunk(cons, prod, intf->rsp, &avail);
- if (avail == 0)
- continue;
- if (avail > len)
- avail = len;
-
- /* We must read header before we read data. */
- rmb();
+ struct xenstore_domain_interface *intf = xenstore_domain_interface();
+ XENSTORE_RING_IDX cons, prod;
+ const char *data = (const char *)tdata;
+ int error;
+
+ while (len != 0) {
+ void *dst;
+ unsigned int avail;
+
+ while ((intf->req_prod - intf->req_cons)
+ == XENSTORE_RING_SIZE) {
+ error = _sleep(intf,
+ lock,
+ PCATCH, "xbwrite", hz/10);
+ if (error && error != EWOULDBLOCK)
+ return (error);
+ }
- memcpy(data, src, avail);
- data += avail;
- len -= avail;
+ /* Read indexes, then verify. */
+ cons = intf->req_cons;
+ prod = intf->req_prod;
+ mb();
+ if (!xb_check_indexes(cons, prod)) {
+ intf->req_cons = intf->req_prod = 0;
+ return (EIO);
+ }
- /* Other side must not see free space until we've copied out */
- mb();
- intf->rsp_cons += avail;
+ dst = xb_get_output_chunk(cons, prod, intf->req, &avail);
+ if (avail == 0)
+ continue;
+ if (avail > len)
+ avail = len;
+ mb();
+
+ memcpy(dst, data, avail);
+ data += avail;
+ len -= avail;
- pr_debug("Finished read of %i bytes (%i to go)\n", avail, len);
+ /* Other side must not see new header until data is there. */
+ wmb();
+ intf->req_prod += avail;
- /* Implies mb(): they will see new header. */
- notify_remote_via_evtchn(xen_start_info->store_evtchn);
- }
+ /* This implies mb() before other side sees interrupt. */
+ notify_remote_via_evtchn(xen_store_evtchn);
+ }
- return 0;
+ return (0);
}
-/* Set up interrupt handler off store event channel. */
-int xb_init_comms(void)
+int
+xb_read(void *tdata, unsigned len, struct lock_object *lock)
{
- struct xenstore_domain_interface *intf = xenstore_domain_interface();
- int err;
-
- if (intf->rsp_prod != intf->rsp_cons) {
- log(LOG_WARNING, "XENBUS response ring is not quiescent "
- "(%08x:%08x): fixing up\n",
- intf->rsp_cons, intf->rsp_prod);
- intf->rsp_cons = intf->rsp_prod;
+ struct xenstore_domain_interface *intf = xenstore_domain_interface();
+ XENSTORE_RING_IDX cons, prod;
+ char *data = (char *)tdata;
+ int error;
+
+ while (len != 0) {
+ unsigned int avail;
+ const char *src;
+
+ while (intf->rsp_cons == intf->rsp_prod) {
+ error = _sleep(intf, lock,
+ PCATCH, "xbread", hz/10);
+ if (error && error != EWOULDBLOCK)
+ return (error);
}
+
+ /* Read indexes, then verify. */
+ cons = intf->rsp_cons;
+ prod = intf->rsp_prod;
+ if (!xb_check_indexes(cons, prod)) {
+ intf->rsp_cons = intf->rsp_prod = 0;
+ return (EIO);
+ }
+
+ src = xb_get_input_chunk(cons, prod, intf->rsp, &avail);
+ if (avail == 0)
+ continue;
+ if (avail > len)
+ avail = len;
- if (xenbus_irq)
- unbind_from_irqhandler(xenbus_irq, &xb_waitq);
+ /* We must read header before we read data. */
+ rmb();
- err = bind_caller_port_to_irqhandler(
- xen_start_info->store_evtchn,
- "xenbus", wake_waiting, NULL, INTR_TYPE_NET, NULL);
- if (err <= 0) {
- log(LOG_WARNING, "XENBUS request irq failed %i\n", err);
- return err;
- }
+ memcpy(data, src, avail);
+ data += avail;
+ len -= avail;
+
+ /* Other side must not see free space until we've copied out */
+ mb();
+ intf->rsp_cons += avail;
- xenbus_irq = err;
+ /* Implies mb(): they will see new header. */
+ notify_remote_via_evtchn(xen_store_evtchn);
+ }
- return 0;
+ return (0);
}
-/*
- * Local variables:
- * c-file-style: "bsd"
- * indent-tabs-mode: t
- * c-indent-level: 4
- * c-basic-offset: 8
- * tab-width: 4
- * End:
- */
+/* Set up interrupt handler off store event channel. */
+int
+xb_init_comms(void)
+{
+ struct xenstore_domain_interface *intf = xenstore_domain_interface();
+ int error;
+
+ if (intf->rsp_prod != intf->rsp_cons) {
+ log(LOG_WARNING, "XENBUS response ring is not quiescent "
+ "(%08x:%08x): fixing up\n",
+ intf->rsp_cons, intf->rsp_prod);
+ intf->rsp_cons = intf->rsp_prod;
+ }
+
+ if (xenstore_irq)
+ unbind_from_irqhandler(xenstore_irq);
+
+ error = bind_caller_port_to_irqhandler(
+ xen_store_evtchn, "xenbus",
+ xb_intr, NULL, INTR_TYPE_NET, &xenstore_irq);
+ if (error) {
+ log(LOG_WARNING, "XENBUS request irq failed %i\n", error);
+ return (error);
+ }
+
+ return (0);
+}
diff --git a/sys/xen/xenbus/xenbus_comms.h b/sys/xen/xenbus/xenbus_comms.h
index 94a57dc..fa47331 100644
--- a/sys/xen/xenbus/xenbus_comms.h
+++ b/sys/xen/xenbus/xenbus_comms.h
@@ -30,123 +30,19 @@
#ifndef _XENBUS_COMMS_H
#define _XENBUS_COMMS_H
+struct sx;
+extern int xen_store_evtchn;
+extern char *xen_store;
+
int xs_init(void);
int xb_init_comms(void);
/* Low level routines. */
-int xb_write(const void *data, unsigned len);
-int xb_read(void *data, unsigned len);
-int xs_input_avail(void);
-extern int xb_waitq;
+int xb_write(const void *data, unsigned len, struct lock_object *);
+int xb_read(void *data, unsigned len, struct lock_object *);
extern int xenbus_running;
-#define __wait_event_interruptible(wchan, condition, ret) \
-do { \
- for (;;) { \
- if (xenbus_running == 0) { \
- break; \
- } \
- if (condition) \
- break; \
- if ((ret = !tsleep(wchan, PWAIT | PCATCH, "waitev", hz/10))) \
- break; \
- } \
-} while (0)
-
-
-#define wait_event_interruptible(wchan, condition) \
-({ \
- int __ret = 0; \
- if (!(condition)) \
- __wait_event_interruptible(wchan, condition, __ret); \
- __ret; \
-})
-
-
-
-#define DECLARE_MUTEX(lock) struct sema lock
-#define semaphore sema
-#define rw_semaphore sema
-
-#define down sema_wait
-#define up sema_post
-#define down_read sema_wait
-#define up_read sema_post
-#define down_write sema_wait
-#define up_write sema_post
-
-/**
- * container_of - cast a member of a structure out to the containing structure
- *
- * @ptr: the pointer to the member.
- * @type: the type of the container struct this is embedded in.
- * @member: the name of the member within the struct.
- *
- */
-#define container_of(ptr, type, member) ({ \
- __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
- (type *)( (char *)__mptr - offsetof(type,member) );})
-
-
-/*
- * XXX
- *
- */
-
-#define GFP_KERNEL 1
-#define EXPORT_SYMBOL(x)
-#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
-#define kfree(ptr) free((void *)(uintptr_t)ptr, M_DEVBUF)
-#define BUG_ON PANIC_IF
-#define semaphore sema
-#define rw_semaphore sema
-#define DEFINE_SPINLOCK(lock) struct mtx lock
-#define DECLARE_MUTEX(lock) struct sema lock
-#define u32 uint32_t
-#define list_del(head, ent) TAILQ_REMOVE(head, ent, list)
-#define simple_strtoul strtoul
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
-#define list_empty TAILQ_EMPTY
-#define wake_up wakeup
-#define BUS_ID_SIZE 128
-
-struct xen_bus_type
-{
- char *root;
- unsigned int levels;
- int (*get_bus_id)(char bus_id[BUS_ID_SIZE], const char *nodename);
- int (*probe)(const char *type, const char *dir);
- struct xendev_list_head *bus;
- int error;
-#if 0
- struct bus_type bus;
- struct device dev;
-#endif
-};
-
-
-#if 0
-
-void dev_changed(const char *node, struct xen_bus_type *bus);
-
-int
-read_otherend_details(struct xenbus_device *xendev, char *id_node,
- char *path_node);
-#endif
-
char *kasprintf(const char *fmt, ...);
-
-
#endif /* _XENBUS_COMMS_H */
-
-/*
- * Local variables:
- * c-file-style: "linux"
- * indent-tabs-mode: t
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- */
diff --git a/sys/xen/xenbus/xenbus_dev.c b/sys/xen/xenbus/xenbus_dev.c
index 52e0b67..ac3f103 100644
--- a/sys/xen/xenbus/xenbus_dev.c
+++ b/sys/xen/xenbus/xenbus_dev.c
@@ -45,19 +45,10 @@ __FBSDID("$FreeBSD$");
#include <sys/conf.h>
#include <machine/xen/xen-os.h>
-#include <machine/xen/hypervisor.h>
+#include <xen/hypervisor.h>
#include <xen/xenbus/xenbusvar.h>
#include <xen/xenbus/xenbus_comms.h>
-#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
-#define BUG_ON PANIC_IF
-#define semaphore sema
-#define rw_semaphore sema
-#define DEFINE_SPINLOCK(lock) struct mtx lock
-#define DECLARE_MUTEX(lock) struct sema lock
-#define u32 uint32_t
-#define simple_strtoul strtoul
-
struct xenbus_dev_transaction {
LIST_ENTRY(xenbus_dev_transaction) list;
struct xenbus_transaction handle;
@@ -78,62 +69,65 @@ struct xenbus_dev_data {
#define MASK_READ_IDX(idx) ((idx)&(PAGE_SIZE-1))
char read_buffer[PAGE_SIZE];
unsigned int read_cons, read_prod;
- int read_waitq;
};
-#if 0
-static struct proc_dir_entry *xenbus_dev_intf;
-#endif
+
static int
xenbus_dev_read(struct cdev *dev, struct uio *uio, int ioflag)
{
- int i = 0;
+ int error;
struct xenbus_dev_data *u = dev->si_drv1;
- if (wait_event_interruptible(&u->read_waitq,
- u->read_prod != u->read_cons))
- return EINTR;
+ while (u->read_prod == u->read_cons) {
+ error = tsleep(u, PCATCH, "xbdread", hz/10);
+ if (error && error != EWOULDBLOCK)
+ return (error);
+ }
- for (i = 0; i < uio->uio_iov[0].iov_len; i++) {
+ while (uio->uio_resid > 0) {
if (u->read_cons == u->read_prod)
break;
- copyout(&u->read_buffer[MASK_READ_IDX(u->read_cons)], (char *)uio->uio_iov[0].iov_base+i, 1);
+ error = uiomove(&u->read_buffer[MASK_READ_IDX(u->read_cons)],
+ 1, uio);
+ if (error)
+ return (error);
u->read_cons++;
- uio->uio_resid--;
}
- return 0;
+ return (0);
}
-static void queue_reply(struct xenbus_dev_data *u,
- char *data, unsigned int len)
+static void
+queue_reply(struct xenbus_dev_data *u, char *data, unsigned int len)
{
int i;
for (i = 0; i < len; i++, u->read_prod++)
u->read_buffer[MASK_READ_IDX(u->read_prod)] = data[i];
- BUG_ON((u->read_prod - u->read_cons) > sizeof(u->read_buffer));
+ KASSERT((u->read_prod - u->read_cons) <= sizeof(u->read_buffer),
+ ("xenstore reply too big"));
- wakeup(&u->read_waitq);
+ wakeup(u);
}
static int
xenbus_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
{
- int err = 0;
+ int error;
struct xenbus_dev_data *u = dev->si_drv1;
struct xenbus_dev_transaction *trans;
void *reply;
- int len = uio->uio_iov[0].iov_len;
+ int len = uio->uio_resid;
if ((len + u->len) > sizeof(u->u.buffer))
- return EINVAL;
+ return (EINVAL);
- if (copyin(u->u.buffer + u->len, uio->uio_iov[0].iov_base, len) != 0)
- return EFAULT;
+ error = uiomove(u->u.buffer + u->len, len, uio);
+ if (error)
+ return (error);
u->len += len;
if (u->len < (sizeof(u->u.msg) + u->u.msg.len))
- return len;
+ return (0);
switch (u->u.msg.type) {
case XS_TRANSACTION_START:
@@ -147,67 +141,59 @@ xenbus_dev_write(struct cdev *dev, struct uio *uio, int ioflag)
case XS_MKDIR:
case XS_RM:
case XS_SET_PERMS:
- reply = xenbus_dev_request_and_reply(&u->u.msg);
- if (IS_ERR(reply)) {
- err = PTR_ERR(reply);
- } else {
+ error = xenbus_dev_request_and_reply(&u->u.msg, &reply);
+ if (!error) {
if (u->u.msg.type == XS_TRANSACTION_START) {
- trans = kmalloc(sizeof(*trans), GFP_KERNEL);
- trans->handle.id = simple_strtoul(reply, NULL, 0);
+ trans = malloc(sizeof(*trans), M_DEVBUF,
+ M_WAITOK);
+ trans->handle.id = strtoul(reply, NULL, 0);
LIST_INSERT_HEAD(&u->transactions, trans, list);
} else if (u->u.msg.type == XS_TRANSACTION_END) {
- LIST_FOREACH(trans, &u->transactions,
- list)
- if (trans->handle.id ==
- u->u.msg.tx_id)
+ LIST_FOREACH(trans, &u->transactions, list)
+ if (trans->handle.id == u->u.msg.tx_id)
break;
#if 0 /* XXX does this mean the list is empty? */
BUG_ON(&trans->list == &u->transactions);
#endif
LIST_REMOVE(trans, list);
- kfree(trans);
+ free(trans, M_DEVBUF);
}
queue_reply(u, (char *)&u->u.msg, sizeof(u->u.msg));
queue_reply(u, (char *)reply, u->u.msg.len);
- kfree(reply);
+ free(reply, M_DEVBUF);
}
break;
default:
- err = EINVAL;
+ error = EINVAL;
break;
}
- if (err == 0) {
+ if (error == 0)
u->len = 0;
- err = len;
- }
- return err;
+ return (error);
}
-static int xenbus_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
+static int
+xenbus_dev_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
{
struct xenbus_dev_data *u;
- if (xen_start_info->store_evtchn == 0)
- return ENOENT;
+ if (xen_store_evtchn == 0)
+ return (ENOENT);
#if 0 /* XXX figure out if equiv needed */
nonseekable_open(inode, filp);
#endif
- u = kmalloc(sizeof(*u), GFP_KERNEL);
- if (u == NULL)
- return ENOMEM;
-
- memset(u, 0, sizeof(*u));
+ u = malloc(sizeof(*u), M_DEVBUF, M_WAITOK|M_ZERO);
LIST_INIT(&u->transactions);
-
dev->si_drv1 = u;
- return 0;
+ return (0);
}
-static int xenbus_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
+static int
+xenbus_dev_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
{
struct xenbus_dev_data *u = dev->si_drv1;
struct xenbus_dev_transaction *trans, *tmp;
@@ -215,11 +201,11 @@ static int xenbus_dev_close(struct cdev *dev, int fflag, int devtype, struct thr
LIST_FOREACH_SAFE(trans, &u->transactions, list, tmp) {
xenbus_transaction_end(trans->handle, 1);
LIST_REMOVE(trans, list);
- kfree(trans);
+ free(trans, M_DEVBUF);
}
- kfree(u);
- return 0;
+ free(u, M_DEVBUF);
+ return (0);
}
static struct cdevsw xenbus_dev_cdevsw = {
@@ -234,21 +220,10 @@ static struct cdevsw xenbus_dev_cdevsw = {
static int
xenbus_dev_sysinit(void)
{
- make_dev(&xenbus_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400, "xenbus");
+ make_dev(&xenbus_dev_cdevsw, 0, UID_ROOT, GID_WHEEL, 0400,
+ "xen/xenbus");
- return 0;
+ return (0);
}
-SYSINIT(xenbus_dev_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, xenbus_dev_sysinit, NULL);
-/* SYSINIT NEEDED XXX */
-
-
-
-/*
- * Local variables:
- * c-file-style: "linux"
- * indent-tabs-mode: t
- * c-indent-level: 8
- * c-basic-offset: 8
- * tab-width: 8
- * End:
- */
+SYSINIT(xenbus_dev_sysinit, SI_SUB_DRIVERS, SI_ORDER_MIDDLE,
+ xenbus_dev_sysinit, NULL);
diff --git a/sys/xen/xenbus/xenbus_probe.c b/sys/xen/xenbus/xenbus_probe.c
index e57e6e3..3d2cb4b 100644
--- a/sys/xen/xenbus/xenbus_probe.c
+++ b/sys/xen/xenbus/xenbus_probe.c
@@ -88,9 +88,7 @@ kasprintf(const char *fmt, ...)
len = vsnprintf(dummy, 0, fmt, ap);
va_end(ap);
- p = kmalloc(len + 1, GFP_KERNEL);
- if (!p)
- return NULL;
+ p = malloc(len + 1, M_DEVBUF, M_WAITOK);
va_start(ap, fmt);
vsprintf(p, fmt, ap);
va_end(ap);
@@ -187,6 +185,7 @@ xenbus_add_device(device_t dev, const char *bus,
struct xenbus_device_ivars *ivars;
enum xenbus_state state;
char *statepath;
+ int error;
ivars = malloc(sizeof(struct xenbus_device_ivars),
M_DEVBUF, M_ZERO|M_WAITOK);
@@ -217,17 +216,19 @@ xenbus_add_device(device_t dev, const char *bus,
/*
* Find the backend details
*/
- xenbus_gather(XBT_NIL, ivars->xd_node,
+ error = xenbus_gather(XBT_NIL, ivars->xd_node,
"backend-id", "%i", &ivars->xd_otherend_id,
"backend", NULL, &ivars->xd_otherend_path,
NULL);
+ if (error)
+ return (error);
sx_init(&ivars->xd_lock, "xdlock");
ivars->xd_type = strdup(type, M_DEVBUF);
ivars->xd_state = XenbusStateInitialising;
statepath = malloc(strlen(ivars->xd_otherend_path)
- + strlen("/state") + 1, M_DEVBUF, M_NOWAIT);
+ + strlen("/state") + 1, M_DEVBUF, M_WAITOK);
sprintf(statepath, "%s/state", ivars->xd_otherend_path);
ivars->xd_otherend_watch.node = statepath;
@@ -245,10 +246,11 @@ xenbus_enumerate_type(device_t dev, const char *bus, const char *type)
{
char **dir;
unsigned int i, count;
+ int error;
- dir = xenbus_directory(XBT_NIL, bus, type, &count);
- if (IS_ERR(dir))
- return (EINVAL);
+ error = xenbus_directory(XBT_NIL, bus, type, &count, &dir);
+ if (error)
+ return (error);
for (i = 0; i < count; i++)
xenbus_add_device(dev, bus, type, dir[i]);
@@ -262,10 +264,11 @@ xenbus_enumerate_bus(device_t dev, const char *bus)
{
char **dir;
unsigned int i, count;
+ int error;
- dir = xenbus_directory(XBT_NIL, bus, "", &count);
- if (IS_ERR(dir))
- return (EINVAL);
+ error = xenbus_directory(XBT_NIL, bus, "", &count, &dir);
+ if (error)
+ return (error);
for (i = 0; i < count; i++) {
xenbus_enumerate_type(dev, bus, dir[i]);
}
@@ -386,28 +389,90 @@ xenbus_attach(device_t dev)
return (0);
}
-static void
+static int
xenbus_suspend(device_t dev)
{
+ int error;
+
DPRINTK("");
- panic("implement me");
-#if 0
- bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
- bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
-#endif
+
+ error = bus_generic_suspend(dev);
+ if (error)
+ return (error);
+
xs_suspend();
+
+ return (0);
}
-static void
+static int
xenbus_resume(device_t dev)
{
+ device_t *kids;
+ struct xenbus_device_ivars *ivars;
+ int i, count, error;
+ char *statepath;
+
xb_init_comms();
xs_resume();
- panic("implement me");
+
+ /*
+ * We must re-examine each device and find the new path for
+ * its backend.
+ */
+ if (device_get_children(dev, &kids, &count) == 0) {
+ for (i = 0; i < count; i++) {
+ if (device_get_state(kids[i]) == DS_NOTPRESENT)
+ continue;
+
+ ivars = device_get_ivars(kids[i]);
+
+ unregister_xenbus_watch(
+ &ivars->xd_otherend_watch);
+ ivars->xd_state = XenbusStateInitialising;
+
+ /*
+ * Find the new backend details and
+ * re-register our watch.
+ */
+ free(ivars->xd_otherend_path, M_DEVBUF);
+ error = xenbus_gather(XBT_NIL, ivars->xd_node,
+ "backend-id", "%i", &ivars->xd_otherend_id,
+ "backend", NULL, &ivars->xd_otherend_path,
+ NULL);
+ if (error)
+ return (error);
+
+ DEVICE_RESUME(kids[i]);
+
+ statepath = malloc(strlen(ivars->xd_otherend_path)
+ + strlen("/state") + 1, M_DEVBUF, M_WAITOK);
+ sprintf(statepath, "%s/state", ivars->xd_otherend_path);
+
+ free(ivars->xd_otherend_watch.node, M_DEVBUF);
+ ivars->xd_otherend_watch.node = statepath;
+ register_xenbus_watch(
+ &ivars->xd_otherend_watch);
+
#if 0
- bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
- bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
-#endif
+ /*
+ * Can't do this yet since we are running in
+ * the xenwatch thread and if we sleep here,
+ * we will stop delivering watch notifications
+ * and the device will never come back online.
+ */
+ sx_xlock(&ivars->xd_lock);
+ while (ivars->xd_state != XenbusStateClosed
+ && ivars->xd_state != XenbusStateConnected)
+ sx_sleep(&ivars->xd_state, &ivars->xd_lock,
+ 0, "xdresume", 0);
+ sx_xunlock(&ivars->xd_lock);
+#endif
+ }
+ free(kids, M_TEMP);
+ }
+
+ return (0);
}
static int
@@ -433,9 +498,11 @@ xenbus_read_ivar(device_t dev, device_t child, int index,
case XENBUS_IVAR_NODE:
*result = (uintptr_t) ivars->xd_node;
return (0);
+
case XENBUS_IVAR_TYPE:
*result = (uintptr_t) ivars->xd_type;
return (0);
+
case XENBUS_IVAR_STATE:
*result = (uintptr_t) ivars->xd_state;
return (0);
@@ -468,8 +535,8 @@ xenbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
goto out;
error = xenbus_scanf(XBT_NIL, ivars->xd_node, "state",
- "%d", &currstate);
- if (error < 0)
+ NULL, "%d", &currstate);
+ if (error)
goto out;
error = xenbus_printf(XBT_NIL, ivars->xd_node, "state",
@@ -494,15 +561,14 @@ xenbus_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
*/
return (EINVAL);
}
+
return (ENOENT);
}
SYSCTL_DECL(_dev);
SYSCTL_NODE(_dev, OID_AUTO, xen, CTLFLAG_RD, NULL, "Xen");
-#if 0
SYSCTL_INT(_dev_xen, OID_AUTO, xsd_port, CTLFLAG_RD, &xen_store_evtchn, 0, "");
SYSCTL_ULONG(_dev_xen, OID_AUTO, xsd_kva, CTLFLAG_RD, (u_long *) &xen_store, 0, "");
-#endif
static device_method_t xenbus_methods[] = {
/* Device interface */
diff --git a/sys/xen/xenbus/xenbus_probe_backend.c b/sys/xen/xenbus/xenbus_probe_backend.c
index af83fe6..20cc49f 100644
--- a/sys/xen/xenbus/xenbus_probe_backend.c
+++ b/sys/xen/xenbus/xenbus_probe_backend.c
@@ -57,10 +57,11 @@ __FBSDID("$FreeBSD$");
#include <sys/sx.h>
#include <machine/xen/xen-os.h>
-#include <machine/xen/hypervisor.h>
-#include <machine/xen/evtchn.h>
+#include <xen/hypervisor.h>
+#include <machine/xen/xenbus.h>
#include <machine/stdarg.h>
+#include <xen/evtchn.h>
#include <xen/xenbus/xenbus_comms.h>
#define BUG_ON PANIC_IF
diff --git a/sys/xen/xenbus/xenbus_xs.c b/sys/xen/xenbus/xenbus_xs.c
index 332a509..9e0f779 100644
--- a/sys/xen/xenbus/xenbus_xs.c
+++ b/sys/xen/xenbus/xenbus_xs.c
@@ -33,91 +33,77 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/cdefs.h>
-#include <sys/unistd.h>
-#include <sys/errno.h>
#include <sys/uio.h>
#include <sys/kernel.h>
-#include <sys/time.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/sx.h>
-#include <sys/sema.h>
#include <sys/syslog.h>
#include <sys/malloc.h>
-#include <sys/libkern.h>
#include <sys/systm.h>
#include <sys/proc.h>
#include <sys/kthread.h>
+#include <sys/unistd.h>
#include <machine/xen/xen-os.h>
-#include <machine/xen/hypervisor.h>
+#include <xen/hypervisor.h>
#include <machine/stdarg.h>
#include <xen/xenbus/xenbusvar.h>
#include <xen/xenbus/xenbus_comms.h>
-static int xs_process_msg(enum xsd_sockmsg_type *type);
+#include <xen/interface/hvm/params.h>
-#define kmalloc(size, unused) malloc(size, M_DEVBUF, M_WAITOK)
-#define BUG_ON PANIC_IF
-#define DEFINE_SPINLOCK(lock) struct mtx lock
-#define u32 uint32_t
-#define list_del(head, ent) TAILQ_REMOVE(head, ent, list)
-#define simple_strtoul strtoul
-#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
-#define list_empty TAILQ_EMPTY
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+static int xs_process_msg(enum xsd_sockmsg_type *type);
-#define streq(a, b) (strcmp((a), (b)) == 0)
int xenwatch_running = 0;
int xenbus_running = 0;
-
-struct kvec {
- const void *iov_base;
- size_t iov_len;
-};
+int xen_store_evtchn;
struct xs_stored_msg {
- TAILQ_ENTRY(xs_stored_msg) list;
-
- struct xsd_sockmsg hdr;
-
- union {
- /* Queued replies. */
- struct {
- char *body;
- } reply;
-
- /* Queued watch events. */
- struct {
- struct xenbus_watch *handle;
- char **vec;
- unsigned int vec_size;
- } watch;
- } u;
+ TAILQ_ENTRY(xs_stored_msg) list;
+
+ struct xsd_sockmsg hdr;
+
+ union {
+ /* Queued replies. */
+ struct {
+ char *body;
+ } reply;
+
+ /* Queued watch events. */
+ struct {
+ struct xenbus_watch *handle;
+ char **vec;
+ unsigned int vec_size;
+ } watch;
+ } u;
};
struct xs_handle {
- /* A list of replies. Currently only one will ever be outstanding. */
- TAILQ_HEAD(xs_handle_list, xs_stored_msg) reply_list;
- struct mtx reply_lock;
- int reply_waitq;
+ /* A list of replies. Currently only one will ever be outstanding. */
+ TAILQ_HEAD(xs_handle_list, xs_stored_msg) reply_list;
+ struct mtx reply_lock;
+ int reply_waitq;
- /* One request at a time. */
- struct sx request_mutex;
+ /* One request at a time. */
+ struct sx request_mutex;
- /* Protect transactions against save/restore. */
- struct sx suspend_mutex;
+ /* Protect transactions against save/restore. */
+ struct sx suspend_mutex;
};
static struct xs_handle xs_state;
/* List of registered watches, and a lock to protect it. */
static LIST_HEAD(watch_list_head, xenbus_watch) watches;
-static DEFINE_SPINLOCK(watches_lock);
+static struct mtx watches_lock;
/* List of pending watch callback events, and a lock to protect it. */
static TAILQ_HEAD(event_list_head, xs_stored_msg) watch_events;
-static DEFINE_SPINLOCK(watch_events_lock);
+static struct mtx watch_events_lock;
+
/*
* Details of the xenwatch callback kernel thread. The thread waits on the
* watch_events_waitq for work to do (queued on watch_events list). When it
@@ -128,831 +114,814 @@ static pid_t xenwatch_pid;
struct sx xenwatch_mutex;
static int watch_events_waitq;
-static int get_error(const char *errorstring)
+#define xsd_error_count (sizeof(xsd_errors) / sizeof(xsd_errors[0]))
+
+static int
+xs_get_error(const char *errorstring)
{
- unsigned int i;
+ unsigned int i;
- for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
- if (i == ARRAY_SIZE(xsd_errors) - 1) {
- log(LOG_WARNING, "XENBUS xen store gave: unknown error %s",
- errorstring);
- return EINVAL;
- }
- }
- return xsd_errors[i].errnum;
+ for (i = 0; i < xsd_error_count; i++) {
+ if (!strcmp(errorstring, xsd_errors[i].errstring))
+ return (xsd_errors[i].errnum);
+ }
+ log(LOG_WARNING, "XENBUS xen store gave: unknown error %s",
+ errorstring);
+ return (EINVAL);
}
-extern void idle_block(void);
extern void kdb_backtrace(void);
-static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
+static int
+xs_read_reply(enum xsd_sockmsg_type *type, unsigned int *len, void **result)
{
- struct xs_stored_msg *msg;
- char *body;
- int i, err;
- enum xsd_sockmsg_type itype = *type;
-
- printf("read_reply ");
- if (xenbus_running == 0) {
- /*
- * Give other domain time to run :-/
- */
- for (i = 0; i < 1000000 && (xenbus_running == 0); i++) {
- err = xs_process_msg(type);
-
- if ((err == 0)
- && (*type != XS_WATCH_EVENT))
- break;
-
- HYPERVISOR_yield();
+ struct xs_stored_msg *msg;
+ char *body;
+ int error;
+
+ mtx_lock(&xs_state.reply_lock);
+
+ while (TAILQ_EMPTY(&xs_state.reply_list)) {
+ while (TAILQ_EMPTY(&xs_state.reply_list)) {
+ error = mtx_sleep(&xs_state.reply_waitq,
+ &xs_state.reply_lock,
+ PCATCH, "xswait", hz/10);
+ if (error && error != EWOULDBLOCK) {
+ mtx_unlock(&xs_state.reply_lock);
+ return (error);
}
- if (list_empty(&xs_state.reply_list)) {
- printf("giving up and returning an error type=%d\n",
- *type);
- kdb_backtrace();
- return (ERR_PTR(-1));
- }
+ }
+
}
- mtx_lock(&xs_state.reply_lock);
- if (xenbus_running) {
- while (list_empty(&xs_state.reply_list)) {
- mtx_unlock(&xs_state.reply_lock);
- wait_event_interruptible(&xs_state.reply_waitq,
- !list_empty(&xs_state.reply_list));
-
- mtx_lock(&xs_state.reply_lock);
- }
- }
- msg = TAILQ_FIRST(&xs_state.reply_list);
- list_del(&xs_state.reply_list, msg);
+ msg = TAILQ_FIRST(&xs_state.reply_list);
+ TAILQ_REMOVE(&xs_state.reply_list, msg, list);
- mtx_unlock(&xs_state.reply_lock);
+ mtx_unlock(&xs_state.reply_lock);
- printf("itype=%d htype=%d ", itype, msg->hdr.type);
- *type = msg->hdr.type;
- if (len)
- *len = msg->hdr.len;
- body = msg->u.reply.body;
+ *type = msg->hdr.type;
+ if (len)
+ *len = msg->hdr.len;
+ body = msg->u.reply.body;
- kfree(msg);
- if (len)
- printf("len=%d\n", *len);
- else
- printf("len=NULL\n");
- return body;
+ free(msg, M_DEVBUF);
+ *result = body;
+ return (0);
}
#if 0
/* Emergency write. UNUSED*/
void xenbus_debug_write(const char *str, unsigned int count)
{
- struct xsd_sockmsg msg = { 0 };
+ struct xsd_sockmsg msg = { 0 };
- msg.type = XS_DEBUG;
- msg.len = sizeof("print") + count + 1;
+ msg.type = XS_DEBUG;
+ msg.len = sizeof("print") + count + 1;
- sx_xlock(&xs_state.request_mutex);
- xb_write(&msg, sizeof(msg));
- xb_write("print", sizeof("print"));
- xb_write(str, count);
- xb_write("", 1);
- sx_xunlock(&xs_state.request_mutex);
+ sx_xlock(&xs_state.request_mutex);
+ xb_write(&msg, sizeof(msg));
+ xb_write("print", sizeof("print"));
+ xb_write(str, count);
+ xb_write("", 1);
+ sx_xunlock(&xs_state.request_mutex);
}
#endif
-void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
+
+int
+xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void **result)
{
- void *ret;
- struct xsd_sockmsg req_msg = *msg;
- int err;
+ struct xsd_sockmsg req_msg = *msg;
+ int error;
- if (req_msg.type == XS_TRANSACTION_START)
- sx_slock(&xs_state.suspend_mutex);
+ if (req_msg.type == XS_TRANSACTION_START)
+ sx_slock(&xs_state.suspend_mutex);
- sx_xlock(&xs_state.request_mutex);
+ sx_xlock(&xs_state.request_mutex);
- err = xb_write(msg, sizeof(*msg) + msg->len);
- if (err) {
- msg->type = XS_ERROR;
- ret = ERR_PTR(err);
- } else {
- ret = read_reply(&msg->type, &msg->len);
- }
+ error = xb_write(msg, sizeof(*msg) + msg->len, &xs_state.request_mutex.lock_object);
+ if (error) {
+ msg->type = XS_ERROR;
+ } else {
+ error = xs_read_reply(&msg->type, &msg->len, result);
+ }
- sx_xunlock(&xs_state.request_mutex);
+ sx_xunlock(&xs_state.request_mutex);
- if ((msg->type == XS_TRANSACTION_END) ||
- ((req_msg.type == XS_TRANSACTION_START) &&
- (msg->type == XS_ERROR)))
- sx_sunlock(&xs_state.suspend_mutex);
+ if ((msg->type == XS_TRANSACTION_END) ||
+ ((req_msg.type == XS_TRANSACTION_START) &&
+ (msg->type == XS_ERROR)))
+ sx_sunlock(&xs_state.suspend_mutex);
- return ret;
+ return (error);
}
-static int xenwatch_inline;
-
-/* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
-static void *xs_talkv(struct xenbus_transaction t,
- enum xsd_sockmsg_type type,
- const struct kvec *iovec,
- unsigned int num_vecs,
- unsigned int *len)
+/*
+ * Send message to xs. The reply is returned in *result and should be
+ * fred with free(*result, M_DEVBUF). Return zero on success or an
+ * error code on failure.
+ */
+static int
+xs_talkv(struct xenbus_transaction t, enum xsd_sockmsg_type type,
+ const struct iovec *iovec, unsigned int num_vecs,
+ unsigned int *len, void **result)
{
- struct xsd_sockmsg msg;
- void *ret = NULL;
- unsigned int i;
- int err;
-
- msg.tx_id = t.id;
- msg.req_id = 0;
- msg.type = type;
- msg.len = 0;
- for (i = 0; i < num_vecs; i++)
- msg.len += iovec[i].iov_len;
-
- printf("xs_talkv ");
-
- sx_xlock(&xs_state.request_mutex);
-
- err = xb_write(&msg, sizeof(msg));
- if (err) {
- sx_xunlock(&xs_state.request_mutex);
- printf("xs_talkv failed %d\n", err);
- return ERR_PTR(err);
- }
-
- for (i = 0; i < num_vecs; i++) {
- err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
- if (err) {
- sx_xunlock(&xs_state.request_mutex);
- printf("xs_talkv failed %d\n", err);
- return ERR_PTR(err);
- }
+ struct xsd_sockmsg msg;
+ void *ret = NULL;
+ unsigned int i;
+ int error;
+
+ msg.tx_id = t.id;
+ msg.req_id = 0;
+ msg.type = type;
+ msg.len = 0;
+ for (i = 0; i < num_vecs; i++)
+ msg.len += iovec[i].iov_len;
+
+ sx_xlock(&xs_state.request_mutex);
+
+ error = xb_write(&msg, sizeof(msg), &xs_state.request_mutex.lock_object);
+ if (error) {
+ sx_xunlock(&xs_state.request_mutex);
+ printf("xs_talkv failed %d\n", error);
+ return (error);
+ }
+
+ for (i = 0; i < num_vecs; i++) {
+ error = xb_write(iovec[i].iov_base, iovec[i].iov_len, &xs_state.request_mutex.lock_object);
+ if (error) {
+ sx_xunlock(&xs_state.request_mutex);
+ printf("xs_talkv failed %d\n", error);
+ return (error);
}
+ }
- ret = read_reply(&msg.type, len);
+ error = xs_read_reply(&msg.type, len, &ret);
- sx_xunlock(&xs_state.request_mutex);
+ sx_xunlock(&xs_state.request_mutex);
- if (IS_ERR(ret))
- return ret;
+ if (error)
+ return (error);
- if (msg.type == XS_ERROR) {
- err = get_error(ret);
- kfree(ret);
- return ERR_PTR(-err);
- }
+ if (msg.type == XS_ERROR) {
+ error = xs_get_error(ret);
+ free(ret, M_DEVBUF);
+ return (error);
+ }
- if ((xenwatch_running == 0) && (xenwatch_inline == 0)) {
- xenwatch_inline = 1;
- while (!TAILQ_EMPTY(&watch_events)
- && xenwatch_running == 0) {
+#if 0
+ if ((xenwatch_running == 0) && (xenwatch_inline == 0)) {
+ xenwatch_inline = 1;
+ while (!TAILQ_EMPTY(&watch_events)
+ && xenwatch_running == 0) {
- struct xs_stored_msg *wmsg = TAILQ_FIRST(&watch_events);
- list_del(&watch_events, wmsg);
- printf("handling %p ...", wmsg->u.watch.handle->callback);
+ struct xs_stored_msg *wmsg = TAILQ_FIRST(&watch_events);
+ TAILQ_REMOVE(&watch_events, wmsg, list);
- wmsg->u.watch.handle->callback(
- wmsg->u.watch.handle,
- (const char **)wmsg->u.watch.vec,
- wmsg->u.watch.vec_size);
- printf("... %p done\n", wmsg->u.watch.handle->callback);
- kfree(wmsg->u.watch.vec);
- kfree(wmsg);
- }
- xenwatch_inline = 0;
+ wmsg->u.watch.handle->callback(
+ wmsg->u.watch.handle,
+ (const char **)wmsg->u.watch.vec,
+ wmsg->u.watch.vec_size);
+ free(wmsg->u.watch.vec, M_DEVBUF);
+ free(wmsg, M_DEVBUF);
}
- BUG_ON(msg.type != type);
+ xenwatch_inline = 0;
+ }
+#endif
+ KASSERT(msg.type == type, ("bad xenstore message type"));
- return ret;
+ if (result)
+ *result = ret;
+ else
+ free(ret, M_DEVBUF);
+
+ return (0);
}
/* Simplified version of xs_talkv: single message. */
-static void *xs_single(struct xenbus_transaction t,
- enum xsd_sockmsg_type type,
- const char *string,
- unsigned int *len)
+static int
+xs_single(struct xenbus_transaction t, enum xsd_sockmsg_type type,
+ const char *string, unsigned int *len, void **result)
{
- struct kvec iovec;
+ struct iovec iovec;
- printf("xs_single %s ", string);
- iovec.iov_base = (const void *)string;
- iovec.iov_len = strlen(string) + 1;
- return xs_talkv(t, type, &iovec, 1, len);
-}
+ iovec.iov_base = (void *)(uintptr_t) string;
+ iovec.iov_len = strlen(string) + 1;
-/* Many commands only need an ack, don't care what it says. */
-static int xs_error(char *reply)
-{
- if (IS_ERR(reply))
- return PTR_ERR(reply);
- kfree(reply);
- return 0;
+ return (xs_talkv(t, type, &iovec, 1, len, result));
}
-static unsigned int count_strings(const char *strings, unsigned int len)
+static unsigned int
+count_strings(const char *strings, unsigned int len)
{
- unsigned int num;
- const char *p;
+ unsigned int num;
+ const char *p;
- for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
- num++;
+ for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
+ num++;
- return num;
+ return num;
}
/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */
-static char *join(const char *dir, const char *name)
+static char *
+join(const char *dir, const char *name)
{
- char *buffer;
+ char *buffer;
- buffer = kmalloc(strlen(dir) + strlen("/") + strlen(name) + 1,
- GFP_KERNEL);
- if (buffer == NULL)
- return ERR_PTR(-ENOMEM);
+ buffer = malloc(strlen(dir) + strlen("/") + strlen(name) + 1,
+ M_DEVBUF, M_WAITOK);
- strcpy(buffer, dir);
- if (!streq(name, "")) {
- strcat(buffer, "/");
- strcat(buffer, name);
- }
+ strcpy(buffer, dir);
+ if (strcmp(name, "")) {
+ strcat(buffer, "/");
+ strcat(buffer, name);
+ }
- return buffer;
+ return (buffer);
}
-static char **split(char *strings, unsigned int len, unsigned int *num)
+static char **
+split(char *strings, unsigned int len, unsigned int *num)
{
- char *p, **ret;
+ char *p, **ret;
- /* Count the strings. */
- *num = count_strings(strings, len) + 1;
+ /* Count the strings. */
+ *num = count_strings(strings, len) + 1;
- /* Transfer to one big alloc for easy freeing. */
- ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL);
- if (!ret) {
- kfree(strings);
- return ERR_PTR(-ENOMEM);
- }
- memcpy(&ret[*num], strings, len);
- kfree(strings);
+ /* Transfer to one big alloc for easy freeing. */
+ ret = malloc(*num * sizeof(char *) + len, M_DEVBUF, M_WAITOK);
+ memcpy(&ret[*num], strings, len);
+ free(strings, M_DEVBUF);
- strings = (char *)&ret[*num];
- for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
- ret[(*num)++] = p;
+ strings = (char *)&ret[*num];
+ for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
+ ret[(*num)++] = p;
- ret[*num] = strings + len;
+ ret[*num] = strings + len;
- return ret;
+ return ret;
}
-char **xenbus_directory(struct xenbus_transaction t,
- const char *dir, const char *node, unsigned int *num)
+/*
+ * Return the contents of a directory in *result which should be freed
+ * with free(*result, M_DEVBUF).
+ */
+int
+xenbus_directory(struct xenbus_transaction t, const char *dir,
+ const char *node, unsigned int *num, char ***result)
{
- char *strings, *path;
- unsigned int len = 0;
-
- path = join(dir, node);
- if (IS_ERR(path))
- return (char **)path;
+ char *strings, *path;
+ unsigned int len = 0;
+ int error;
- strings = xs_single(t, XS_DIRECTORY, path, &len);
- kfree(path);
- if (IS_ERR(strings))
- return (char **)strings;
+ path = join(dir, node);
+ error = xs_single(t, XS_DIRECTORY, path, &len, (void **) &strings);
+ free(path, M_DEVBUF);
+ if (error)
+ return (error);
- return split(strings, len, num);
+ *result = split(strings, len, num);
+ return (0);
}
-EXPORT_SYMBOL(xenbus_directory);
-/* Check if a path exists. Return 1 if it does. */
-int xenbus_exists(struct xenbus_transaction t,
- const char *dir, const char *node)
+/*
+ * Check if a path exists. Return 1 if it does.
+ */
+int
+xenbus_exists(struct xenbus_transaction t, const char *dir, const char *node)
{
- char **d;
- int dir_n;
+ char **d;
+ int error, dir_n;
- d = xenbus_directory(t, dir, node, &dir_n);
- if (IS_ERR(d))
- return 0;
- kfree(d);
- return 1;
+ error = xenbus_directory(t, dir, node, &dir_n, &d);
+ if (error)
+ return (0);
+ free(d, M_DEVBUF);
+ return (1);
}
-EXPORT_SYMBOL(xenbus_exists);
-/* Get the value of a single file.
- * Returns a kmalloced value: call free() on it after use.
- * len indicates length in bytes.
+/*
+ * Get the value of a single file. Returns the contents in *result
+ * which should be freed with free(*result, M_DEVBUF) after use.
+ * The length of the value in bytes is returned in *len.
*/
-void *xenbus_read(struct xenbus_transaction t,
- const char *dir, const char *node, unsigned int *len)
+int
+xenbus_read(struct xenbus_transaction t, const char *dir, const char *node,
+ unsigned int *len, void **result)
{
- char *path;
- void *ret;
-
- path = join(dir, node);
- if (IS_ERR(path))
- return (void *)path;
+ char *path;
+ void *ret;
+ int error;
- printf("xs_read ");
- ret = xs_single(t, XS_READ, path, len);
- kfree(path);
- return ret;
+ path = join(dir, node);
+ error = xs_single(t, XS_READ, path, len, &ret);
+ free(path, M_DEVBUF);
+ if (error)
+ return (error);
+ *result = ret;
+ return (0);
}
-EXPORT_SYMBOL(xenbus_read);
-/* Write the value of a single file.
- * Returns -err on failure.
+/*
+ * Write the value of a single file. Returns error on failure.
*/
-int xenbus_write(struct xenbus_transaction t,
- const char *dir, const char *node, const char *string)
+int
+xenbus_write(struct xenbus_transaction t, const char *dir, const char *node,
+ const char *string)
{
- char *path;
- struct kvec iovec[2];
- int ret;
+ char *path;
+ struct iovec iovec[2];
+ int error;
+
+ path = join(dir, node);
- path = join(dir, node);
- if (IS_ERR(path))
- return PTR_ERR(path);
+ iovec[0].iov_base = (void *)(uintptr_t) path;
+ iovec[0].iov_len = strlen(path) + 1;
+ iovec[1].iov_base = (void *)(uintptr_t) string;
+ iovec[1].iov_len = strlen(string);
- iovec[0].iov_base = path;
- iovec[0].iov_len = strlen(path) + 1;
- iovec[1].iov_base = string;
- iovec[1].iov_len = strlen(string);
+ error = xs_talkv(t, XS_WRITE, iovec, 2, NULL, NULL);
+ free(path, M_DEVBUF);
- printf("xenbus_write dir=%s val=%s ", dir, string);
- ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
- kfree(path);
- return ret;
+ return (error);
}
-EXPORT_SYMBOL(xenbus_write);
-/* Create a new directory. */
-int xenbus_mkdir(struct xenbus_transaction t,
- const char *dir, const char *node)
+/*
+ * Create a new directory.
+ */
+int
+xenbus_mkdir(struct xenbus_transaction t, const char *dir, const char *node)
{
- char *path;
- int ret;
+ char *path;
+ int ret;
- path = join(dir, node);
- if (IS_ERR(path))
- return PTR_ERR(path);
+ path = join(dir, node);
+ ret = xs_single(t, XS_MKDIR, path, NULL, NULL);
+ free(path, M_DEVBUF);
- ret = xs_error(xs_single(t, XS_MKDIR, path, NULL));
- kfree(path);
- return ret;
+ return (ret);
}
-EXPORT_SYMBOL(xenbus_mkdir);
-/* Destroy a file or directory (directories must be empty). */
-int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node)
+/*
+ * Destroy a file or directory (directories must be empty).
+ */
+int
+xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node)
{
- char *path;
- int ret;
+ char *path;
+ int ret;
- path = join(dir, node);
- if (IS_ERR(path))
- return PTR_ERR(path);
+ path = join(dir, node);
+ ret = xs_single(t, XS_RM, path, NULL, NULL);
+ free(path, M_DEVBUF);
- ret = xs_error(xs_single(t, XS_RM, path, NULL));
- kfree(path);
- return ret;
+ return (ret);
}
-EXPORT_SYMBOL(xenbus_rm);
-/* Start a transaction: changes by others will not be seen during this
+/*
+ * Start a transaction: changes by others will not be seen during this
* transaction, and changes will not be visible to others until end.
*/
-int xenbus_transaction_start(struct xenbus_transaction *t)
+int
+xenbus_transaction_start(struct xenbus_transaction *t)
{
- char *id_str;
+ char *id_str;
+ int error;
- sx_slock(&xs_state.suspend_mutex);
- id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL);
- if (IS_ERR(id_str)) {
- sx_sunlock(&xs_state.suspend_mutex);
- return PTR_ERR(id_str);
- }
+ sx_slock(&xs_state.suspend_mutex);
+ error = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL,
+ (void **) &id_str);
+ if (error) {
+ sx_sunlock(&xs_state.suspend_mutex);
+ return (error);
+ }
- t->id = simple_strtoul(id_str, NULL, 0);
- kfree(id_str);
+ t->id = strtoul(id_str, NULL, 0);
+ free(id_str, M_DEVBUF);
- return 0;
+ return (0);
}
-EXPORT_SYMBOL(xenbus_transaction_start);
-/* End a transaction.
- * If abandon is true, transaction is discarded instead of committed.
+/*
+ * End a transaction. If abandon is true, transaction is discarded
+ * instead of committed.
*/
int xenbus_transaction_end(struct xenbus_transaction t, int abort)
{
- char abortstr[2];
- int err;
+ char abortstr[2];
+ int error;
- if (abort)
- strcpy(abortstr, "F");
- else
- strcpy(abortstr, "T");
+ if (abort)
+ strcpy(abortstr, "F");
+ else
+ strcpy(abortstr, "T");
- printf("xenbus_transaction_end ");
- err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
+ error = xs_single(t, XS_TRANSACTION_END, abortstr, NULL, NULL);
- sx_sunlock(&xs_state.suspend_mutex);
+ sx_sunlock(&xs_state.suspend_mutex);
- return err;
+ return (error);
}
-EXPORT_SYMBOL(xenbus_transaction_end);
-/* Single read and scanf: returns -errno or num scanned. */
-int xenbus_scanf(struct xenbus_transaction t,
- const char *dir, const char *node, const char *fmt, ...)
+/* Single read and scanf: returns zero or errno. */
+int
+xenbus_scanf(struct xenbus_transaction t,
+ const char *dir, const char *node, int *scancountp, const char *fmt, ...)
{
- va_list ap;
- int ret;
- char *val;
-
- val = xenbus_read(t, dir, node, NULL);
- if (IS_ERR(val))
- return PTR_ERR(val);
-
- va_start(ap, fmt);
- ret = vsscanf(val, fmt, ap);
- va_end(ap);
- kfree(val);
- /* Distinctive errno. */
- if (ret == 0)
- return -ERANGE;
- return ret;
-}
-EXPORT_SYMBOL(xenbus_scanf);
-
-/* Single printf and write: returns -errno or 0. */
-int xenbus_printf(struct xenbus_transaction t,
- const char *dir, const char *node, const char *fmt, ...)
+ va_list ap;
+ int error, ns;
+ char *val;
+
+ error = xenbus_read(t, dir, node, NULL, (void **) &val);
+ if (error)
+ return (error);
+
+ va_start(ap, fmt);
+ ns = vsscanf(val, fmt, ap);
+ va_end(ap);
+ free(val, M_DEVBUF);
+ /* Distinctive errno. */
+ if (ns == 0)
+ return (ERANGE);
+ if (scancountp)
+ *scancountp = ns;
+ return (0);
+}
+
+/* Single printf and write: returns zero or errno. */
+int
+xenbus_printf(struct xenbus_transaction t,
+ const char *dir, const char *node, const char *fmt, ...)
{
- va_list ap;
- int ret;
+ va_list ap;
+ int error, ret;
#define PRINTF_BUFFER_SIZE 4096
- char *printf_buffer;
+ char *printf_buffer;
- printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
- if (printf_buffer == NULL)
- return -ENOMEM;
+ printf_buffer = malloc(PRINTF_BUFFER_SIZE, M_DEVBUF, M_WAITOK);
- va_start(ap, fmt);
- ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
- va_end(ap);
+ va_start(ap, fmt);
+ ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
+ va_end(ap);
- BUG_ON(ret > PRINTF_BUFFER_SIZE-1);
- ret = xenbus_write(t, dir, node, printf_buffer);
+ KASSERT(ret <= PRINTF_BUFFER_SIZE-1, ("xenbus_printf: message too large"));
+ error = xenbus_write(t, dir, node, printf_buffer);
- kfree(printf_buffer);
+ free(printf_buffer, M_DEVBUF);
- return ret;
+ return (error);
}
-EXPORT_SYMBOL(xenbus_printf);
/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
-int xenbus_gather(struct xenbus_transaction t, const char *dir, ...)
+int
+xenbus_gather(struct xenbus_transaction t, const char *dir, ...)
{
- va_list ap;
- const char *name;
- int i, ret = 0;
+ va_list ap;
+ const char *name;
+ int error, i;
- for (i = 0; i < 10000; i++)
- HYPERVISOR_yield();
+ for (i = 0; i < 10000; i++)
+ HYPERVISOR_yield();
- printf("gather ");
- va_start(ap, dir);
- while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
- const char *fmt = va_arg(ap, char *);
- void *result = va_arg(ap, void *);
- char *p;
-
- p = xenbus_read(t, dir, name, NULL);
- if (IS_ERR(p)) {
- ret = PTR_ERR(p);
- break;
- }
- printf(" %s ", p);
- if (fmt) {
- if (sscanf(p, fmt, result) == 0)
- ret = -EINVAL;
- kfree(p);
- } else
- *(char **)result = p;
- }
- va_end(ap);
- printf("\n");
- return ret;
-}
-EXPORT_SYMBOL(xenbus_gather);
-
-static int xs_watch(const char *path, const char *token)
+ va_start(ap, dir);
+ error = 0;
+ while (error == 0 && (name = va_arg(ap, char *)) != NULL) {
+ const char *fmt = va_arg(ap, char *);
+ void *result = va_arg(ap, void *);
+ char *p;
+
+ error = xenbus_read(t, dir, name, NULL, (void **) &p);
+ if (error)
+ break;
+
+ if (fmt) {
+ if (sscanf(p, fmt, result) == 0)
+ error = EINVAL;
+ free(p, M_DEVBUF);
+ } else
+ *(char **)result = p;
+ }
+ va_end(ap);
+
+ return (error);
+}
+
+static int
+xs_watch(const char *path, const char *token)
{
- struct kvec iov[2];
+ struct iovec iov[2];
- iov[0].iov_base = path;
- iov[0].iov_len = strlen(path) + 1;
- iov[1].iov_base = token;
- iov[1].iov_len = strlen(token) + 1;
+ iov[0].iov_base = (void *)(uintptr_t) path;
+ iov[0].iov_len = strlen(path) + 1;
+ iov[1].iov_base = (void *)(uintptr_t) token;
+ iov[1].iov_len = strlen(token) + 1;
- return xs_error(xs_talkv(XBT_NIL, XS_WATCH, iov,
- ARRAY_SIZE(iov), NULL));
+ return (xs_talkv(XBT_NIL, XS_WATCH, iov, 2, NULL, NULL));
}
-static int xs_unwatch(const char *path, const char *token)
+static int
+xs_unwatch(const char *path, const char *token)
{
- struct kvec iov[2];
+ struct iovec iov[2];
- iov[0].iov_base = path;
- iov[0].iov_len = strlen(path) + 1;
- iov[1].iov_base = token;
- iov[1].iov_len = strlen(token) + 1;
+ iov[0].iov_base = (void *)(uintptr_t) path;
+ iov[0].iov_len = strlen(path) + 1;
+ iov[1].iov_base = (void *)(uintptr_t) token;
+ iov[1].iov_len = strlen(token) + 1;
- return xs_error(xs_talkv(XBT_NIL, XS_UNWATCH, iov,
- ARRAY_SIZE(iov), NULL));
+ return (xs_talkv(XBT_NIL, XS_UNWATCH, iov, 2, NULL, NULL));
}
-static struct xenbus_watch *find_watch(const char *token)
+static struct xenbus_watch *
+find_watch(const char *token)
{
- struct xenbus_watch *i, *cmp;
+ struct xenbus_watch *i, *cmp;
- cmp = (void *)simple_strtoul(token, NULL, 16);
+ cmp = (void *)strtoul(token, NULL, 16);
- LIST_FOREACH(i, &watches, list)
- if (i == cmp)
- return i;
+ LIST_FOREACH(i, &watches, list)
+ if (i == cmp)
+ return (i);
- return NULL;
+ return (NULL);
}
/* Register callback to watch this node. */
-int register_xenbus_watch(struct xenbus_watch *watch)
+int
+register_xenbus_watch(struct xenbus_watch *watch)
{
- /* Pointer in ascii is the token. */
- char token[sizeof(watch) * 2 + 1];
- int err;
+ /* Pointer in ascii is the token. */
+ char token[sizeof(watch) * 2 + 1];
+ int error;
- sprintf(token, "%lX", (long)watch);
+ sprintf(token, "%lX", (long)watch);
- sx_slock(&xs_state.suspend_mutex);
+ sx_slock(&xs_state.suspend_mutex);
- mtx_lock(&watches_lock);
- BUG_ON(find_watch(token) != NULL);
- LIST_INSERT_HEAD(&watches, watch, list);
- mtx_unlock(&watches_lock);
+ mtx_lock(&watches_lock);
+ KASSERT(find_watch(token) == NULL, ("watch already registered"));
+ LIST_INSERT_HEAD(&watches, watch, list);
+ mtx_unlock(&watches_lock);
- err = xs_watch(watch->node, token);
+ error = xs_watch(watch->node, token);
- /* Ignore errors due to multiple registration. */
- if ((err != 0) && (err != -EEXIST)) {
- mtx_lock(&watches_lock);
- LIST_REMOVE(watch, list);
- mtx_unlock(&watches_lock);
- }
+ /* Ignore errors due to multiple registration. */
+ if (error == EEXIST) {
+ mtx_lock(&watches_lock);
+ LIST_REMOVE(watch, list);
+ mtx_unlock(&watches_lock);
+ }
- sx_sunlock(&xs_state.suspend_mutex);
+ sx_sunlock(&xs_state.suspend_mutex);
- return err;
+ return (error);
}
-EXPORT_SYMBOL(register_xenbus_watch);
-void unregister_xenbus_watch(struct xenbus_watch *watch)
+void
+unregister_xenbus_watch(struct xenbus_watch *watch)
{
- struct xs_stored_msg *msg, *tmp;
- char token[sizeof(watch) * 2 + 1];
- int err;
+ struct xs_stored_msg *msg, *tmp;
+ char token[sizeof(watch) * 2 + 1];
+ int error;
- sprintf(token, "%lX", (long)watch);
+ sprintf(token, "%lX", (long)watch);
- sx_slock(&xs_state.suspend_mutex);
-
- mtx_lock(&watches_lock);
- BUG_ON(!find_watch(token));
- LIST_REMOVE(watch, list);
- mtx_unlock(&watches_lock);
+ sx_slock(&xs_state.suspend_mutex);
+
+ mtx_lock(&watches_lock);
+ KASSERT(find_watch(token), ("watch not registered"));
+ LIST_REMOVE(watch, list);
+ mtx_unlock(&watches_lock);
+
+ error = xs_unwatch(watch->node, token);
+ if (error)
+ log(LOG_WARNING, "XENBUS Failed to release watch %s: %i\n",
+ watch->node, error);
+
+ sx_sunlock(&xs_state.suspend_mutex);
+
+ /* Cancel pending watch events. */
+ mtx_lock(&watch_events_lock);
+ TAILQ_FOREACH_SAFE(msg, &watch_events, list, tmp) {
+ if (msg->u.watch.handle != watch)
+ continue;
+ TAILQ_REMOVE(&watch_events, msg, list);
+ free(msg->u.watch.vec, M_DEVBUF);
+ free(msg, M_DEVBUF);
+ }
+ mtx_unlock(&watch_events_lock);
+
+ /* Flush any currently-executing callback, unless we are it. :-) */
+ if (curproc->p_pid != xenwatch_pid) {
+ sx_xlock(&xenwatch_mutex);
+ sx_xunlock(&xenwatch_mutex);
+ }
+}
+
+void
+xs_suspend(void)
+{
- err = xs_unwatch(watch->node, token);
- if (err)
- log(LOG_WARNING, "XENBUS Failed to release watch %s: %i\n",
- watch->node, err);
+ sx_xlock(&xs_state.suspend_mutex);
+ sx_xlock(&xs_state.request_mutex);
+}
- sx_sunlock(&xs_state.suspend_mutex);
+void
+xs_resume(void)
+{
+ struct xenbus_watch *watch;
+ char token[sizeof(watch) * 2 + 1];
- /* Cancel pending watch events. */
- mtx_lock(&watch_events_lock);
- TAILQ_FOREACH_SAFE(msg, &watch_events, list, tmp) {
- if (msg->u.watch.handle != watch)
- continue;
- list_del(&watch_events, msg);
- kfree(msg->u.watch.vec);
- kfree(msg);
- }
- mtx_unlock(&watch_events_lock);
+ sx_xunlock(&xs_state.request_mutex);
- /* Flush any currently-executing callback, unless we are it. :-) */
- if (curproc->p_pid != xenwatch_pid) {
- sx_xlock(&xenwatch_mutex);
- sx_xunlock(&xenwatch_mutex);
- }
-}
-EXPORT_SYMBOL(unregister_xenbus_watch);
+ /* No need for watches_lock: the suspend_mutex is sufficient. */
+ LIST_FOREACH(watch, &watches, list) {
+ sprintf(token, "%lX", (long)watch);
+ xs_watch(watch->node, token);
+ }
-void xs_suspend(void)
-{
- sx_xlock(&xs_state.suspend_mutex);
- sx_xlock(&xs_state.request_mutex);
+ sx_xunlock(&xs_state.suspend_mutex);
}
-void xs_resume(void)
+static void
+xenwatch_thread(void *unused)
{
- struct xenbus_watch *watch;
- char token[sizeof(watch) * 2 + 1];
+ struct xs_stored_msg *msg;
- sx_xunlock(&xs_state.request_mutex);
+ for (;;) {
- /* No need for watches_lock: the suspend_mutex is sufficient. */
- LIST_FOREACH(watch, &watches, list) {
- sprintf(token, "%lX", (long)watch);
- xs_watch(watch->node, token);
- }
+ mtx_lock(&watch_events_lock);
+ while (TAILQ_EMPTY(&watch_events))
+ mtx_sleep(&watch_events_waitq,
+ &watch_events_lock,
+ PWAIT | PCATCH, "waitev", hz/10);
- sx_xunlock(&xs_state.suspend_mutex);
-}
+ mtx_unlock(&watch_events_lock);
+ sx_xlock(&xenwatch_mutex);
-static void xenwatch_thread(void *unused)
-{
- struct xs_stored_msg *msg;
+ mtx_lock(&watch_events_lock);
+ msg = TAILQ_FIRST(&watch_events);
+ if (msg)
+ TAILQ_REMOVE(&watch_events, msg, list);
+ mtx_unlock(&watch_events_lock);
- DELAY(100000);
- while (xenwatch_inline) {
- printf("xenwatch inline still running\n");
- DELAY(100000);
+ if (msg != NULL) {
+ msg->u.watch.handle->callback(
+ msg->u.watch.handle,
+ (const char **)msg->u.watch.vec,
+ msg->u.watch.vec_size);
+ free(msg->u.watch.vec, M_DEVBUF);
+ free(msg, M_DEVBUF);
}
-
-
- for (;;) {
-
- while (list_empty(&watch_events))
- tsleep(&watch_events_waitq,
- PWAIT | PCATCH, "waitev", hz/10);
-
- sx_xlock(&xenwatch_mutex);
-
- mtx_lock(&watch_events_lock);
- msg = TAILQ_FIRST(&watch_events);
- if (msg)
- list_del(&watch_events, msg);
- mtx_unlock(&watch_events_lock);
-
- if (msg != NULL) {
- msg->u.watch.handle->callback(
- msg->u.watch.handle,
- (const char **)msg->u.watch.vec,
- msg->u.watch.vec_size);
- kfree(msg->u.watch.vec);
- kfree(msg);
- }
- sx_xunlock(&xenwatch_mutex);
- }
+ sx_xunlock(&xenwatch_mutex);
+ }
}
-static int xs_process_msg(enum xsd_sockmsg_type *type)
+static int
+xs_process_msg(enum xsd_sockmsg_type *type)
{
- struct xs_stored_msg *msg;
- char *body;
- int err;
-
- msg = kmalloc(sizeof(*msg), GFP_KERNEL);
- if (msg == NULL)
- return -ENOMEM;
-
- err = xb_read(&msg->hdr, sizeof(msg->hdr));
- if (err) {
- kfree(msg);
- return err;
- }
-
- body = kmalloc(msg->hdr.len + 1, GFP_KERNEL);
- if (body == NULL) {
- kfree(msg);
- return -ENOMEM;
- }
+ struct xs_stored_msg *msg;
+ char *body;
+ int error;
- err = xb_read(body, msg->hdr.len);
- if (err) {
- kfree(body);
- kfree(msg);
- return err;
- }
- body[msg->hdr.len] = '\0';
-
- *type = msg->hdr.type;
- if (msg->hdr.type == XS_WATCH_EVENT) {
- msg->u.watch.vec = split(body, msg->hdr.len,
- &msg->u.watch.vec_size);
- if (IS_ERR(msg->u.watch.vec)) {
- kfree(msg);
- return PTR_ERR(msg->u.watch.vec);
- }
+ msg = malloc(sizeof(*msg), M_DEVBUF, M_WAITOK);
+ mtx_lock(&xs_state.reply_lock);
+ error = xb_read(&msg->hdr, sizeof(msg->hdr), &xs_state.reply_lock.lock_object);
+ mtx_unlock(&xs_state.reply_lock);
+ if (error) {
+ free(msg, M_DEVBUF);
+ return (error);
+ }
+
+ body = malloc(msg->hdr.len + 1, M_DEVBUF, M_WAITOK);
+ mtx_lock(&xs_state.reply_lock);
+ error = xb_read(body, msg->hdr.len, &xs_state.reply_lock.lock_object);
+ mtx_unlock(&xs_state.reply_lock);
+ if (error) {
+ free(body, M_DEVBUF);
+ free(msg, M_DEVBUF);
+ return (error);
+ }
+ body[msg->hdr.len] = '\0';
+
+ *type = msg->hdr.type;
+ if (msg->hdr.type == XS_WATCH_EVENT) {
+ msg->u.watch.vec = split(body, msg->hdr.len,
+ &msg->u.watch.vec_size);
- mtx_lock(&watches_lock);
- msg->u.watch.handle = find_watch(
- msg->u.watch.vec[XS_WATCH_TOKEN]);
- if (msg->u.watch.handle != NULL) {
- mtx_lock(&watch_events_lock);
- TAILQ_INSERT_TAIL(&watch_events, msg, list);
- wakeup(&watch_events_waitq);
- mtx_unlock(&watch_events_lock);
- } else {
- kfree(msg->u.watch.vec);
- kfree(msg);
- }
- mtx_unlock(&watches_lock);
+ mtx_lock(&watches_lock);
+ msg->u.watch.handle = find_watch(
+ msg->u.watch.vec[XS_WATCH_TOKEN]);
+ if (msg->u.watch.handle != NULL) {
+ mtx_lock(&watch_events_lock);
+ TAILQ_INSERT_TAIL(&watch_events, msg, list);
+ wakeup(&watch_events_waitq);
+ mtx_unlock(&watch_events_lock);
} else {
- printf("event=%d ", *type);
- msg->u.reply.body = body;
- mtx_lock(&xs_state.reply_lock);
- TAILQ_INSERT_TAIL(&xs_state.reply_list, msg, list);
- wakeup(&xs_state.reply_waitq);
- mtx_unlock(&xs_state.reply_lock);
+ free(msg->u.watch.vec, M_DEVBUF);
+ free(msg, M_DEVBUF);
}
- if (*type == XS_WATCH_EVENT)
- printf("\n");
+ mtx_unlock(&watches_lock);
+ } else {
+ msg->u.reply.body = body;
+ mtx_lock(&xs_state.reply_lock);
+ TAILQ_INSERT_TAIL(&xs_state.reply_list, msg, list);
+ wakeup(&xs_state.reply_waitq);
+ mtx_unlock(&xs_state.reply_lock);
+ }
- return 0;
+ return 0;
}
-static void xenbus_thread(void *unused)
+static void
+xenbus_thread(void *unused)
{
- int err;
- enum xsd_sockmsg_type type;
+ int error;
+ enum xsd_sockmsg_type type;
+ xenbus_running = 1;
- DELAY(10000);
- xenbus_running = 1;
- pause("xenbus", hz/10);
+ for (;;) {
+ error = xs_process_msg(&type);
+ if (error)
+ printf("XENBUS error %d while reading message\n",
+ error);
+ }
+}
- for (;;) {
- err = xs_process_msg(&type);
- if (err)
- printf("XENBUS error %d while reading "
- "message\n", err);
+#ifdef XENHVM
+static unsigned long xen_store_mfn;
+char *xen_store;
- }
+static inline unsigned long
+hvm_get_parameter(int index)
+{
+ struct xen_hvm_param xhv;
+ int error;
+
+ xhv.domid = DOMID_SELF;
+ xhv.index = index;
+ error = HYPERVISOR_hvm_op(HVMOP_get_param, &xhv);
+ if (error) {
+ printf("hvm_get_parameter: failed to get %d, error %d\n",
+ index, error);
+ return (0);
+ }
+ return (xhv.value);
}
-int xs_init(void)
+#endif
+
+int
+xs_init(void)
{
- int err;
- struct proc *p;
+ int error;
+ struct proc *p;
+
+#ifdef XENHVM
+ xen_store_evtchn = hvm_get_parameter(HVM_PARAM_STORE_EVTCHN);
+ xen_store_mfn = hvm_get_parameter(HVM_PARAM_STORE_PFN);
+ xen_store = pmap_mapdev(xen_store_mfn * PAGE_SIZE, PAGE_SIZE);
+#else
+ xen_store_evtchn = xen_start_info->store_evtchn;
+#endif
- TAILQ_INIT(&xs_state.reply_list);
- TAILQ_INIT(&watch_events);
- sx_init(&xenwatch_mutex, "xenwatch");
+ TAILQ_INIT(&xs_state.reply_list);
+ TAILQ_INIT(&watch_events);
+ sx_init(&xenwatch_mutex, "xenwatch");
- mtx_init(&xs_state.reply_lock, "state reply", NULL, MTX_DEF);
- sx_init(&xs_state.request_mutex, "xenstore request");
- sx_init(&xs_state.suspend_mutex, "xenstore suspend");
+ mtx_init(&xs_state.reply_lock, "state reply", NULL, MTX_DEF);
+ sx_init(&xs_state.request_mutex, "xenstore request");
+ sx_init(&xs_state.suspend_mutex, "xenstore suspend");
#if 0
- mtx_init(&xs_state.suspend_mutex, "xenstore suspend", NULL, MTX_DEF);
- sema_init(&xs_state.request_mutex, 1, "xenstore request");
- sema_init(&xenwatch_mutex, 1, "xenwatch");
+ mtx_init(&xs_state.suspend_mutex, "xenstore suspend", NULL, MTX_DEF);
+ sema_init(&xs_state.request_mutex, 1, "xenstore request");
+ sema_init(&xenwatch_mutex, 1, "xenwatch");
#endif
- mtx_init(&watches_lock, "watches", NULL, MTX_DEF);
- mtx_init(&watch_events_lock, "watch events", NULL, MTX_DEF);
+ mtx_init(&watches_lock, "watches", NULL, MTX_DEF);
+ mtx_init(&watch_events_lock, "watch events", NULL, MTX_DEF);
- /* Initialize the shared memory rings to talk to xenstored */
- err = xb_init_comms();
- if (err)
- return err;
-
- err = kproc_create(xenwatch_thread, NULL, &p,
- RFHIGHPID, 0, "xenwatch");
- if (err)
- return err;
- xenwatch_pid = p->p_pid;
-
- err = kproc_create(xenbus_thread, NULL, NULL,
- RFHIGHPID, 0, "xenbus");
+ /* Initialize the shared memory rings to talk to xenstored */
+ error = xb_init_comms();
+ if (error)
+ return (error);
+
+ xenwatch_running = 1;
+ error = kproc_create(xenwatch_thread, NULL, &p,
+ RFHIGHPID, 0, "xenwatch");
+ if (error)
+ return (error);
+ xenwatch_pid = p->p_pid;
+
+ error = kproc_create(xenbus_thread, NULL, NULL,
+ RFHIGHPID, 0, "xenbus");
- return err;
+ return (error);
}
-
-
-/*
- * Local variables:
- * c-file-style: "bsd"
- * indent-tabs-mode: t
- * c-indent-level: 4
- * c-basic-offset: 8
- * tab-width: 4
- * End:
- */
diff --git a/sys/xen/xenbus/xenbusvar.h b/sys/xen/xenbus/xenbusvar.h
index 1331c43..6511664 100644
--- a/sys/xen/xenbus/xenbusvar.h
+++ b/sys/xen/xenbus/xenbusvar.h
@@ -103,32 +103,37 @@ struct xenbus_transaction
#define XBT_NIL ((struct xenbus_transaction) { 0 })
-char **xenbus_directory(struct xenbus_transaction t,
- const char *dir, const char *node, unsigned int *num);
-void *xenbus_read(struct xenbus_transaction t,
- const char *dir, const char *node, unsigned int *len);
-int xenbus_write(struct xenbus_transaction t,
- const char *dir, const char *node, const char *string);
-int xenbus_mkdir(struct xenbus_transaction t,
- const char *dir, const char *node);
-int xenbus_exists(struct xenbus_transaction t,
- const char *dir, const char *node);
+int xenbus_directory(struct xenbus_transaction t, const char *dir,
+ const char *node, unsigned int *num, char ***result);
+int xenbus_read(struct xenbus_transaction t, const char *dir,
+ const char *node, unsigned int *len, void **result);
+int xenbus_write(struct xenbus_transaction t, const char *dir,
+ const char *node, const char *string);
+int xenbus_mkdir(struct xenbus_transaction t, const char *dir,
+ const char *node);
+int xenbus_exists(struct xenbus_transaction t, const char *dir,
+ const char *node);
int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node);
int xenbus_transaction_start(struct xenbus_transaction *t);
int xenbus_transaction_end(struct xenbus_transaction t, int abort);
-/* Single read and scanf: returns -errno or num scanned if > 0. */
+/*
+ * Single read and scanf: returns errno or zero. If scancountp is
+ * non-null, then number of items scanned is returned in *scanncountp.
+ */
int xenbus_scanf(struct xenbus_transaction t,
- const char *dir, const char *node, const char *fmt, ...)
- __attribute__((format(scanf, 4, 5)));
+ const char *dir, const char *node, int *scancountp, const char *fmt, ...)
+ __attribute__((format(scanf, 5, 6)));
-/* Single printf and write: returns -errno or 0. */
+/* Single printf and write: returns errno or 0. */
int xenbus_printf(struct xenbus_transaction t,
const char *dir, const char *node, const char *fmt, ...)
__attribute__((format(printf, 4, 5)));
-/* Generic read function: NULL-terminated triples of name,
- * sprintf-style type string, and pointer. Returns 0 or errno.*/
+/*
+ * Generic read function: NULL-terminated triples of name,
+ * sprintf-style type string, and pointer. Returns 0 or errno.
+ */
int xenbus_gather(struct xenbus_transaction t, const char *dir, ...);
/* notifer routines for when the xenstore comes up */
@@ -142,7 +147,9 @@ void xs_suspend(void);
void xs_resume(void);
/* Used by xenbus_dev to borrow kernel's store connection. */
-void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
+int xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void **result);
+
+#if 0
#define XENBUS_IS_ERR_READ(str) ({ \
if (!IS_ERR(str) && strlen(str) == 0) { \
@@ -152,12 +159,15 @@ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg);
IS_ERR(str); \
})
-#define XENBUS_EXIST_ERR(err) ((err) == -ENOENT || (err) == -ERANGE)
+#endif
+
+#define XENBUS_EXIST_ERR(err) ((err) == ENOENT || (err) == ERANGE)
+
/**
* Register a watch on the given path, using the given xenbus_watch structure
* for storage, and the given callback function as the callback. Return 0 on
- * success, or -errno on error. On success, the given path will be saved as
+ * success, or errno on error. On success, the given path will be saved as
* watch->node, and remains the caller's to free. On error, watch->node will
* be NULL, the device will switch to XenbusStateClosing, and the error will
* be saved in the store.
@@ -171,7 +181,7 @@ int xenbus_watch_path(device_t dev, char *path,
/**
* Register a watch on the given path/path2, using the given xenbus_watch
* structure for storage, and the given callback function as the callback.
- * Return 0 on success, or -errno on error. On success, the watched path
+ * Return 0 on success, or errno on error. On success, the watched path
* (path/path2) will be saved as watch->node, and becomes the caller's to
* kfree(). On error, watch->node will be NULL, so the caller has nothing to
* free, the device will switch to XenbusStateClosing, and the error will be
@@ -186,7 +196,7 @@ int xenbus_watch_path2(device_t dev, const char *path,
/**
* Advertise in the store a change of the given driver to the given new_state.
* which case this is performed inside its own transaction. Return 0 on
- * success, or -errno on error. On error, the device will switch to
+ * success, or errno on error. On error, the device will switch to
* XenbusStateClosing, and the error will be saved in the store.
*/
int xenbus_switch_state(device_t dev,
@@ -194,16 +204,17 @@ int xenbus_switch_state(device_t dev,
/**
- * Grant access to the given ring_mfn to the peer of the given device. Return
- * 0 on success, or -errno on error. On error, the device will switch to
- * XenbusStateClosing, and the error will be saved in the store.
+ * Grant access to the given ring_mfn to the peer of the given device.
+ * Return 0 on success, or errno on error. On error, the device will
+ * switch to XenbusStateClosing, and the error will be saved in the
+ * store. The grant ring reference is returned in *refp.
*/
-int xenbus_grant_ring(device_t dev, unsigned long ring_mfn);
+int xenbus_grant_ring(device_t dev, unsigned long ring_mfn, int *refp);
/**
* Allocate an event channel for the given xenbus_device, assigning the newly
- * created local port to *port. Return 0 on success, or -errno on error. On
+ * created local port to *port. Return 0 on success, or errno on error. On
* error, the device will switch to XenbusStateClosing, and the error will be
* saved in the store.
*/
@@ -211,7 +222,7 @@ int xenbus_alloc_evtchn(device_t dev, int *port);
/**
- * Free an existing event channel. Returns 0 on success or -errno on error.
+ * Free an existing event channel. Returns 0 on success or errno on error.
*/
int xenbus_free_evtchn(device_t dev, int port);
OpenPOWER on IntegriCloud