diff --git a/sys/xen/xenbus/xenbus.c b/sys/xen/xenbus/xenbus.c index c59d4aec4532..415279ec2311 100644 --- a/sys/xen/xenbus/xenbus.c +++ b/sys/xen/xenbus/xenbus.c @@ -1,259 +1,217 @@ /****************************************************************************** * Copyright (C) 2005 XenSource Ltd * * This file may be distributed separately from the Linux kernel, or * incorporated into other software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /** * \file xenbus.c * * \brief Client-facing interface for the Xenbus driver. * * In other words, the interface between the Xenbus and the device-specific * code, be it the frontend or the backend of that driver. */ #if 0 #define DPRINTK(fmt, args...) \ printk("xenbus_client (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args) #else #define DPRINTK(fmt, args...) ((void)0) #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include MALLOC_DEFINE(M_XENBUS, "xenbus", "XenBus Support"); /*------------------------- Private Functions --------------------------------*/ /** * \brief Construct the error path corresponding to the given XenBus * device. * * \param dev The XenBus device for which we are constructing an error path. * * \return On success, the contructed error path. Otherwise NULL. * * It is the caller's responsibility to free any returned error path * node using the M_XENBUS malloc type. */ static char * error_path(device_t dev) { char *path_buffer = malloc(strlen("error/") + strlen(xenbus_get_node(dev)) + 1,M_XENBUS, M_WAITOK); strcpy(path_buffer, "error/"); strcpy(path_buffer + strlen("error/"), xenbus_get_node(dev)); return (path_buffer); } /*--------------------------- Public Functions -------------------------------*/ /*-------- API comments for these methods can be found in xenbusvar.h --------*/ const char * xenbus_strstate(XenbusState state) { static const char *const name[] = { [ XenbusStateUnknown ] = "Unknown", [ XenbusStateInitialising ] = "Initialising", [ XenbusStateInitWait ] = "InitWait", [ XenbusStateInitialised ] = "Initialised", [ XenbusStateConnected ] = "Connected", [ XenbusStateClosing ] = "Closing", [ XenbusStateClosed ] = "Closed", }; return ((state < (XenbusStateClosed + 1)) ? name[state] : "INVALID"); } -int -xenbus_watch_path(device_t dev, char *path, struct xs_watch *watch, - xs_watch_cb_t *callback, uintptr_t callback_data) -{ - int error; - - watch->node = path; - watch->callback = callback; - watch->callback_data = callback_data; - - error = xs_register_watch(watch); - - if (error) { - watch->node = NULL; - watch->callback = NULL; - xenbus_dev_fatal(dev, error, "adding watch on %s", path); - } - - return (error); -} - -int -xenbus_watch_path2(device_t dev, const char *path, - const char *path2, struct xs_watch *watch, - xs_watch_cb_t *callback, uintptr_t callback_data) -{ - int error; - char *state = malloc(strlen(path) + 1 + strlen(path2) + 1, - M_XENBUS, M_WAITOK); - - strcpy(state, path); - strcat(state, "/"); - strcat(state, path2); - - error = xenbus_watch_path(dev, state, watch, callback, callback_data); - if (error) { - free(state,M_XENBUS); - } - - return (error); -} - void xenbus_dev_verror(device_t dev, int err, const char *fmt, va_list ap) { int ret; unsigned int len; char *printf_buffer = NULL, *path_buffer = NULL; #define PRINTF_BUFFER_SIZE 4096 printf_buffer = malloc(PRINTF_BUFFER_SIZE,M_XENBUS, M_WAITOK); len = sprintf(printf_buffer, "%i ", err); ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap); KASSERT(len + ret <= PRINTF_BUFFER_SIZE-1, ("xenbus error message too big")); device_printf(dev, "Error %s\n", printf_buffer); path_buffer = error_path(dev); if (path_buffer == NULL) { printf("xenbus: failed to write error node for %s (%s)\n", xenbus_get_node(dev), printf_buffer); goto fail; } if (xs_write(XST_NIL, path_buffer, "error", printf_buffer) != 0) { printf("xenbus: failed to write error node for %s (%s)\n", xenbus_get_node(dev), printf_buffer); goto fail; } fail: if (printf_buffer) free(printf_buffer,M_XENBUS); if (path_buffer) free(path_buffer,M_XENBUS); } void xenbus_dev_error(device_t dev, int err, const char *fmt, ...) { va_list ap; va_start(ap, fmt); xenbus_dev_verror(dev, err, fmt, ap); va_end(ap); } void xenbus_dev_vfatal(device_t dev, int err, const char *fmt, va_list ap) { xenbus_dev_verror(dev, err, fmt, ap); device_printf(dev, "Fatal error. Transitioning to Closing State\n"); xenbus_set_state(dev, XenbusStateClosing); } void xenbus_dev_fatal(device_t dev, int err, const char *fmt, ...) { va_list ap; va_start(ap, fmt); xenbus_dev_vfatal(dev, err, fmt, ap); va_end(ap); } int xenbus_grant_ring(device_t dev, unsigned long ring_mfn, grant_ref_t *refp) { int error; error = gnttab_grant_foreign_access( xenbus_get_otherend_id(dev), ring_mfn, 0, refp); if (error) { xenbus_dev_fatal(dev, error, "granting access to ring page"); return (error); } return (0); } XenbusState xenbus_read_driver_state(const char *path) { XenbusState result; int error; error = xs_gather(XST_NIL, path, "state", "%d", &result, NULL); if (error) result = XenbusStateClosed; return (result); } int xenbus_dev_is_online(device_t dev) { const char *path; int error; int value; path = xenbus_get_node(dev); error = xs_gather(XST_NIL, path, "online", "%d", &value, NULL); if (error != 0) { /* Default to not online. */ value = 0; } return (value); } void xenbus_localend_changed(device_t dev, const char *path) { } diff --git a/sys/xen/xenbus/xenbusvar.h b/sys/xen/xenbus/xenbusvar.h index 377d60c01590..bea65fff8e5a 100644 --- a/sys/xen/xenbus/xenbusvar.h +++ b/sys/xen/xenbus/xenbusvar.h @@ -1,281 +1,225 @@ /****************************************************************************** * Copyright (C) 2005 Rusty Russell, IBM Corporation * Copyright (C) 2005 XenSource Ltd. * * This file may be distributed separately from the Linux kernel, or * incorporated into other software packages, subject to the following license: * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this source file (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * $FreeBSD$ */ /** * \file xenbusvar.h * * \brief Datastructures and function declarations for usedby device * drivers operating on the XenBus. */ #ifndef _XEN_XENBUS_XENBUSVAR_H #define _XEN_XENBUS_XENBUSVAR_H #include #include #include #include #include #include #include #include #include #include #include /* XenBus allocations including XenStore data returned to clients. */ MALLOC_DECLARE(M_XENBUS); enum { /** * Path of this device node. */ XENBUS_IVAR_NODE, /** * The device type (e.g. vif, vbd). */ XENBUS_IVAR_TYPE, /** * The state of this device (not the otherend's state). */ XENBUS_IVAR_STATE, /** * Domain ID of the other end device. */ XENBUS_IVAR_OTHEREND_ID, /** * Path of the other end device. */ XENBUS_IVAR_OTHEREND_PATH }; /** * Simplified accessors for xenbus devices: * * xenbus_get_node * xenbus_get_type * xenbus_get_state * xenbus_get_otherend_id * xenbus_get_otherend_path */ #define XENBUS_ACCESSOR(var, ivar, type) \ __BUS_ACCESSOR(xenbus, var, XENBUS, ivar, type) XENBUS_ACCESSOR(node, NODE, const char *) XENBUS_ACCESSOR(type, TYPE, const char *) XENBUS_ACCESSOR(state, STATE, enum xenbus_state) XENBUS_ACCESSOR(otherend_id, OTHEREND_ID, int) XENBUS_ACCESSOR(otherend_path, OTHEREND_PATH, const char *) /** * Return the state of a XenBus device. * * \param path The root XenStore path for the device. * * \return The current state of the device or XenbusStateClosed if no * state can be read. */ XenbusState xenbus_read_driver_state(const char *path); /** * Return the state of the "other end" (peer) of a XenBus device. * * \param dev The XenBus device whose peer to query. * * \return The current state of the peer device or XenbusStateClosed if no * state can be read. */ static inline XenbusState xenbus_get_otherend_state(device_t dev) { return (xenbus_read_driver_state(xenbus_get_otherend_path(dev))); } -/** - * Initialize and register a watch on the given path (client suplied storage). - * - * \param dev The XenBus device requesting the watch service. - * \param path The XenStore path of the object to be watched. The - * storage for this string must be stable for the lifetime - * of the watch. - * \param watch The watch object to use for this request. This object - * must be stable for the lifetime of the watch. - * \param callback The function to call when XenStore objects at or below - * path are modified. - * \param cb_data Client data that can be retrieved from the watch object - * during the callback. - * - * \return On success, 0. Otherwise an errno value indicating the - * type of failure. - * - * \note On error, the device 'dev' will be switched to the XenbusStateClosing - * state and the returned error is saved in the per-device error node - * for dev in the XenStore. - */ -int xenbus_watch_path(device_t dev, char *path, - struct xs_watch *watch, - xs_watch_cb_t *callback, - uintptr_t cb_data); - -/** - * Initialize and register a watch at path/path2 in the XenStore. - * - * \param dev The XenBus device requesting the watch service. - * \param path The base XenStore path of the object to be watched. - * \param path2 The tail XenStore path of the object to be watched. - * \param watch The watch object to use for this request. This object - * must be stable for the lifetime of the watch. - * \param callback The function to call when XenStore objects at or below - * path are modified. - * \param cb_data Client data that can be retrieved from the watch object - * during the callback. - * - * \return On success, 0. Otherwise an errno value indicating the - * type of failure. - * - * \note On error, \a dev will be switched to the XenbusStateClosing - * state and the returned error is saved in the per-device error node - * for \a dev in the XenStore. - * - * Similar to xenbus_watch_path, however the storage for the path to the - * watched object is allocated from the heap and filled with "path '/' path2". - * Should a call to this function succeed, it is the callers responsibility - * to free watch->node using the M_XENBUS malloc type. - */ -int xenbus_watch_path2(device_t dev, const char *path, - const char *path2, struct xs_watch *watch, - xs_watch_cb_t *callback, - uintptr_t cb_data); - /** * Grant access to the given ring_mfn to the peer of the given device. * * \param dev The device granting access to the ring page. * \param ring_mfn The guest machine page number of the page to grant * peer access rights. * \param refp[out] The grant reference for the page. * * \return On success, 0. Otherwise an errno value indicating the * type of failure. * * A successful call to xenbus_grant_ring should be paired with a call * to gnttab_end_foreign_access() when foregn access to this page is no * longer requried. * * \note On error, \a dev will be switched to the XenbusStateClosing * state and the returned error is saved in the per-device error node * for \a dev in the XenStore. */ int xenbus_grant_ring(device_t dev, unsigned long ring_mfn, grant_ref_t *refp); /** * Record the given errno, along with the given, printf-style, formatted * message in dev's device specific error node in the XenStore. * * \param dev The device which encountered the error. * \param err The errno value corresponding to the error. * \param fmt Printf format string followed by a variable number of * printf arguments. */ void xenbus_dev_error(device_t dev, int err, const char *fmt, ...) __attribute__((format(printf, 3, 4))); /** * va_list version of xenbus_dev_error(). * * \param dev The device which encountered the error. * \param err The errno value corresponding to the error. * \param fmt Printf format string. * \param ap Va_list of printf arguments. */ void xenbus_dev_verror(device_t dev, int err, const char *fmt, va_list ap) __attribute__((format(printf, 3, 0))); /** * Equivalent to xenbus_dev_error(), followed by * xenbus_set_state(dev, XenbusStateClosing). * * \param dev The device which encountered the error. * \param err The errno value corresponding to the error. * \param fmt Printf format string followed by a variable number of * printf arguments. */ void xenbus_dev_fatal(device_t dev, int err, const char *fmt, ...) __attribute__((format(printf, 3, 4))); /** * va_list version of xenbus_dev_fatal(). * * \param dev The device which encountered the error. * \param err The errno value corresponding to the error. * \param fmt Printf format string. * \param ap Va_list of printf arguments. */ void xenbus_dev_vfatal(device_t dev, int err, const char *fmt, va_list) __attribute__((format(printf, 3, 0))); /** * Convert a member of the xenbus_state enum into an ASCII string. * * /param state The XenBus state to lookup. * * /return A string representing state or, for unrecognized states, * the string "Unknown". */ const char *xenbus_strstate(enum xenbus_state state); /** * Return the value of a XenBus device's "online" node within the XenStore. * * \param dev The XenBus device to query. * * \return The value of the "online" node for the device. If the node * does not exist, 0 (offline) is returned. */ int xenbus_dev_is_online(device_t dev); /** * Default callback invoked when a change to the local XenStore sub-tree * for a device is modified. * * \param dev The XenBus device whose tree was modified. * \param path The tree relative sub-path to the modified node. The empty * string indicates the root of the tree was destroyed. */ void xenbus_localend_changed(device_t dev, const char *path); #include "xenbus_if.h" #endif /* _XEN_XENBUS_XENBUSVAR_H */