[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH v3 04/10] plat/xen: Add support for communication with Xenstore daemon
Reviewed-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx> I will add two minor modifications here (see inline), and push it. The third is proposed for the follow up (if you will like it). Costin Lupu <costin.lupu@xxxxxxxxx> writes: > Add support for communication with Xenstore daemon via the shared > page. In Unikraft, the incoming messages are processed by the > Xenstore thread. > > Signed-off-by: Costin Lupu <costin.lupu@xxxxxxxxx> > --- > plat/xen/Makefile.uk | 1 + > plat/xen/xenbus/xenbus.c | 8 + > plat/xen/xenbus/xs_comms.c | 608 > +++++++++++++++++++++++++++++++++++++++++++++ > plat/xen/xenbus/xs_comms.h | 64 +++++ > 4 files changed, 681 insertions(+) > create mode 100644 plat/xen/xenbus/xs_comms.c > create mode 100644 plat/xen/xenbus/xs_comms.h > > diff --git a/plat/xen/Makefile.uk b/plat/xen/Makefile.uk > index b8c70e1..2703a54 100644 > --- a/plat/xen/Makefile.uk > +++ b/plat/xen/Makefile.uk > @@ -79,4 +79,5 @@ LIBXENBUS_ASINCLUDES-y += $(LIBXENPLAT_ASINCLUDES-y) > LIBXENBUS_CFLAGS-y += $(LIBXENPLAT_CFLAGS-y) > LIBXENBUS_CINCLUDES-y += $(LIBXENPLAT_CINCLUDES-y) > LIBXENBUS_SRCS-y += $(LIBXENPLAT_BASE)/xenbus/xenbus.c > +LIBXENBUS_SRCS-y += $(LIBXENPLAT_BASE)/xenbus/xs_comms.c > endif > diff --git a/plat/xen/xenbus/xenbus.c b/plat/xen/xenbus/xenbus.c > index 1bc57c3..a20546b 100644 > --- a/plat/xen/xenbus/xenbus.c > +++ b/plat/xen/xenbus/xenbus.c > @@ -43,6 +43,7 @@ > #include <uk/errptr.h> > #include <uk/assert.h> > #include <xenbus/xenbus.h> > +#include "xs_comms.h" > > static struct xenbus_handler xbh; > > @@ -86,6 +87,13 @@ static int xenbus_init(struct uk_alloc *a) > > xbh.a = a; > > + ret = xs_comms_init(); > + if (ret) { > + uk_printd(DLVL_ERR, > + "Error initializing Xenstore communication."); > + return ret; > + } > + > UK_TAILQ_FOREACH_SAFE(drv, &xbh.drv_list, next, drv_next) { > if (drv->init) { > ret = drv->init(a); > diff --git a/plat/xen/xenbus/xs_comms.c b/plat/xen/xenbus/xs_comms.c > new file mode 100644 > index 0000000..61a38b7 > --- /dev/null > +++ b/plat/xen/xenbus/xs_comms.c > @@ -0,0 +1,608 @@ > +/* SPDX-License-Identifier: BSD-3-Clause */ > +/* > + * Authors: Steven Smith (sos22@xxxxxxxxx) > + * Grzegorz Milos (gm281@xxxxxxxxx) > + * John D. Ramsdell > + * Costin Lupu <costin.lupu@xxxxxxxxx> > + * > + * Copyright (c) 2006, Cambridge University > + * 2018, NEC Europe Ltd., NEC Corporation. All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. Neither the name of the copyright holder nor the names of its > + * contributors may be used to endorse or promote products derived from > + * this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS > IS" > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > + * POSSIBILITY OF SUCH DAMAGE. > + * > + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. > + */ > +/* > + * Communication with Xenstore > + * Ported from Mini-OS xenbus.c > + */ > + > +#include <string.h> > +#include <uk/errptr.h> > +#include <uk/bitmap.h> > +#include <uk/wait.h> > +#include <uk/arch/spinlock.h> > +#include <common/events.h> > +#include <xen-x86/mm.h> > +#include <xen-x86/setup.h> > +#include "xs_comms.h" > + > + > +/* > + * Xenstore handler structure > + */ > +struct xs_handler { > + /**< Communication: event channel */ > + evtchn_port_t evtchn; > + /**< Communication: shared memory */ > + struct xenstore_domain_interface *buf; > + /**< Thread processing incoming xs replies */ > + struct uk_thread *thread; > + /**< Waiting queue for notifying incoming xs replies */ > + struct uk_waitq waitq; > +}; > + > +static struct xs_handler xsh = { > + .waitq = __WAIT_QUEUE_INITIALIZER(xsh.waitq), > +}; > + > +/* > + * In-flight request structure. > + */ > +struct xs_request { > + /**< used when queueing requests */ > + UK_TAILQ_ENTRY(struct xs_request) next; > + /**< Waiting queue for incoming reply notification */ > + struct uk_waitq waitq; > + /**< Request header */ > + struct xsd_sockmsg hdr; > + /**< Request payload iovecs */ > + const struct xs_iovec *payload_iovecs; > + /**< Received reply */ > + struct { > + /**< Reply string + size */ > + struct xs_iovec iovec; > + /**< Error number */ > + int errornum; > + /**< Non-zero for incoming replies */ > + int recvd; > + } reply; > +}; > +UK_TAILQ_HEAD(xs_request_list, struct xs_request); > + > +/* > + * Pool of in-flight requests. > + * Request IDs are reused, hence the limited set of entries. > + */ > +struct xs_request_pool { > + /**< Number of live requests */ > + __u32 num_live; > + /**< Last probed request index */ > + __u32 last_probed; > + /**< Lock */ > + spinlock_t lock; > + /**< Waiting queue for 'not-full' notifications */ > + struct uk_waitq waitq; > + /**< Queue for requests to be sent */ > + struct xs_request_list queued; > + > + /* Map size is power of 2 */ > +#define XS_REQ_POOL_SHIFT 5 > +#define XS_REQ_POOL_SIZE (1 << XS_REQ_POOL_SHIFT) I will move these defines outside of structure declaration to the beginning of the file > + unsigned long entries_bm[UK_BITS_TO_LONGS(XS_REQ_POOL_SIZE) > + * sizeof(long)]; > + /**< Entries */ > + struct xs_request entries[XS_REQ_POOL_SIZE]; > +}; > + > +static struct xs_request_pool xs_req_pool; > + > +static void xs_request_pool_init(struct xs_request_pool *pool) > +{ > + struct xs_request *xs_req; > + > + pool->num_live = 0; > + ukarch_spin_lock_init(&pool->lock); > + uk_waitq_init(&pool->waitq); > + UK_TAILQ_INIT(&pool->queued); > + uk_bitmap_zero(pool->entries_bm, XS_REQ_POOL_SIZE); Missing initialization of last_probed. Of course this will work, since a static variable is passed into this function, and static variables are initialized with zeroes. But since you initializing the bitmap (which, btw, is a reasonable thing to do, because we can't assume that the pointer comes pre-zeroed), it makes sense to initialize last_probed as well. I will add this line before pushing. > + for (int i = 0; i < XS_REQ_POOL_SIZE; i++) { > + xs_req = &pool->entries[i]; > + xs_req->hdr.req_id = i; > + uk_waitq_init(&xs_req->waitq); > + } > +} > + > +/* > + * Allocate an identifier for a Xenstore request. > + * Blocks if none are available. > + */ > +static struct xs_request *xs_request_get(void) > +{ > + unsigned long entry_idx; > + > + /* wait for an available entry */ > + while (1) { > + ukarch_spin_lock(&xs_req_pool.lock); > + > + if (xs_req_pool.num_live < XS_REQ_POOL_SIZE) > + break; > + > + ukarch_spin_unlock(&xs_req_pool.lock); > + > + uk_waitq_wait_event(&xs_req_pool.waitq, > + (xs_req_pool.num_live < XS_REQ_POOL_SIZE)); > + } > + > + /* find an available entry */ > + entry_idx = > + uk_find_next_zero_bit(xs_req_pool.entries_bm, XS_REQ_POOL_SIZE, > + (xs_req_pool.last_probed + 1) % XS_REQ_POOL_SIZE); > + > + if (entry_idx == XS_REQ_POOL_SIZE) > + entry_idx = uk_find_next_zero_bit(xs_req_pool.entries_bm, > + XS_REQ_POOL_SIZE, 0); > + > + uk_set_bit(entry_idx, xs_req_pool.entries_bm); > + xs_req_pool.last_probed = entry_idx; What you did here is totally fine. Just a tiny little suggestion. Rename 'last_probed' to 'hint', and assign here xs_req_pool.hint = (xs_req_pool.last_probed + 1) % XS_REQ_POOL_SIZE); This an idea for next patches. If you like it > + xs_req_pool.num_live++; > + > + ukarch_spin_unlock(&xs_req_pool.lock); > + > + return &xs_req_pool.entries[entry_idx]; > +} > + > +/* Release a request identifier */ > +static void xs_request_put(struct xs_request *xs_req) > +{ > + __u32 reqid = xs_req->hdr.req_id; > + > + ukarch_spin_lock(&xs_req_pool.lock); > + > + UK_ASSERT(ukarch_test_bit(reqid, xs_req_pool.entries_bm) == 1); > + > + uk_clear_bit(reqid, xs_req_pool.entries_bm); > + xs_req_pool.num_live--; > + > + if (xs_req_pool.num_live == XS_REQ_POOL_SIZE - 1) > + uk_waitq_wake_up(&xs_req_pool.waitq); > + > + ukarch_spin_unlock(&xs_req_pool.lock); > +} > + > +static struct xs_request *xs_request_peek(void) > +{ > + struct xs_request *xs_req; > + > + ukarch_spin_lock(&xs_req_pool.lock); > + xs_req = UK_TAILQ_FIRST(&xs_req_pool.queued); > + ukarch_spin_unlock(&xs_req_pool.lock); > + > + return xs_req; > +} > + > +static void xs_request_enqueue(struct xs_request *xs_req) > +{ > + ukarch_spin_lock(&xs_req_pool.lock); > + UK_TAILQ_INSERT_TAIL(&xs_req_pool.queued, xs_req, next); > + ukarch_spin_unlock(&xs_req_pool.lock); > +} > + > +static struct xs_request *xs_request_dequeue(void) > +{ > + struct xs_request *xs_req; > + > + ukarch_spin_lock(&xs_req_pool.lock); > + xs_req = UK_TAILQ_FIRST(&xs_req_pool.queued); > + if (xs_req) > + UK_TAILQ_REMOVE(&xs_req_pool.queued, xs_req, next); > + ukarch_spin_unlock(&xs_req_pool.lock); > + > + return xs_req; > +} > + > +static int xs_avail_to_read(void) > +{ > + return (xsh.buf->rsp_prod != xsh.buf->rsp_cons); > +} > + > +static int xs_avail_space_for_read(unsigned int size) > +{ > + return (xsh.buf->rsp_prod - xsh.buf->rsp_cons >= size); > +} > + > +static int xs_avail_to_write(void) > +{ > + return (xsh.buf->req_prod - xsh.buf->req_cons != XENSTORE_RING_SIZE && > + !UK_TAILQ_EMPTY(&xs_req_pool.queued)); > +} > + > +static int xs_avail_space_for_write(unsigned int size) > +{ > + return (xsh.buf->req_prod - xsh.buf->req_cons + > + size <= XENSTORE_RING_SIZE); > +} > + > +static int xs_avail_work(void) > +{ > + return (xs_avail_to_read() || xs_avail_to_write()); > +} > + > +/* > + * Send request to Xenstore. A request is made of multiple iovecs which are > + * preceded by a single iovec referencing the request header. The iovecs are > + * seen by Xenstore as if sent atomically. This can block. > + */ > +static int xs_msg_write(struct xsd_sockmsg *xsd_req, > + const struct xs_iovec *iovec) > +{ > + XENSTORE_RING_IDX prod; > + const struct xs_iovec *crnt_iovec; > + struct xs_iovec hdr_iovec; > + unsigned int req_size, req_off; > + unsigned int buf_off; > + unsigned int this_chunk_len; > + int rc; > + > + req_size = sizeof(*xsd_req) + xsd_req->len; > + if (req_size > XENSTORE_RING_SIZE) > + return -ENOSPC; > + > + if (!xs_avail_space_for_write(req_size)) > + return -ENOSPC; > + > + /* We must write requests after reading the consumer index. */ > + mb(); > + > + /* > + * We're now guaranteed to be able to send the message > + * without overflowing the ring. Do so. > + */ > + > + hdr_iovec.data = xsd_req; > + hdr_iovec.len = sizeof(*xsd_req); > + > + /* The batched iovecs are preceded by a single header. */ > + crnt_iovec = &hdr_iovec; > + > + prod = xsh.buf->req_prod; > + req_off = 0; > + buf_off = 0; > + while (req_off < req_size) { > + this_chunk_len = MIN(crnt_iovec->len - buf_off, > + XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod)); > + > + memcpy( > + (char *) xsh.buf->req + MASK_XENSTORE_IDX(prod), > + (char *) crnt_iovec->data + buf_off, > + this_chunk_len > + ); > + > + prod += this_chunk_len; > + req_off += this_chunk_len; > + buf_off += this_chunk_len; > + > + if (buf_off == crnt_iovec->len) { > + buf_off = 0; > + if (crnt_iovec == &hdr_iovec) > + crnt_iovec = iovec; > + else > + crnt_iovec++; > + } > + } > + > + uk_printd(DLVL_EXTRA, "Complete main loop of %s.\n", __func__); > + UK_ASSERT(buf_off == 0); > + UK_ASSERT(req_off == req_size); > + UK_ASSERT(prod <= xsh.buf->req_cons + XENSTORE_RING_SIZE); > + > + /* Remote must see entire message before updating indexes */ > + wmb(); > + > + xsh.buf->req_prod += req_size; > + > + /* Send evtchn to notify remote */ > + rc = notify_remote_via_evtchn(xsh.evtchn); > + UK_ASSERT(rc == 0); > + > + return 0; > +} > + > +int xs_msg_reply(enum xsd_sockmsg_type msg_type, xenbus_transaction_t xbt, > + const struct xs_iovec *req_iovecs, int req_iovecs_num, > + struct xs_iovec *rep_iovec) > +{ > + struct xs_request *xs_req; > + int err; > + > + if (req_iovecs == NULL) > + return -EINVAL; > + > + xs_req = xs_request_get(); > + xs_req->hdr.type = msg_type; > + /* req_id was set on pool init */ > + xs_req->hdr.tx_id = xbt; > + xs_req->hdr.len = 0; > + for (int i = 0; i < req_iovecs_num; i++) > + xs_req->hdr.len += req_iovecs[i].len; > + > + xs_req->payload_iovecs = req_iovecs; > + xs_req->reply.recvd = 0; > + > + /* enqueue the request */ > + xs_request_enqueue(xs_req); > + /* wake xenstore thread to send it */ > + uk_waitq_wake_up(&xsh.waitq); > + > + /* wait reply */ > + uk_waitq_wait_event(&xs_req->waitq, > + xs_req->reply.recvd != 0); > + > + err = -xs_req->reply.errornum; > + if (err == 0) { > + if (rep_iovec) > + *rep_iovec = xs_req->reply.iovec; > + else > + free(xs_req->reply.iovec.data); > + } > + > + xs_request_put(xs_req); > + > + return err; > +} > + > +void xs_send(void) > +{ > + struct xs_request *xs_req; > + int err; > + > + xs_req = xs_request_peek(); > + while (xs_req != NULL) { > + err = xs_msg_write(&xs_req->hdr, xs_req->payload_iovecs); > + if (err) { > + if (err != -ENOSPC) > + uk_printd(DLVL_WARN, > + "Error sending message err=%d\n", err); > + break; > + } > + > + /* remove it from queue */ > + xs_request_dequeue(); > + > + xs_req = xs_request_peek(); > + } > +} > + > +/* > + * Converts a Xenstore reply error to a positive error number. > + * Returns 0 if the reply is successful. > + */ > +static int reply_to_errno(const char *reply) > +{ > + int err = 0; > + > + for (int i = 0; i < (int) ARRAY_SIZE(xsd_errors); i++) { > + if (!strcmp(reply, xsd_errors[i].errstring)) { > + err = xsd_errors[i].errnum; > + goto out; > + } > + } > + > + uk_printd(DLVL_WARN, "Unknown Xenstore error: %s\n", reply); > + err = EINVAL; > + > +out: > + return err; > +} > + > +/* Process an incoming xs reply */ > +static void process_reply(struct xsd_sockmsg *hdr, char *payload) > +{ > + struct xs_request *xs_req; > + > + if (!ukarch_test_bit(hdr->req_id, xs_req_pool.entries_bm)) { > + uk_printd(DLVL_WARN, "Invalid reply id=%d\n", hdr->req_id); > + free(payload); > + return; > + } > + > + xs_req = &xs_req_pool.entries[hdr->req_id]; > + > + if (hdr->type == XS_ERROR) { > + xs_req->reply.errornum = reply_to_errno(payload); > + free(payload); > + > + } else if (hdr->type != xs_req->hdr.type) { > + uk_printd(DLVL_WARN, > + "Mismatching message type: %d\n", hdr->type); > + free(payload); > + return; > + > + } else { > + /* set reply */ > + xs_req->reply.iovec.data = payload; > + xs_req->reply.iovec.len = hdr->len; > + xs_req->reply.errornum = 0; > + } > + > + xs_req->reply.recvd = 1; > + > + /* notify waiting requester */ > + uk_waitq_wake_up(&xs_req->waitq); > +} > + > +/* Process an incoming xs watch event */ > +static void process_watch_event(char *watch_msg) > +{ > + /* TODO */ > +} > + > +static void memcpy_from_ring(const char *ring, char *dest, int off, int len) > +{ > + int c1, c2; > + > + c1 = MIN(len, XENSTORE_RING_SIZE - off); > + c2 = len - c1; > + > + memcpy(dest, ring + off, c1); > + if (c2) > + memcpy(dest + c1, ring, c2); > +} > + > +static void xs_msg_read(struct xsd_sockmsg *hdr) > +{ > + XENSTORE_RING_IDX cons; > + char *payload; > + > + payload = malloc(hdr->len + 1); > + if (payload == NULL) { > + uk_printd(DLVL_WARN, > + "No memory available for saving Xenstore message!\n"); > + return; > + } > + > + cons = xsh.buf->rsp_cons; > + > + /* copy payload */ > + memcpy_from_ring( > + xsh.buf->rsp, > + payload, > + MASK_XENSTORE_IDX(cons + sizeof(*hdr)), > + hdr->len > + ); > + payload[hdr->len] = '\0'; > + > + /* Remote must not see available space until we've copied the reply */ > + mb(); > + xsh.buf->rsp_cons += sizeof(*hdr) + hdr->len; > + > + if (xsh.buf->rsp_prod - cons >= XENSTORE_RING_SIZE) > + notify_remote_via_evtchn(xsh.evtchn); > + > + if (hdr->type == XS_WATCH_EVENT) > + process_watch_event(payload); > + else > + process_reply(hdr, payload); > +} > + > +static void xs_recv(void) > +{ > + struct xsd_sockmsg msg; > + > + while (1) { > + uk_printd(DLVL_EXTRA, "Rsp_cons %d, rsp_prod %d.\n", > + xsh.buf->rsp_cons, xsh.buf->rsp_prod); > + > + if (!xs_avail_space_for_read(sizeof(msg))) > + break; > + > + /* Make sure data is read after reading the indexes */ > + rmb(); > + > + /* copy the message header */ > + memcpy_from_ring( > + xsh.buf->rsp, > + (char *) &msg, > + MASK_XENSTORE_IDX(xsh.buf->rsp_cons), > + sizeof(msg) > + ); > + > + uk_printd(DLVL_EXTRA, "Msg len %lu, %u avail, id %u.\n", > + msg.len + sizeof(msg), > + xsh.buf->rsp_prod - xsh.buf->rsp_cons, > + msg.req_id); > + > + if (!xs_avail_space_for_read(sizeof(msg) + msg.len)) > + break; > + > + /* Make sure data is read after reading the indexes */ > + rmb(); > + > + uk_printd(DLVL_EXTRA, "Message is good.\n"); > + xs_msg_read(&msg); > + } > +} > + > +static void xs_thread_func(void *ign __unused) > +{ > + for (;;) { > + uk_waitq_wait_event(&xsh.waitq, xs_avail_work()); > + > + if (xs_avail_to_write()) > + xs_send(); > + > + if (xs_avail_to_read()) > + xs_recv(); > + } > +} > + > +static void xs_evtchn_handler(evtchn_port_t port, > + struct __regs *regs __unused, void *ign __unused) > +{ > + UK_ASSERT(xsh.evtchn == port); > + uk_waitq_wake_up(&xsh.waitq); > +} > + > +int xs_comms_init(void) > +{ > + struct uk_thread *thread; > + evtchn_port_t port; > + > + xs_request_pool_init(&xs_req_pool); > + > + uk_waitq_init(&xsh.waitq); > + > + thread = uk_thread_create("xenstore", xs_thread_func, NULL); > + if (PTRISERR(thread)) > + return PTR2ERR(thread); > + > + xsh.thread = thread; > + > + xsh.evtchn = HYPERVISOR_start_info->store_evtchn; > + xsh.buf = mfn_to_virt(HYPERVISOR_start_info->store_mfn); > + > + port = bind_evtchn(xsh.evtchn, xs_evtchn_handler, NULL); > + UK_ASSERT(port == xsh.evtchn); > + unmask_evtchn(xsh.evtchn); > + > + uk_printd(DLVL_INFO, > + "Xenstore connection initialised on port %d, buf %p (mfn > %#lx)\n", > + port, xsh.buf, HYPERVISOR_start_info->store_mfn); > + > + return 0; > +} > + > +void xs_comms_fini(void) > +{ > + mask_evtchn(xsh.evtchn); > + unbind_evtchn(xsh.evtchn); > + > + xsh.buf = NULL; > + > + /* TODO stop thread, instead of killing it */ > + uk_thread_destroy(xsh.thread); > + xsh.thread = NULL; > +} > diff --git a/plat/xen/xenbus/xs_comms.h b/plat/xen/xenbus/xs_comms.h > new file mode 100644 > index 0000000..9b558d0 > --- /dev/null > +++ b/plat/xen/xenbus/xs_comms.h > @@ -0,0 +1,64 @@ > +/* SPDX-License-Identifier: BSD-3-Clause */ > +/* > + * Authors: Costin Lupu <costin.lupu@xxxxxxxxx> > + * > + * Copyright (c) 2018, NEC Europe Ltd., NEC Corporation. All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * 3. Neither the name of the copyright holder nor the names of its > + * contributors may be used to endorse or promote products derived from > + * this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS > IS" > + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE > + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR > + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF > + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS > + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN > + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) > + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE > + * POSSIBILITY OF SUCH DAMAGE. > + * > + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. > + */ > + > +#ifndef __XS_COMMS_H__ > +#define __XS_COMMS_H__ > + > +#include <xen/io/xs_wire.h> > +#include <xenbus/xs.h> > + > +int xs_comms_init(void); > +void xs_comms_fini(void); > + > +struct xs_iovec { > + void *data; > + unsigned int len; > +}; > + > +/* > + * Sends a message to Xenstore and blocks waiting for a reply. > + * The reply is malloc'ed and should be freed by the caller. > + * > + * @param msg_type Xenstore message type > + * @param xbt Xenbus transaction id > + * @param req_iovecs Array of request strings buffers > + * @param req_iovecs_num Request strings buffers number > + * @param rep_iovec Incoming reply string buffer (optional) > + * @return 0 on success, a negative errno value on error. > + */ > +int xs_msg_reply(enum xsd_sockmsg_type msg_type, xenbus_transaction_t xbt, > + const struct xs_iovec *req_iovecs, int req_iovecs_num, > + struct xs_iovec *rep_iovec); > + > +#endif /* __XS_COMMS_H__ */ > -- > 2.11.0 > -- Yuri Volchkov Software Specialist NEC Europe Ltd Kurfürsten-Anlage 36 D-69115 Heidelberg _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |