/****************************************************************************** * 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.
*/
/* * 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). */ staticunsignedint xs_state_users; /* Suspend handler waiting or already active (protected by xs_state_lock)? */ staticint 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);
for (i = 0; strcmp(errorstring, xsd_errors[i].errstring) != 0; i++) { if (i == ARRAY_SIZE(xsd_errors) - 1) {
pr_warn("xen store gave: unknown error %s\n",
errorstring); return EINVAL;
}
} return xsd_errors[i].errnum;
}
staticbool xenbus_ok(void)
{ switch (xen_store_domain_type) { case XS_LOCAL: switch (system_state) { case SYSTEM_POWER_OFF: case SYSTEM_RESTART: case SYSTEM_HALT: returnfalse; default: break;
} returntrue; case XS_PV: case XS_HVM: /* FIXME: Could check that the remote domain is alive,
* but it is normally initial domain. */ returntrue; default: break;
} returnfalse;
}
staticbool test_reply(struct xb_req_data *req)
{ if (req->state == xb_req_state_got_reply || !xenbus_ok()) { /* read req->state before all other fields */
virt_rmb(); returntrue;
}
/* Make sure to reread req->state each time. */
barrier();
returnfalse;
}
staticvoid *read_reply(struct xb_req_data *req)
{ do {
wait_event(req->wq, test_reply(req));
if (!xenbus_ok()) /* * If we are in the process of being shut-down there is * no point of trying to contact XenBus - it is either * killed (xenstored application) or the other domain * has been killed or is unreachable.
*/ return ERR_PTR(-EIO); if (req->err) return ERR_PTR(req->err);
/* Many commands only need an ack, don't care what it says. */ staticint xs_error(char *reply)
{ if (IS_ERR(reply)) return PTR_ERR(reply);
kfree(reply); return 0;
}
/* Count the strings. */
*num = count_strings(strings, len);
/* Transfer to one big alloc for easy freeing. */
ret = kmalloc(*num * sizeof(char *) + len, GFP_NOIO | __GFP_HIGH); if (!ret) {
kfree(strings); return ERR_PTR(-ENOMEM);
}
memcpy(&ret[*num], strings, len);
kfree(strings);
strings = (char *)&ret[*num]; for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
ret[(*num)++] = p;
/* Check if a path exists. Return 1 if it does. */ int xenbus_exists(struct xenbus_transaction t, constchar *dir, constchar *node)
{ char **d; int dir_n;
d = xenbus_directory(t, dir, node, &dir_n); if (IS_ERR(d)) return 0;
kfree(d); return 1;
}
EXPORT_SYMBOL_GPL(xenbus_exists);
/* 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, constchar *dir, constchar *node, unsignedint *len)
{ char *path; void *ret;
path = join(dir, node); if (IS_ERR(path)) return ERR_CAST(path);
/* Write the value of a single file. * Returns -err on failure.
*/ int xenbus_write(struct xenbus_transaction t, constchar *dir, constchar *node, constchar *string)
{ constchar *path; struct kvec iovec[2]; int ret;
path = join(dir, node); if (IS_ERR(path)) return PTR_ERR(path);
/* Destroy a file or directory (directories must be empty). */ int xenbus_rm(struct xenbus_transaction t, constchar *dir, constchar *node)
{ char *path; int ret;
path = join(dir, node); if (IS_ERR(path)) return PTR_ERR(path);
/* 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)
{ char *id_str;
id_str = xs_single(XBT_NIL, XS_TRANSACTION_START, "", NULL); if (IS_ERR(id_str)) return PTR_ERR(id_str);
/* End a transaction. * If abandon is true, transaction is discarded instead of committed.
*/ int xenbus_transaction_end(struct xenbus_transaction t, int abort)
{ char abortstr[2];
if (abort)
strcpy(abortstr, "F"); else
strcpy(abortstr, "T");
/* Single read and scanf: returns -errno or num scanned. */ int xenbus_scanf(struct xenbus_transaction t, constchar *dir, constchar *node, constchar *fmt, ...)
{
va_list ap; int ret; char *val;
val = xenbus_read(t, dir, node, NULL); if (IS_ERR(val)) return PTR_ERR(val);
/* Register callback to watch this node. */ int register_xenbus_watch(struct xenbus_watch *watch)
{ /* Pointer in ascii is the token. */ char token[sizeof(watch) * 2 + 1]; int err;
/* No need for watches_lock: the xs_watch_rwsem is sufficient. */
list_for_each_entry(watch, &watches, list) {
sprintf(token, "%lX", (long)watch);
xs_watch(watch->node, token);
}
if (event) {
event->handle->callback(event->handle, event->path,
event->token);
kfree(event);
}
mutex_unlock(&xenwatch_mutex);
}
return 0;
}
/* * 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.
*/ staticint xs_reboot_notify(struct notifier_block *nb, unsignedlong code, void *unused)
{ struct xb_req_data *req;
int xs_init(void)
{ int err; struct task_struct *task;
register_reboot_notifier(&xs_reboot_nb);
/* Initialize the shared memory rings to talk to xenstored */
err = xb_init_comms(); if (err) return err;
task = kthread_run(xenwatch_thread, NULL, "xenwatch"); if (IS_ERR(task)) return PTR_ERR(task);
/* shutdown watches for kexec boot */
xs_reset_watches();
return 0;
}
Messung V0.5
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.10Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.