843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER START
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The contents of this file are subject to the terms of the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Common Development and Distribution License (the "License").
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You may not use this file except in compliance with the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * or http://www.opensolaris.org/os/licensing.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * See the License for the specific language governing permissions
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and limitations under the License.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When distributing Covered Code, include this CDDL HEADER in each
843e19887f64dde75055cf8842fc4db2171eff45johnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If applicable, add the following below this CDDL HEADER, with the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * fields enclosed by brackets "[]" replaced with your own identifying
843e19887f64dde75055cf8842fc4db2171eff45johnlev * information: Portions Copyright [yyyy] [name of copyright owner]
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * CDDL HEADER END
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Use is subject to license terms.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xenbus_xs.c
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is the kernel equivalent of the "xs" library. We don't need everything
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and we use xenbus_comms for communication.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Copyright (C) 2005 Rusty Russell, IBM Corporation
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This file may be distributed separately from the Linux kernel, or
843e19887f64dde75055cf8842fc4db2171eff45johnlev * incorporated into other software packages, subject to the following license:
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Permission is hereby granted, free of charge, to any person obtaining a copy
843e19887f64dde75055cf8842fc4db2171eff45johnlev * of this source file (the "Software"), to deal in the Software without
843e19887f64dde75055cf8842fc4db2171eff45johnlev * restriction, including without limitation the rights to use, copy, modify,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * merge, publish, distribute, sublicense, and/or sell copies of the Software,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * and to permit persons to whom the Software is furnished to do so, subject to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the following conditions:
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The above copyright notice and this permission notice shall be included in
843e19887f64dde75055cf8842fc4db2171eff45johnlev * all copies or substantial portions of the Software.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
843e19887f64dde75055cf8842fc4db2171eff45johnlev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
843e19887f64dde75055cf8842fc4db2171eff45johnlev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
843e19887f64dde75055cf8842fc4db2171eff45johnlev * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
843e19887f64dde75055cf8842fc4db2171eff45johnlev * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
843e19887f64dde75055cf8842fc4db2171eff45johnlev * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
843e19887f64dde75055cf8842fc4db2171eff45johnlev * IN THE SOFTWARE.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * NOTE: To future maintainers of the Solaris version of this file:
843e19887f64dde75055cf8842fc4db2171eff45johnlev * I found the Linux version of this code to be very disgusting in
843e19887f64dde75055cf8842fc4db2171eff45johnlev * overloading pointers and error codes into void * return values.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The main difference you will find is that all such usage is changed
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to pass pointers to void* to be filled in with return values and
843e19887f64dde75055cf8842fc4db2171eff45johnlev * the functions return error codes.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/errno.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/types.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/sysmacros.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/uio.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/mutex.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/condvar.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/rwlock.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/disp.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/ddi.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/sunddi.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/avintr.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/cmn_err.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <sys/mach_mmu.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <util/sscanf.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define _XSD_ERRORS_DEFINED
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#ifdef XPV_HVM_DRIVER
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#include <sys/xpv_support.h>
551bc2a66868b5cb5be6b70ab9f55515e77a39a9mrj#endif
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <sys/hypervisor.h>
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev#include <sys/taskq.h>
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev#include <sys/sdt.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/sys/xenbus_impl.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/sys/xenbus_comms.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/sys/xendev.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev#include <xen/public/io/xs_wire.h>
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define streq(a, b) (strcmp((a), (b)) == 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define list_empty(list) (list_head(list) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstruct xs_stored_msg {
349b53dd4e695e3d833b5380540385145b2d3ae8Stuart Maybee list_node_t list;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xsd_sockmsg hdr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev union {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Queued replies. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct {
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *body;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } reply;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Queued watch events. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct {
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xenbus_watch *handle;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char **vec;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int vec_size;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } watch;
843e19887f64dde75055cf8842fc4db2171eff45johnlev } un;
843e19887f64dde75055cf8842fc4db2171eff45johnlev};
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic struct xs_handle {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* A list of replies. Currently only one will ever be outstanding. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_t reply_list;
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmutex_t reply_lock;
843e19887f64dde75055cf8842fc4db2171eff45johnlev kcondvar_t reply_cv;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* One request at a time. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmutex_t request_mutex;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Protect transactions against save/restore. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev krwlock_t suspend_lock;
843e19887f64dde75055cf8842fc4db2171eff45johnlev} xs_state;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int last_req_id;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * List of clients wanting a xenstore up notification, and a lock to protect it
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic boolean_t xenstore_up;
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic list_t notify_list;
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic kmutex_t notify_list_lock;
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic taskq_t *xenbus_taskq;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* List of registered watches, and a lock to protect it. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic list_t watches;
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic kmutex_t watches_lock;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* List of pending watch callback events, and a lock to protect it. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic list_t watch_events;
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic kmutex_t watch_events_lock;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Details of the xenwatch callback kernel thread. The thread waits on the
843e19887f64dde75055cf8842fc4db2171eff45johnlev * watch_events_cv for work to do (queued on watch_events list). When it
843e19887f64dde75055cf8842fc4db2171eff45johnlev * wakes up it acquires the xenwatch_mutex before reading the list and
843e19887f64dde75055cf8842fc4db2171eff45johnlev * carrying out work.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic kmutex_t xenwatch_mutex;
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic kcondvar_t watch_events_cv;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int process_msg(void);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevget_error(const char *errorstring)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i == (sizeof (xsd_errors) / sizeof (xsd_errors[0])) - 1) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN,
843e19887f64dde75055cf8842fc4db2171eff45johnlev "XENBUS xen store gave: unknown error %s",
843e19887f64dde75055cf8842fc4db2171eff45johnlev errorstring);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (EINVAL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xsd_errors[i].errnum);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Read a synchronous reply from xenstore. Since we can return early before
843e19887f64dde75055cf8842fc4db2171eff45johnlev * reading a relevant reply, we discard any messages not matching the request
843e19887f64dde75055cf8842fc4db2171eff45johnlev * ID. Caller must free returned message on success.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevread_reply(struct xsd_sockmsg *req_hdr, struct xs_stored_msg **reply)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev extern int do_polled_io;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&xs_state.reply_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (;;) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (list_empty(&xs_state.reply_list)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (interrupts_unleashed && !do_polled_io) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (cv_wait_sig(&xs_state.reply_cv,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &xs_state.reply_lock) == 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.reply_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev *reply = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (EINTR);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else { /* polled mode needed for early probes */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.reply_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) HYPERVISOR_yield();
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) process_msg();
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&xs_state.reply_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev *reply = list_head(&xs_state.reply_list);
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_remove(&xs_state.reply_list, *reply);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((*reply)->hdr.req_id == req_hdr->req_id)
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.reply_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Emergency write. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_debug_write(const char *str, unsigned int count)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xsd_sockmsg msg = { 0 };
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg.type = XS_DEBUG;
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg.len = sizeof ("print") + count + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xb_write(&msg, sizeof (msg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xb_write("print", sizeof ("print"));
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xb_write(str, count);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xb_write("", 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * This is pretty unpleasant. First off, there's the horrible logic around
843e19887f64dde75055cf8842fc4db2171eff45johnlev * suspend_lock and transactions. Also, we can be interrupted either before we
843e19887f64dde75055cf8842fc4db2171eff45johnlev * write a message, or before we receive a reply. A client that wants to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * survive this can't know which case happened. Luckily all clients don't care
843e19887f64dde75055cf8842fc4db2171eff45johnlev * about signals currently, and the alternative (a hard wait on a userspace
843e19887f64dde75055cf8842fc4db2171eff45johnlev * daemon) isn't exactly preferable. Caller must free 'reply' on success.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void **reply)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xsd_sockmsg req_msg = *msg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xs_stored_msg *reply_msg = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (req_msg.type == XS_TRANSACTION_START)
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_enter(&xs_state.suspend_lock, RW_READER);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg->req_id = last_req_id++;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xb_write(msg, sizeof (*msg) + msg->len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (req_msg.type == XS_TRANSACTION_START)
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_exit(&xs_state.suspend_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg->type = XS_ERROR;
843e19887f64dde75055cf8842fc4db2171eff45johnlev *reply = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto out;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = read_reply(msg, &reply_msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (msg->type == XS_TRANSACTION_START)
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_exit(&xs_state.suspend_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev *reply = NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto out;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev *reply = reply_msg->un.reply.body;
843e19887f64dde75055cf8842fc4db2171eff45johnlev *msg = reply_msg->hdr;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (reply_msg->hdr.type == XS_TRANSACTION_END)
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_exit(&xs_state.suspend_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevout:
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (reply_msg != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(reply_msg, sizeof (*reply_msg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Send message to xs, return errcode, rval filled in with pointer
843e19887f64dde75055cf8842fc4db2171eff45johnlev * to kmem_alloc'ed reply.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_talkv(xenbus_transaction_t t,
843e19887f64dde75055cf8842fc4db2171eff45johnlev enum xsd_sockmsg_type type,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const iovec_t *iovec,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int num_vecs,
843e19887f64dde75055cf8842fc4db2171eff45johnlev void **rval,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int *len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xsd_sockmsg msg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xs_stored_msg *reply_msg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *reply;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int i;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg.tx_id = (uint32_t)(unsigned long)t;
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg.type = type;
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg.len = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < num_vecs; i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg.len += iovec[i].iov_len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg.req_id = last_req_id++;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xb_write(&msg, sizeof (msg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < num_vecs; i++) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xb_write(iovec[i].iov_base, iovec[i].iov_len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = read_reply(&msg, &reply_msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev reply = reply_msg->un.reply.body;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (reply_msg->hdr.type == XS_ERROR) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = get_error(reply);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(reply, reply_msg->hdr.len + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev goto out;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (len != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev *len = reply_msg->hdr.len + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(reply_msg->hdr.type == type);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (rval != NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev *rval = reply;
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(reply, reply_msg->hdr.len + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevout:
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(reply_msg, sizeof (*reply_msg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Simplified version of xs_talkv: single message. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_single(xenbus_transaction_t t,
843e19887f64dde75055cf8842fc4db2171eff45johnlev enum xsd_sockmsg_type type,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *string, void **ret,
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int *len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec_t iovec;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec.iov_base = (char *)string;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec.iov_len = strlen(string) + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xs_talkv(t, type, &iovec, 1, ret, len));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic unsigned int
843e19887f64dde75055cf8842fc4db2171eff45johnlevcount_strings(const char *strings, unsigned int len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int num;
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *p;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
843e19887f64dde75055cf8842fc4db2171eff45johnlev num++;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (num);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Return the path to dir with /name appended. Buffer must be kmem_free()'ed */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char *
843e19887f64dde75055cf8842fc4db2171eff45johnlevjoin(const char *dir, const char *name)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *buffer;
843e19887f64dde75055cf8842fc4db2171eff45johnlev size_t slashlen;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev slashlen = streq(name, "") ? 0 : 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev buffer = kmem_alloc(strlen(dir) + slashlen + strlen(name) + 1,
843e19887f64dde75055cf8842fc4db2171eff45johnlev KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) strcpy(buffer, dir);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (slashlen != 0) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) strcat(buffer, "/");
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) strcat(buffer, name);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (buffer);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic char **
843e19887f64dde75055cf8842fc4db2171eff45johnlevsplit(char *strings, unsigned int len, unsigned int *num)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *p, **ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Count the strings. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((*num = count_strings(strings, len - 1)) == 0)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Transfer to one big alloc for easy freeing. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = kmem_alloc(*num * sizeof (char *) + (len - 1), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) memcpy(&ret[*num], strings, len - 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(strings, len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev strings = (char *)&ret[*num];
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (p = strings, *num = 0; p < strings + (len - 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev p += strlen(p) + 1) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret[(*num)++] = p;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevchar **
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_directory(xenbus_transaction_t t,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, unsigned int *num)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *strings, *path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = join(dir, node);
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_single(t, XS_DIRECTORY, path, (void **)&strings, &len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(path, strlen(path) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err != 0 || strings == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* sigh, we lose error code info here */
843e19887f64dde75055cf8842fc4db2171eff45johnlev *num = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (split(strings, len, num));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz/* Check if a path exists. */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczboolean_t
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxenbus_exists(const char *dir, const char *node)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz void *p;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz uint_t n;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if (xenbus_read(XBT_NULL, dir, node, &p, &n) != 0)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (B_FALSE);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz kmem_free(p, n);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (B_TRUE);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz/* Check if a directory path exists. */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczboolean_t
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxenbus_exists_dir(const char *dir, const char *node)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char **d;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int dir_n;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i, len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz d = xenbus_directory(XBT_NULL, dir, node, &dir_n);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (d == NULL)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (B_FALSE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0, len = 0; i < dir_n; i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev len += strlen(d[i]) + 1 + sizeof (char *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(d, len);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (B_TRUE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Get the value of a single file.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Returns a kmem_alloced value in retp: call kmem_free() on it after use.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * len indicates length in bytes.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_read(xenbus_transaction_t t,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, void **retp, unsigned int *len)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = join(dir, node);
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_single(t, XS_READ, path, retp, len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(path, strlen(path) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczint
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowiczxenbus_read_str(const char *dir, const char *node, char **retp)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz{
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz uint_t n;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz int err;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz char *str;
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz /*
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Since we access the xenbus value immediatly we can't be
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * part of a transaction.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz if ((err = xenbus_read(XBT_NULL, dir, node, (void **)&str, &n)) != 0)
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (err);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz ASSERT((str != NULL) && (n > 0));
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz /*
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * Why bother with this? Because xenbus is truly annoying in the
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * fact that when it returns a string, it doesn't guarantee that
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * the memory that holds the string is of size strlen() + 1.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * This forces callers to keep track of the size of the memory
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * containing the string. Ugh. We'll work around this by
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz * re-allocate strings to always be of size strlen() + 1.
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz */
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz *retp = strdup(str);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz kmem_free(str, n);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz return (0);
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz}
7f0b8309074a5d8e9f9d8ffe7aad7bb0b1ee6b1fEdward Pilatowicz
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Write the value of a single file.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Returns err on failure.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_write(xenbus_transaction_t t,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, const char *string)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec_t iovec[2];
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = join(dir, node);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec[0].iov_base = (void *)path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec[0].iov_len = strlen(path) + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec[1].iov_base = (void *)string;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec[1].iov_len = strlen(string);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = xs_talkv(t, XS_WRITE, iovec, 2, NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(path, iovec[0].iov_len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Create a new directory. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_mkdir(xenbus_transaction_t t, const char *dir, const char *node)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = join(dir, node);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = xs_single(t, XS_MKDIR, path, NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(path, strlen(path) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Destroy a file or directory (directories must be empty). */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_rm(xenbus_transaction_t t, const char *dir, const char *node)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev path = join(dir, node);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = xs_single(t, XS_RM, path, NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(path, strlen(path) + 1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Start a transaction: changes by others will not be seen during this
843e19887f64dde75055cf8842fc4db2171eff45johnlev * transaction, and changes will not be visible to others until end.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_transaction_start(xenbus_transaction_t *t)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev void *id_str;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned long id;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_enter(&xs_state.suspend_lock, RW_READER);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_single(XBT_NULL, XS_TRANSACTION_START, "", &id_str, &len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_exit(&xs_state.suspend_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_strtoul((char *)id_str, NULL, 0, &id);
843e19887f64dde75055cf8842fc4db2171eff45johnlev *t = (xenbus_transaction_t)id;
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(id_str, len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * End a transaction.
843e19887f64dde75055cf8842fc4db2171eff45johnlev * If abandon is true, transaction is discarded instead of committed.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_transaction_end(xenbus_transaction_t t, int abort)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev char abortstr[2];
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (abort)
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) strcpy(abortstr, "F");
843e19887f64dde75055cf8842fc4db2171eff45johnlev else
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) strcpy(abortstr, "T");
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_single(t, XS_TRANSACTION_END, abortstr, NULL, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_exit(&xs_state.suspend_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Single read and scanf: returns errno or 0. This can only handle a single
843e19887f64dde75055cf8842fc4db2171eff45johnlev * conversion specifier.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* SCANFLIKE4 */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_scanf(xenbus_transaction_t t,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, const char *fmt, ...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_list ap;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *val;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = xenbus_read(t, dir, node, (void **)&val, &len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_start(ap, fmt);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (vsscanf(val, fmt, ap) != 1)
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = ERANGE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_end(ap);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(val, len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Single printf and write: returns errno or 0. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* PRINTFLIKE4 */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_printf(xenbus_transaction_t t,
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *dir, const char *node, const char *fmt, ...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_list ap;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ret;
843e19887f64dde75055cf8842fc4db2171eff45johnlev#define PRINTF_BUFFER_SIZE 4096
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *printf_buffer;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev printf_buffer = kmem_alloc(PRINTF_BUFFER_SIZE, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_start(ap, fmt);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_end(ap);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(ret <= PRINTF_BUFFER_SIZE-1);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = xenbus_write(t, dir, node, printf_buffer);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(printf_buffer, PRINTF_BUFFER_SIZE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_gather(xenbus_transaction_t t, const char *dir, ...)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_list ap;
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *name;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int ret = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev unsigned int len;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_start(ap, dir);
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev const char *fmt = va_arg(ap, char *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev void *result = va_arg(ap, void *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *p;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = xenbus_read(t, dir, name, (void **)&p, &len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (ret)
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (fmt) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(result != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (sscanf(p, fmt, result) != 1)
843e19887f64dde75055cf8842fc4db2171eff45johnlev ret = EINVAL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(p, len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else
843e19887f64dde75055cf8842fc4db2171eff45johnlev *(char **)result = p;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev va_end(ap);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (ret);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_watch(const char *path, const char *token)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec_t iov[2];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev iov[0].iov_base = (void *)path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iov[0].iov_len = strlen(path) + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iov[1].iov_base = (void *)token;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iov[1].iov_len = strlen(token) + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xs_talkv(XBT_NULL, XS_WATCH, iov, 2, NULL, NULL));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_unwatch(const char *path, const char *token)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev iovec_t iov[2];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev iov[0].iov_base = (char *)path;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iov[0].iov_len = strlen(path) + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iov[1].iov_base = (char *)token;
843e19887f64dde75055cf8842fc4db2171eff45johnlev iov[1].iov_len = strlen(token) + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (xs_talkv(XBT_NULL, XS_UNWATCH, iov, 2, NULL, NULL));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic struct xenbus_watch *
843e19887f64dde75055cf8842fc4db2171eff45johnlevfind_watch(const char *token)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xenbus_watch *i, *cmp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) ddi_strtoul(token, NULL, 16, (unsigned long *)&cmp);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = list_head(&watches); i != NULL; i = list_next(&watches, i))
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (i == cmp)
843e19887f64dde75055cf8842fc4db2171eff45johnlev break;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (i);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Register a xenstore state notify callback */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_register_xenbus_callback(void (*callback)(int))
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xenbus_notify *xbn, *xnp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbn = kmem_alloc(sizeof (struct xenbus_notify), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xbn->notify_func = callback;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&notify_list_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Make sure not already on the list
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnp = list_head(&notify_list);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (; xnp != NULL; xnp = list_next(&notify_list, xnp)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xnp->notify_func == callback) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(xbn, sizeof (struct xenbus_notify));
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&notify_list_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (EEXIST);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnp = xbn;
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_insert_tail(&notify_list, xbn);
843e19887f64dde75055cf8842fc4db2171eff45johnlevdone:
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (xenstore_up)
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnp->notify_func(XENSTORE_UP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&notify_list_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Notify clients of xenstore state
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevdo_notify_callbacks(void *arg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xenbus_notify *xnp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&notify_list_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnp = list_head(&notify_list);
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (; xnp != NULL; xnp = list_next(&notify_list, xnp)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev xnp->notify_func((int)((uintptr_t)arg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&notify_list_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_notify_xenstore_up(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xenstore_up = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) taskq_dispatch(xenbus_taskq, do_notify_callbacks,
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void *)XENSTORE_UP, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_notify_xenstore_down(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev xenstore_up = B_FALSE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) taskq_dispatch(xenbus_taskq, do_notify_callbacks,
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void *)XENSTORE_DOWN, 0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/* Register callback to watch this node. */
843e19887f64dde75055cf8842fc4db2171eff45johnlevint
843e19887f64dde75055cf8842fc4db2171eff45johnlevregister_xenbus_watch(struct xenbus_watch *watch)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Pointer in ascii is the token. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev char token[sizeof (watch) * 2 + 1];
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xenstore_up);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(token, sizeof (token), "%lX", (long)watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_enter(&xs_state.suspend_lock, RW_READER);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&watches_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * May be re-registering a watch if xenstore daemon was restarted
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (find_watch(token) == NULL)
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_insert_tail(&watches, watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&watches_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev DTRACE_XPV3(xenbus__register__watch, const char *, watch->node,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev uintptr_t, watch->callback, struct xenbus_watch *, watch);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_watch(watch->node, token);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Ignore errors due to multiple registration. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if ((err != 0) && (err != EEXIST)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&watches_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_remove(&watches, watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&watches_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_exit(&xs_state.suspend_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevfree_stored_msg(struct xs_stored_msg *msg)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int i, len = 0;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (i = 0; i < msg->un.watch.vec_size; i++)
843e19887f64dde75055cf8842fc4db2171eff45johnlev len += strlen(msg->un.watch.vec[i]) + 1 + sizeof (char *);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(msg->un.watch.vec, len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(msg, sizeof (*msg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevunregister_xenbus_watch(struct xenbus_watch *watch)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xs_stored_msg *msg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char token[sizeof (watch) * 2 + 1];
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(token, sizeof (token), "%lX", (long)watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_enter(&xs_state.suspend_lock, RW_READER);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&watches_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(find_watch(token));
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_remove(&watches, watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&watches_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev DTRACE_XPV3(xenbus__unregister__watch, const char *, watch->node,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev uintptr_t, watch->callback, struct xenbus_watch *, watch);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xs_unwatch(watch->node, token);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err)
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "XENBUS Failed to release watch %s: %d",
843e19887f64dde75055cf8842fc4db2171eff45johnlev watch->node, err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_exit(&xs_state.suspend_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Cancel pending watch events. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&watch_events_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg = list_head(&watch_events);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (msg != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xs_stored_msg *tmp = list_next(&watch_events, msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (msg->un.watch.handle == watch) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_remove(&watch_events, msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev free_stored_msg(msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg = tmp;
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&watch_events_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* Flush any currently-executing callback, unless we are it. :-) */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (mutex_owner(&xenwatch_mutex) != curthread) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&xenwatch_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xenwatch_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_suspend(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_enter(&xs_state.suspend_lock, RW_WRITER);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xb_suspend();
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_resume(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xenbus_watch *watch;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char token[sizeof (watch) * 2 + 1];
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.request_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xb_init();
843e19887f64dde75055cf8842fc4db2171eff45johnlev xb_setup_intr();
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /* No need for watches_lock: the suspend_lock is sufficient. */
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (watch = list_head(&watches); watch != NULL;
843e19887f64dde75055cf8842fc4db2171eff45johnlev watch = list_next(&watches, watch)) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) snprintf(token, sizeof (token), "%lX", (long)watch);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) xs_watch(watch->node, token);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_exit(&xs_state.suspend_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenwatch_thread(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xs_stored_msg *msg;
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev struct xenbus_watch *watch;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev for (;;) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&watch_events_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev while (list_empty(&watch_events))
843e19887f64dde75055cf8842fc4db2171eff45johnlev cv_wait(&watch_events_cv, &watch_events_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg = list_head(&watch_events);
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev ASSERT(msg != NULL);
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev list_remove(&watch_events, msg);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev watch = msg->un.watch.handle;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&watch_events_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev mutex_enter(&xenwatch_mutex);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev DTRACE_XPV4(xenbus__fire__watch,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev const char *, watch->node,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev uintptr_t, watch->callback,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev struct xenbus_watch *, watch,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev const char *, msg->un.watch.vec[XS_WATCH_PATH]);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev watch->callback(watch, (const char **)msg->un.watch.vec,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev msg->un.watch.vec_size);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev
1d03c31e0733adea0edef54f0d5d2ea9639ecd2ajohnlev free_stored_msg(msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xenwatch_mutex);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic int
843e19887f64dde75055cf8842fc4db2171eff45johnlevprocess_msg(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev struct xs_stored_msg *msg;
843e19887f64dde75055cf8842fc4db2171eff45johnlev char *body;
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err, mlen;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg = kmem_alloc(sizeof (*msg), KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xb_read(&msg->hdr, sizeof (msg->hdr));
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(msg, sizeof (*msg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mlen = msg->hdr.len + 1;
843e19887f64dde75055cf8842fc4db2171eff45johnlev body = kmem_alloc(mlen, KM_SLEEP);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = xb_read(body, msg->hdr.len);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(body, mlen);
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(msg, sizeof (*msg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev body[mlen - 1] = '\0';
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (msg->hdr.type == XS_WATCH_EVENT) {
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev const char *token;
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg->un.watch.vec = split(body, msg->hdr.len + 1,
843e19887f64dde75055cf8842fc4db2171eff45johnlev &msg->un.watch.vec_size);
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (msg->un.watch.vec == NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev kmem_free(msg, sizeof (*msg));
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (EIO);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&watches_lock);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev token = msg->un.watch.vec[XS_WATCH_TOKEN];
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev if ((msg->un.watch.handle = find_watch(token)) != NULL) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&watch_events_lock);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev DTRACE_XPV4(xenbus__enqueue__watch,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev const char *, msg->un.watch.handle->node,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev uintptr_t, msg->un.watch.handle->callback,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev struct xenbus_watch *, msg->un.watch.handle,
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev const char *, msg->un.watch.vec[XS_WATCH_PATH]);
ab4a9beb2e4d596be0b3288c7d92919e27781b57johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_insert_tail(&watch_events, msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev cv_broadcast(&watch_events_cv);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&watch_events_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev free_stored_msg(msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&watches_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev } else {
843e19887f64dde75055cf8842fc4db2171eff45johnlev msg->un.reply.body = body;
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_enter(&xs_state.reply_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_insert_tail(&xs_state.reply_list, msg);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_exit(&xs_state.reply_lock);
843e19887f64dde75055cf8842fc4db2171eff45johnlev cv_signal(&xs_state.reply_cv);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev return (0);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxenbus_thread(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev int err;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon /*
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon * We have to wait for interrupts to be ready, so we don't clash
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon * with the polled-IO code in read_reply().
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon */
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon while (!interrupts_unleashed)
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon delay(10);
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon
fc621ef0ea706feeefe877e29c056b46fd3915b4John Levon for (;;) {
843e19887f64dde75055cf8842fc4db2171eff45johnlev err = process_msg();
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (err)
843e19887f64dde75055cf8842fc4db2171eff45johnlev cmn_err(CE_WARN, "XENBUS error %d while reading "
843e19887f64dde75055cf8842fc4db2171eff45johnlev "message", err);
843e19887f64dde75055cf8842fc4db2171eff45johnlev }
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev/*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * When setting up xenbus, dom0 and domU have to take different paths, which
843e19887f64dde75055cf8842fc4db2171eff45johnlev * makes this code a little confusing. For dom0:
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xs_early_init - mutex init only
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xs_dom0_init - called on xenbus dev attach: set up our xenstore page and
843e19887f64dde75055cf8842fc4db2171eff45johnlev * event channel; start xenbus threads for responding to interrupts.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * And for domU:
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xs_early_init - mutex init; set up our xenstore page and event channel
843e19887f64dde75055cf8842fc4db2171eff45johnlev * xs_domu_init - installation of IRQ handler; start xenbus threads.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * We need an early init on domU so we can use xenbus in polled mode to
843e19887f64dde75055cf8842fc4db2171eff45johnlev * discover devices, VCPUs etc.
843e19887f64dde75055cf8842fc4db2171eff45johnlev *
843e19887f64dde75055cf8842fc4db2171eff45johnlev * On resume, we use xb_init() and xb_setup_intr() to restore xenbus to a
843e19887f64dde75055cf8842fc4db2171eff45johnlev * working state.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_early_init(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_create(&xs_state.reply_list, sizeof (struct xs_stored_msg),
843e19887f64dde75055cf8842fc4db2171eff45johnlev offsetof(struct xs_stored_msg, list));
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_create(&watch_events, sizeof (struct xs_stored_msg),
843e19887f64dde75055cf8842fc4db2171eff45johnlev offsetof(struct xs_stored_msg, list));
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_create(&watches, sizeof (struct xenbus_watch),
843e19887f64dde75055cf8842fc4db2171eff45johnlev offsetof(struct xenbus_watch, list));
843e19887f64dde75055cf8842fc4db2171eff45johnlev list_create(&notify_list, sizeof (struct xenbus_notify),
843e19887f64dde75055cf8842fc4db2171eff45johnlev offsetof(struct xenbus_notify, list));
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(&xs_state.reply_lock, NULL, MUTEX_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(&xs_state.request_mutex, NULL, MUTEX_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev mutex_init(&notify_list_lock, NULL, MUTEX_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev rw_init(&xs_state.suspend_lock, NULL, RW_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev cv_init(&xs_state.reply_cv, NULL, CV_DEFAULT, NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (DOMAIN_IS_INITDOMAIN(xen_info))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xb_init();
843e19887f64dde75055cf8842fc4db2171eff45johnlev xenstore_up = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevstatic void
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_thread_init(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) thread_create(NULL, 0, xenwatch_thread, NULL, 0, &p0,
843e19887f64dde75055cf8842fc4db2171eff45johnlev TS_RUN, minclsyspri);
843e19887f64dde75055cf8842fc4db2171eff45johnlev (void) thread_create(NULL, 0, xenbus_thread, NULL, 0, &p0,
843e19887f64dde75055cf8842fc4db2171eff45johnlev TS_RUN, minclsyspri);
843e19887f64dde75055cf8842fc4db2171eff45johnlev xenbus_taskq = taskq_create("xenbus_taskq", 1,
843e19887f64dde75055cf8842fc4db2171eff45johnlev maxclsyspri - 1, 1, 1, TASKQ_PREPOPULATE);
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(xenbus_taskq != NULL);
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_domu_init(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (DOMAIN_IS_INITDOMAIN(xen_info))
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * Add interrupt handler for xenbus now, must wait till after
843e19887f64dde75055cf8842fc4db2171eff45johnlev * psm module is loaded. All use of xenbus is in polled mode
843e19887f64dde75055cf8842fc4db2171eff45johnlev * until xs_init is called since it is what kicks off the xs
843e19887f64dde75055cf8842fc4db2171eff45johnlev * server threads.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev xs_thread_init();
843e19887f64dde75055cf8842fc4db2171eff45johnlev xb_setup_intr();
843e19887f64dde75055cf8842fc4db2171eff45johnlev}
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlevvoid
843e19887f64dde75055cf8842fc4db2171eff45johnlevxs_dom0_init(void)
843e19887f64dde75055cf8842fc4db2171eff45johnlev{
843e19887f64dde75055cf8842fc4db2171eff45johnlev static boolean_t initialized = B_FALSE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev ASSERT(DOMAIN_IS_INITDOMAIN(xen_info));
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev /*
843e19887f64dde75055cf8842fc4db2171eff45johnlev * The xenbus driver might be re-attaching.
843e19887f64dde75055cf8842fc4db2171eff45johnlev */
843e19887f64dde75055cf8842fc4db2171eff45johnlev if (initialized)
843e19887f64dde75055cf8842fc4db2171eff45johnlev return;
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev xb_init();
843e19887f64dde75055cf8842fc4db2171eff45johnlev xs_thread_init();
843e19887f64dde75055cf8842fc4db2171eff45johnlev xb_setup_intr();
843e19887f64dde75055cf8842fc4db2171eff45johnlev
843e19887f64dde75055cf8842fc4db2171eff45johnlev initialized = B_TRUE;
843e19887f64dde75055cf8842fc4db2171eff45johnlev}