linux/drivers/xen/xenbus/xenbus_xs.c

/******************************************************************************
 * xenbus_xs.c
 *
 * This is the kernel equivalent of the "xs" library.  We don't need everything
 * and we use xenbus_comms for communication.
 *
 * Copyright (C) 2005 Rusty Russell, IBM Corporation
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License version 2
 * as published by the Free Software Foundation; or, when 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.
 */

#define pr_fmt(fmt)

#include <linux/unistd.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/uio.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/kthread.h>
#include <linux/reboot.h>
#include <linux/rwsem.h>
#include <linux/mutex.h>
#include <asm/xen/hypervisor.h>
#include <xen/xenbus.h>
#include <xen/xen.h>
#include "xenbus.h"

/*
 * Framework to protect suspend/resume handling against normal Xenstore
 * message handling:
 * During suspend/resume there must be no open transaction and no pending
 * Xenstore request.
 * New watch events happening in this time can be ignored by firing all watches
 * after resume.
 */

/* Lock protecting enter/exit critical region. */
static DEFINE_SPINLOCK(xs_state_lock);
/* Number of users in critical region (protected by xs_state_lock). */
static unsigned int xs_state_users;
/* Suspend handler waiting or already active (protected by xs_state_lock)? */
static int xs_suspend_active;
/* Unique Xenstore request id (protected by xs_state_lock). */
static uint32_t xs_request_id;

/* Wait queue for all callers waiting for critical region to become usable. */
static DECLARE_WAIT_QUEUE_HEAD(xs_state_enter_wq);
/* Wait queue for suspend handling waiting for critical region being empty. */
static DECLARE_WAIT_QUEUE_HEAD(xs_state_exit_wq);

/* List of registered watches, and a lock to protect it. */
static LIST_HEAD(watches);
static DEFINE_SPINLOCK(watches_lock);

/* List of pending watch callback events, and a lock to protect it. */
static LIST_HEAD(watch_events);
static DEFINE_SPINLOCK(watch_events_lock);

/* Protect watch (de)register against save/restore. */
static DECLARE_RWSEM(xs_watch_rwsem);

/*
 * Details of the xenwatch callback kernel thread. The thread waits on the
 * watch_events_waitq for work to do (queued on watch_events list). When it
 * wakes up it acquires the xenwatch_mutex before reading the list and
 * carrying out work.
 */
static pid_t xenwatch_pid;
static DEFINE_MUTEX(xenwatch_mutex);
static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq);

static void xs_suspend_enter(void)
{}

static void xs_suspend_exit(void)
{}

static uint32_t xs_request_enter(struct xb_req_data *req)
{}

void xs_request_exit(struct xb_req_data *req)
{}

static int get_error(const char *errorstring)
{}

static bool xenbus_ok(void)
{}

static bool test_reply(struct xb_req_data *req)
{}

static void *read_reply(struct xb_req_data *req)
{}

static void xs_send(struct xb_req_data *req, struct xsd_sockmsg *msg)
{}

static void *xs_wait_for_reply(struct xb_req_data *req, struct xsd_sockmsg *msg)
{}

static void xs_wake_up(struct xb_req_data *req)
{}

int xenbus_dev_request_and_reply(struct xsd_sockmsg *msg, void *par)
{}
EXPORT_SYMBOL();

/* Send message to xs, get kmalloc'ed reply.  ERR_PTR() on error. */
static void *xs_talkv(struct xenbus_transaction t,
		      enum xsd_sockmsg_type type,
		      const struct kvec *iovec,
		      unsigned int num_vecs,
		      unsigned int *len)
{}

/* Simplified version of xs_talkv: single message. */
static void *xs_single(struct xenbus_transaction t,
		       enum xsd_sockmsg_type type,
		       const char *string,
		       unsigned int *len)
{}

/* Many commands only need an ack, don't care what it says. */
static int xs_error(char *reply)
{}

static unsigned int count_strings(const char *strings, unsigned int len)
{}

/* Return the path to dir with /name appended. Buffer must be kfree()'ed. */
static char *join(const char *dir, const char *name)
{}

static char **split(char *strings, unsigned int len, unsigned int *num)
{}

char **xenbus_directory(struct xenbus_transaction t,
			const char *dir, const char *node, unsigned int *num)
{}
EXPORT_SYMBOL_GPL();

/* Check if a path exists. Return 1 if it does. */
int xenbus_exists(struct xenbus_transaction t,
		  const char *dir, const char *node)
{}
EXPORT_SYMBOL_GPL();

/* Get the value of a single file.
 * Returns a kmalloced value: call free() on it after use.
 * len indicates length in bytes.
 */
void *xenbus_read(struct xenbus_transaction t,
		  const char *dir, const char *node, unsigned int *len)
{}
EXPORT_SYMBOL_GPL();

/* Write the value of a single file.
 * Returns -err on failure.
 */
int xenbus_write(struct xenbus_transaction t,
		 const char *dir, const char *node, const char *string)
{}
EXPORT_SYMBOL_GPL();

/* Create a new directory. */
int xenbus_mkdir(struct xenbus_transaction t,
		 const char *dir, const char *node)
{}
EXPORT_SYMBOL_GPL();

/* Destroy a file or directory (directories must be empty). */
int xenbus_rm(struct xenbus_transaction t, const char *dir, const char *node)
{}
EXPORT_SYMBOL_GPL();

/* Start a transaction: changes by others will not be seen during this
 * transaction, and changes will not be visible to others until end.
 */
int xenbus_transaction_start(struct xenbus_transaction *t)
{}
EXPORT_SYMBOL_GPL();

/* End a transaction.
 * If abandon is true, transaction is discarded instead of committed.
 */
int xenbus_transaction_end(struct xenbus_transaction t, int abort)
{}
EXPORT_SYMBOL_GPL();

/* Single read and scanf: returns -errno or num scanned. */
int xenbus_scanf(struct xenbus_transaction t,
		 const char *dir, const char *node, const char *fmt, ...)
{}
EXPORT_SYMBOL_GPL();

/* Read an (optional) unsigned value. */
unsigned int xenbus_read_unsigned(const char *dir, const char *node,
				  unsigned int default_val)
{}
EXPORT_SYMBOL_GPL();

/* Single printf and write: returns -errno or 0. */
int xenbus_printf(struct xenbus_transaction t,
		  const char *dir, const char *node, const char *fmt, ...)
{}
EXPORT_SYMBOL_GPL();

/* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
int xenbus_gather(struct xenbus_transaction t, const char *dir, ...)
{}
EXPORT_SYMBOL_GPL();

static int xs_watch(const char *path, const char *token)
{}

static int xs_unwatch(const char *path, const char *token)
{}

static struct xenbus_watch *find_watch(const char *token)
{}

int xs_watch_msg(struct xs_watch_event *event)
{}

/*
 * Certain older XenBus toolstack cannot handle reading values that are
 * not populated. Some Xen 3.4 installation are incapable of doing this
 * so if we are running on anything older than 4 do not attempt to read
 * control/platform-feature-xs_reset_watches.
 */
static bool xen_strict_xenbus_quirk(void)
{}
static void xs_reset_watches(void)
{}

/* Register callback to watch this node. */
int register_xenbus_watch(struct xenbus_watch *watch)
{}
EXPORT_SYMBOL_GPL();

void unregister_xenbus_watch(struct xenbus_watch *watch)
{}
EXPORT_SYMBOL_GPL();

void xs_suspend(void)
{}

void xs_resume(void)
{}

void xs_suspend_cancel(void)
{}

static int xenwatch_thread(void *unused)
{}

/*
 * Wake up all threads waiting for a xenstore reply. In case of shutdown all
 * pending replies will be marked as "aborted" in order to let the waiters
 * return in spite of xenstore possibly no longer being able to reply. This
 * will avoid blocking shutdown by a thread waiting for xenstore but being
 * necessary for shutdown processing to proceed.
 */
static int xs_reboot_notify(struct notifier_block *nb,
			    unsigned long code, void *unused)
{}

static struct notifier_block xs_reboot_nb =;

int xs_init(void)
{}