/* 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);
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()) /* *Ifweareintheprocessofbeingshut-downthereis *nopointoftryingtocontactXenBus-itiseither *killed(xenstoredapplication)ortheotherdomain *hasbeenkilledorisunreachable.
*/ 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); return0;
}
/* 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)) return0;
kfree(d); return1;
}
EXPORT_SYMBOL_GPL(xenbus_exists);
/* Get the value of a single file. *Returnsakmallocedvalue:callfree()onitafteruse. *lenindicateslengthinbytes.
*/ 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-erronfailure.
*/ 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,andchangeswillnotbevisibletoothersuntilend.
*/ 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. *Ifabandonistrue,transactionisdiscardedinsteadofcommitted.
*/ 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);
}
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.