xen-vtx-unstable

annotate linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @ 6751:1cb7adaa3355

Put xenstored.h in linux-public include dir.
Signed-off-by: Chris Wright <chrisw@osdl.org>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Sep 13 08:35:41 2005 +0000 (2005-09-13)
parents 80afc502461b
children 4d899a738d59 8ca0f98ba8e2
rev   line source
cl349@5598 1 /******************************************************************************
cl349@5598 2 * xenbus_xs.c
cl349@5598 3 *
cl349@5598 4 * This is the kernel equivalent of the "xs" library. We don't need everything
cl349@5863 5 * and we use xenbus_comms for communication.
cl349@5598 6 *
cl349@5598 7 * Copyright (C) 2005 Rusty Russell, IBM Corporation
cl349@5598 8 *
cl349@5598 9 * This file may be distributed separately from the Linux kernel, or
cl349@5598 10 * incorporated into other software packages, subject to the following license:
cl349@5598 11 *
cl349@5598 12 * Permission is hereby granted, free of charge, to any person obtaining a copy
cl349@5598 13 * of this source file (the "Software"), to deal in the Software without
cl349@5598 14 * restriction, including without limitation the rights to use, copy, modify,
cl349@5598 15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
cl349@5598 16 * and to permit persons to whom the Software is furnished to do so, subject to
cl349@5598 17 * the following conditions:
cl349@5598 18 *
cl349@5598 19 * The above copyright notice and this permission notice shall be included in
cl349@5598 20 * all copies or substantial portions of the Software.
cl349@5598 21 *
cl349@5598 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
cl349@5598 23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
cl349@5598 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
cl349@5598 25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
cl349@5598 26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
cl349@5598 27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
cl349@5598 28 * IN THE SOFTWARE.
cl349@5598 29 */
cl349@5598 30
cl349@5598 31 #include <linux/errno.h>
cl349@5598 32 #include <linux/types.h>
cl349@5598 33 #include <linux/uio.h>
cl349@5598 34 #include <linux/kernel.h>
cl349@5598 35 #include <linux/string.h>
cl349@5598 36 #include <linux/err.h>
cl349@5598 37 #include <linux/slab.h>
cl349@5598 38 #include <linux/fcntl.h>
cl349@5598 39 #include <linux/kthread.h>
cl349@5598 40 #include <asm-xen/xenbus.h>
cl349@6751 41 #include <asm-xen/linux-public/xenstored.h>
cl349@5598 42 #include "xenbus_comms.h"
cl349@5598 43
cl349@5598 44 #define streq(a, b) (strcmp((a), (b)) == 0)
cl349@5598 45
cl349@5874 46 static char printf_buffer[4096];
cl349@5598 47 static LIST_HEAD(watches);
kaf24@6480 48
cl349@5863 49 DECLARE_MUTEX(xenbus_lock);
kaf24@6480 50 EXPORT_SYMBOL(xenbus_lock);
cl349@5598 51
cl349@5598 52 static int get_error(const char *errorstring)
cl349@5598 53 {
cl349@5598 54 unsigned int i;
cl349@5598 55
cl349@5598 56 for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
cl349@5598 57 if (i == ARRAY_SIZE(xsd_errors) - 1) {
cl349@5670 58 printk(KERN_WARNING
cl349@5670 59 "XENBUS xen store gave: unknown error %s",
cl349@5598 60 errorstring);
cl349@5598 61 return EINVAL;
cl349@5598 62 }
cl349@5598 63 }
cl349@5598 64 return xsd_errors[i].errnum;
cl349@5598 65 }
cl349@5598 66
cl349@5598 67 static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
cl349@5598 68 {
cl349@5598 69 struct xsd_sockmsg msg;
cl349@5598 70 void *ret;
cl349@5598 71 int err;
cl349@5598 72
cl349@5902 73 err = xb_read(&msg, sizeof(msg));
cl349@5598 74 if (err)
cl349@5598 75 return ERR_PTR(err);
cl349@5598 76
cl349@5598 77 ret = kmalloc(msg.len + 1, GFP_KERNEL);
cl349@5598 78 if (!ret)
cl349@5598 79 return ERR_PTR(-ENOMEM);
cl349@5598 80
cl349@5902 81 err = xb_read(ret, msg.len);
cl349@5598 82 if (err) {
cl349@5598 83 kfree(ret);
cl349@5598 84 return ERR_PTR(err);
cl349@5598 85 }
cl349@5598 86 ((char*)ret)[msg.len] = '\0';
cl349@5598 87
cl349@5598 88 *type = msg.type;
cl349@5598 89 if (len)
cl349@5598 90 *len = msg.len;
cl349@5598 91 return ret;
cl349@5598 92 }
cl349@5598 93
cl349@5747 94 /* Emergency write. */
cl349@5863 95 void xenbus_debug_write(const char *str, unsigned int count)
cl349@5747 96 {
cl349@5747 97 struct xsd_sockmsg msg;
cl349@5747 98
cl349@5747 99 msg.type = XS_DEBUG;
cl349@5747 100 msg.len = sizeof("print") + count + 1;
cl349@5747 101
cl349@5902 102 xb_write(&msg, sizeof(msg));
cl349@5902 103 xb_write("print", sizeof("print"));
cl349@5902 104 xb_write(str, count);
cl349@5902 105 xb_write("", 1);
cl349@5747 106 }
cl349@5747 107
cl349@5598 108 /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
cl349@6749 109 static void *xs_talkv(enum xsd_sockmsg_type type,
cl349@6749 110 const struct kvec *iovec,
cl349@6749 111 unsigned int num_vecs,
cl349@6749 112 unsigned int *len)
cl349@5598 113 {
cl349@5598 114 struct xsd_sockmsg msg;
cl349@5598 115 void *ret = NULL;
cl349@5598 116 unsigned int i;
cl349@5598 117 int err;
cl349@5598 118
cl349@5863 119 WARN_ON(down_trylock(&xenbus_lock) == 0);
cl349@5598 120
cl349@5598 121 msg.type = type;
cl349@5598 122 msg.len = 0;
cl349@5598 123 for (i = 0; i < num_vecs; i++)
cl349@5598 124 msg.len += iovec[i].iov_len;
cl349@5598 125
cl349@5902 126 err = xb_write(&msg, sizeof(msg));
cl349@5598 127 if (err)
cl349@5598 128 return ERR_PTR(err);
cl349@5598 129
cl349@5598 130 for (i = 0; i < num_vecs; i++) {
cl349@5902 131 err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
cl349@5598 132 if (err)
cl349@5598 133 return ERR_PTR(err);
cl349@5598 134 }
cl349@5598 135
cl349@5598 136 /* Watches can have fired before reply comes: daemon detects
cl349@5598 137 * and re-transmits, so we can ignore this. */
cl349@5598 138 do {
cl349@5598 139 kfree(ret);
cl349@5598 140 ret = read_reply(&msg.type, len);
cl349@5598 141 if (IS_ERR(ret))
cl349@5598 142 return ret;
cl349@5598 143 } while (msg.type == XS_WATCH_EVENT);
cl349@5598 144
cl349@5598 145 if (msg.type == XS_ERROR) {
cl349@5598 146 err = get_error(ret);
cl349@5598 147 kfree(ret);
cl349@5598 148 return ERR_PTR(-err);
cl349@5598 149 }
cl349@5598 150
cl349@5598 151 BUG_ON(msg.type != type);
cl349@5598 152 return ret;
cl349@5598 153 }
cl349@5598 154
cl349@5598 155 /* Simplified version of xs_talkv: single message. */
cl349@5598 156 static void *xs_single(enum xsd_sockmsg_type type,
cl349@5598 157 const char *string, unsigned int *len)
cl349@5598 158 {
cl349@5598 159 struct kvec iovec;
cl349@5598 160
cl349@5598 161 iovec.iov_base = (void *)string;
cl349@5598 162 iovec.iov_len = strlen(string) + 1;
cl349@5598 163 return xs_talkv(type, &iovec, 1, len);
cl349@5598 164 }
cl349@5598 165
cl349@5598 166 /* Many commands only need an ack, don't care what it says. */
cl349@5598 167 static int xs_error(char *reply)
cl349@5598 168 {
cl349@5598 169 if (IS_ERR(reply))
cl349@5598 170 return PTR_ERR(reply);
cl349@5598 171 kfree(reply);
cl349@5598 172 return 0;
cl349@5598 173 }
cl349@5598 174
cl349@5598 175 static unsigned int count_strings(const char *strings, unsigned int len)
cl349@5598 176 {
cl349@5598 177 unsigned int num;
cl349@5598 178 const char *p;
cl349@5598 179
cl349@5598 180 for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
cl349@5598 181 num++;
cl349@5598 182
cl349@5598 183 return num;
cl349@5598 184 }
cl349@5598 185
cl349@5863 186 /* Return the path to dir with /name appended. */
cl349@5863 187 static char *join(const char *dir, const char *name)
cl349@5863 188 {
cl349@5863 189 static char buffer[4096];
cl349@5863 190
cl349@5863 191 BUG_ON(down_trylock(&xenbus_lock) == 0);
cl349@6250 192 /* XXX FIXME: might not be correct if name == "" */
cl349@5863 193 BUG_ON(strlen(dir) + strlen("/") + strlen(name) + 1 > sizeof(buffer));
cl349@5863 194
cl349@5863 195 strcpy(buffer, dir);
cl349@5863 196 if (!streq(name, "")) {
cl349@5863 197 strcat(buffer, "/");
cl349@5863 198 strcat(buffer, name);
cl349@5863 199 }
cl349@5863 200 return buffer;
cl349@5863 201 }
cl349@5863 202
cl349@5863 203 char **xenbus_directory(const char *dir, const char *node, unsigned int *num)
cl349@5598 204 {
cl349@5598 205 char *strings, *p, **ret;
cl349@5598 206 unsigned int len;
cl349@5598 207
cl349@5863 208 strings = xs_single(XS_DIRECTORY, join(dir, node), &len);
cl349@5598 209 if (IS_ERR(strings))
cl349@5598 210 return (char **)strings;
cl349@5598 211
cl349@5598 212 /* Count the strings. */
cl349@5598 213 *num = count_strings(strings, len);
cl349@5598 214
cl349@5598 215 /* Transfer to one big alloc for easy freeing. */
cl349@5598 216 ret = kmalloc(*num * sizeof(char *) + len, GFP_ATOMIC);
cl349@5598 217 if (!ret) {
cl349@5598 218 kfree(strings);
cl349@5598 219 return ERR_PTR(-ENOMEM);
cl349@5598 220 }
cl349@5598 221 memcpy(&ret[*num], strings, len);
cl349@5598 222 kfree(strings);
cl349@5598 223
cl349@5598 224 strings = (char *)&ret[*num];
cl349@5598 225 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
cl349@5598 226 ret[(*num)++] = p;
cl349@5598 227 return ret;
cl349@5598 228 }
kaf24@6480 229 EXPORT_SYMBOL(xenbus_directory);
cl349@5598 230
cl349@5598 231 /* Check if a path exists. Return 1 if it does. */
cl349@5863 232 int xenbus_exists(const char *dir, const char *node)
cl349@5598 233 {
cl349@5863 234 char **d;
cl349@5670 235 int dir_n;
cl349@5598 236
cl349@5867 237 d = xenbus_directory(dir, node, &dir_n);
cl349@5863 238 if (IS_ERR(d))
cl349@5670 239 return 0;
cl349@5863 240 kfree(d);
cl349@5670 241 return 1;
cl349@5598 242 }
kaf24@6480 243 EXPORT_SYMBOL(xenbus_exists);
cl349@5598 244
cl349@5598 245 /* Get the value of a single file.
cl349@5598 246 * Returns a kmalloced value: call free() on it after use.
cl349@5598 247 * len indicates length in bytes.
cl349@5598 248 */
cl349@5863 249 void *xenbus_read(const char *dir, const char *node, unsigned int *len)
cl349@5598 250 {
cl349@5863 251 return xs_single(XS_READ, join(dir, node), len);
cl349@5598 252 }
kaf24@6467 253 EXPORT_SYMBOL(xenbus_read);
cl349@5598 254
cl349@5598 255 /* Write the value of a single file.
cl349@5598 256 * Returns -err on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
cl349@5598 257 */
cl349@5863 258 int xenbus_write(const char *dir, const char *node,
cl349@5863 259 const char *string, int createflags)
cl349@5598 260 {
cl349@5863 261 const char *flags, *path;
cl349@5598 262 struct kvec iovec[3];
cl349@5598 263
cl349@5863 264 path = join(dir, node);
cl349@5598 265 /* Format: Flags (as string), path, data. */
cl349@5598 266 if (createflags == 0)
cl349@5598 267 flags = XS_WRITE_NONE;
cl349@5598 268 else if (createflags == O_CREAT)
cl349@5598 269 flags = XS_WRITE_CREATE;
cl349@5598 270 else if (createflags == (O_CREAT|O_EXCL))
cl349@5598 271 flags = XS_WRITE_CREATE_EXCL;
cl349@5598 272 else
cl349@5598 273 return -EINVAL;
cl349@5598 274
cl349@5598 275 iovec[0].iov_base = (void *)path;
cl349@5598 276 iovec[0].iov_len = strlen(path) + 1;
cl349@5598 277 iovec[1].iov_base = (void *)flags;
cl349@5598 278 iovec[1].iov_len = strlen(flags) + 1;
cl349@5863 279 iovec[2].iov_base = (void *)string;
cl349@5863 280 iovec[2].iov_len = strlen(string);
cl349@5598 281
cl349@5598 282 return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
cl349@5598 283 }
kaf24@6480 284 EXPORT_SYMBOL(xenbus_write);
cl349@5598 285
cl349@5598 286 /* Create a new directory. */
cl349@5863 287 int xenbus_mkdir(const char *dir, const char *node)
cl349@5598 288 {
cl349@5863 289 return xs_error(xs_single(XS_MKDIR, join(dir, node), NULL));
cl349@5598 290 }
kaf24@6480 291 EXPORT_SYMBOL(xenbus_mkdir);
cl349@5598 292
cl349@5598 293 /* Destroy a file or directory (directories must be empty). */
cl349@5863 294 int xenbus_rm(const char *dir, const char *node)
cl349@5598 295 {
cl349@5863 296 return xs_error(xs_single(XS_RM, join(dir, node), NULL));
cl349@5598 297 }
kaf24@6480 298 EXPORT_SYMBOL(xenbus_rm);
cl349@5598 299
cl349@5598 300 /* Start a transaction: changes by others will not be seen during this
cl349@5598 301 * transaction, and changes will not be visible to others until end.
cl349@5598 302 * Transaction only applies to the given subtree.
cl349@5598 303 * You can only have one transaction at any time.
cl349@5598 304 */
cl349@5863 305 int xenbus_transaction_start(const char *subtree)
cl349@5598 306 {
cl349@5598 307 return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
cl349@5598 308 }
kaf24@6467 309 EXPORT_SYMBOL(xenbus_transaction_start);
cl349@5598 310
cl349@5598 311 /* End a transaction.
cl349@5598 312 * If abandon is true, transaction is discarded instead of committed.
cl349@5598 313 */
cl349@5863 314 int xenbus_transaction_end(int abort)
cl349@5598 315 {
cl349@5598 316 char abortstr[2];
cl349@5598 317
cl349@5598 318 if (abort)
cl349@5598 319 strcpy(abortstr, "F");
cl349@5598 320 else
cl349@5598 321 strcpy(abortstr, "T");
cl349@5598 322 return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
cl349@5598 323 }
kaf24@6467 324 EXPORT_SYMBOL(xenbus_transaction_end);
cl349@5598 325
cl349@5863 326 /* Single read and scanf: returns -errno or num scanned. */
cl349@5863 327 int xenbus_scanf(const char *dir, const char *node, const char *fmt, ...)
cl349@5598 328 {
cl349@5863 329 va_list ap;
cl349@5863 330 int ret;
cl349@5863 331 char *val;
cl349@5863 332
cl349@5863 333 val = xenbus_read(dir, node, NULL);
cl349@5863 334 if (IS_ERR(val))
cl349@5863 335 return PTR_ERR(val);
cl349@5598 336
cl349@5863 337 va_start(ap, fmt);
cl349@5863 338 ret = vsscanf(val, fmt, ap);
cl349@5863 339 va_end(ap);
cl349@5863 340 kfree(val);
cl349@5863 341 /* Distinctive errno. */
cl349@5863 342 if (ret == 0)
cl349@5863 343 return -ERANGE;
cl349@5863 344 return ret;
cl349@5863 345 }
kaf24@6467 346 EXPORT_SYMBOL(xenbus_scanf);
cl349@5863 347
cl349@5863 348 /* Single printf and write: returns -errno or 0. */
cl349@5863 349 int xenbus_printf(const char *dir, const char *node, const char *fmt, ...)
cl349@5598 350 {
cl349@5863 351 va_list ap;
cl349@5863 352 int ret;
cl349@5863 353
cl349@5863 354 BUG_ON(down_trylock(&xenbus_lock) == 0);
cl349@5863 355 va_start(ap, fmt);
cl349@5874 356 ret = vsnprintf(printf_buffer, sizeof(printf_buffer), fmt, ap);
cl349@5863 357 va_end(ap);
cl349@5863 358
cl349@5874 359 BUG_ON(ret > sizeof(printf_buffer)-1);
cl349@5874 360 return xenbus_write(dir, node, printf_buffer, O_CREAT);
cl349@5598 361 }
kaf24@6467 362 EXPORT_SYMBOL(xenbus_printf);
cl349@5598 363
cl349@5874 364 /* Report a (negative) errno into the store, with explanation. */
cl349@5874 365 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
cl349@5874 366 {
cl349@5874 367 va_list ap;
cl349@5874 368 int ret;
cl349@5874 369 unsigned int len;
cl349@5874 370
cl349@5874 371 BUG_ON(down_trylock(&xenbus_lock) == 0);
cl349@5874 372
cl349@5874 373 len = sprintf(printf_buffer, "%i ", -err);
cl349@5874 374 va_start(ap, fmt);
cl349@5874 375 ret = vsnprintf(printf_buffer+len, sizeof(printf_buffer)-len, fmt, ap);
cl349@5874 376 va_end(ap);
cl349@5874 377
cl349@5874 378 BUG_ON(len + ret > sizeof(printf_buffer)-1);
cl349@5874 379 dev->has_error = 1;
cl349@5874 380 if (xenbus_write(dev->nodename, "error", printf_buffer, O_CREAT) != 0)
cl349@5874 381 printk("xenbus: failed to write error node for %s (%s)\n",
cl349@5874 382 dev->nodename, printf_buffer);
cl349@5874 383 }
kaf24@6467 384 EXPORT_SYMBOL(xenbus_dev_error);
cl349@5874 385
cl349@5874 386 /* Clear any error. */
cl349@5874 387 void xenbus_dev_ok(struct xenbus_device *dev)
cl349@5598 388 {
cl349@5874 389 if (dev->has_error) {
cl349@5874 390 if (xenbus_rm(dev->nodename, "error") != 0)
cl349@5874 391 printk("xenbus: failed to clear error node for %s\n",
cl349@5874 392 dev->nodename);
cl349@5874 393 else
cl349@5874 394 dev->has_error = 0;
cl349@5874 395 }
cl349@5874 396 }
kaf24@6467 397 EXPORT_SYMBOL(xenbus_dev_ok);
cl349@5874 398
cl349@5863 399 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
cl349@5863 400 int xenbus_gather(const char *dir, ...)
cl349@5863 401 {
cl349@5863 402 va_list ap;
cl349@5863 403 const char *name;
cl349@5863 404 int ret = 0;
cl349@5598 405
cl349@5863 406 va_start(ap, dir);
cl349@5863 407 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
cl349@5863 408 const char *fmt = va_arg(ap, char *);
cl349@5863 409 void *result = va_arg(ap, void *);
cl349@5863 410 char *p;
cl349@5863 411
cl349@5863 412 p = xenbus_read(dir, name, NULL);
cl349@5863 413 if (IS_ERR(p)) {
cl349@5863 414 ret = PTR_ERR(p);
cl349@5863 415 break;
cl349@5863 416 }
cl349@6250 417 if (fmt) {
cl349@6250 418 if (sscanf(p, fmt, result) == 0)
cl349@6250 419 ret = -EINVAL;
cl349@6250 420 kfree(p);
cl349@6250 421 } else
cl349@6250 422 *(char **)result = p;
cl349@5863 423 }
cl349@5863 424 va_end(ap);
cl349@5863 425 return ret;
cl349@5598 426 }
kaf24@6467 427 EXPORT_SYMBOL(xenbus_gather);
cl349@5598 428
cl349@5876 429 static int xs_watch(const char *path, const char *token)
cl349@5598 430 {
cl349@5876 431 struct kvec iov[2];
cl349@5598 432
cl349@5598 433 iov[0].iov_base = (void *)path;
cl349@5598 434 iov[0].iov_len = strlen(path) + 1;
cl349@5598 435 iov[1].iov_base = (void *)token;
cl349@5598 436 iov[1].iov_len = strlen(token) + 1;
cl349@5598 437
cl349@5598 438 return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
cl349@5598 439 }
cl349@5598 440
cl349@5598 441 static char *xs_read_watch(char **token)
cl349@5598 442 {
cl349@5598 443 enum xsd_sockmsg_type type;
cl349@5598 444 char *ret;
cl349@5598 445
cl349@5598 446 ret = read_reply(&type, NULL);
cl349@5598 447 if (IS_ERR(ret))
cl349@5598 448 return ret;
cl349@5598 449
cl349@5598 450 BUG_ON(type != XS_WATCH_EVENT);
cl349@5598 451 *token = ret + strlen(ret) + 1;
cl349@5598 452 return ret;
cl349@5598 453 }
cl349@5598 454
cl349@5598 455 static int xs_acknowledge_watch(const char *token)
cl349@5598 456 {
cl349@5598 457 return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
cl349@5598 458 }
cl349@5598 459
cl349@5598 460 static int xs_unwatch(const char *path, const char *token)
cl349@5598 461 {
cl349@5598 462 struct kvec iov[2];
cl349@5598 463
cl349@5598 464 iov[0].iov_base = (char *)path;
cl349@5598 465 iov[0].iov_len = strlen(path) + 1;
cl349@5598 466 iov[1].iov_base = (char *)token;
cl349@5598 467 iov[1].iov_len = strlen(token) + 1;
cl349@5598 468
cl349@5598 469 return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
cl349@5598 470 }
cl349@5598 471
cl349@5598 472 /* A little paranoia: we don't just trust token. */
cl349@5598 473 static struct xenbus_watch *find_watch(const char *token)
cl349@5598 474 {
cl349@5598 475 struct xenbus_watch *i, *cmp;
cl349@5598 476
cl349@5598 477 cmp = (void *)simple_strtoul(token, NULL, 16);
cl349@5598 478
cl349@5598 479 list_for_each_entry(i, &watches, list)
cl349@5598 480 if (i == cmp)
cl349@5598 481 return i;
cl349@5598 482 return NULL;
cl349@5598 483 }
cl349@5598 484
cl349@5598 485 /* Register callback to watch this node. */
cl349@5598 486 int register_xenbus_watch(struct xenbus_watch *watch)
cl349@5598 487 {
cl349@5598 488 /* Pointer in ascii is the token. */
cl349@5598 489 char token[sizeof(watch) * 2 + 1];
cl349@5598 490 int err;
cl349@5598 491
cl349@5598 492 sprintf(token, "%lX", (long)watch);
cl349@5598 493 BUG_ON(find_watch(token));
cl349@5598 494
cl349@5876 495 err = xs_watch(watch->node, token);
cl349@5598 496 if (!err)
cl349@5598 497 list_add(&watch->list, &watches);
cl349@5598 498 return err;
cl349@5598 499 }
kaf24@6467 500 EXPORT_SYMBOL(register_xenbus_watch);
cl349@5598 501
cl349@5598 502 void unregister_xenbus_watch(struct xenbus_watch *watch)
cl349@5598 503 {
cl349@5598 504 char token[sizeof(watch) * 2 + 1];
cl349@5598 505 int err;
cl349@5598 506
cl349@5598 507 sprintf(token, "%lX", (long)watch);
cl349@5598 508 BUG_ON(!find_watch(token));
cl349@5598 509
cl349@5598 510 err = xs_unwatch(watch->node, token);
cl349@5598 511 list_del(&watch->list);
cl349@5598 512
cl349@5598 513 if (err)
cl349@5903 514 printk(KERN_WARNING
cl349@5903 515 "XENBUS Failed to release watch %s: %i\n",
cl349@5598 516 watch->node, err);
cl349@5598 517 }
kaf24@6467 518 EXPORT_SYMBOL(unregister_xenbus_watch);
cl349@5598 519
cl349@6209 520 /* Re-register callbacks to all watches. */
cl349@6209 521 void reregister_xenbus_watches(void)
cl349@6209 522 {
cl349@6209 523 struct xenbus_watch *watch;
cl349@6209 524 char token[sizeof(watch) * 2 + 1];
cl349@6209 525
cl349@6209 526 list_for_each_entry(watch, &watches, list) {
cl349@6209 527 sprintf(token, "%lX", (long)watch);
cl349@6209 528 xs_watch(watch->node, token);
cl349@6209 529 }
cl349@6209 530 }
cl349@6209 531
cl349@5598 532 static int watch_thread(void *unused)
cl349@5598 533 {
cl349@5598 534 for (;;) {
cl349@5598 535 char *token;
cl349@5598 536 char *node = NULL;
cl349@5598 537
cl349@5902 538 wait_event(xb_waitq, xs_input_avail());
cl349@5598 539
cl349@5598 540 /* If this is a spurious wakeup caused by someone
cl349@5598 541 * doing an op, they'll hold the lock and the buffer
cl349@5598 542 * will be empty by the time we get there.
cl349@5598 543 */
cl349@5863 544 down(&xenbus_lock);
cl349@5902 545 if (xs_input_avail())
cl349@5598 546 node = xs_read_watch(&token);
cl349@5747 547
cl349@5598 548 if (node && !IS_ERR(node)) {
cl349@5598 549 struct xenbus_watch *w;
cl349@5598 550 int err;
cl349@5598 551
cl349@5903 552 err = xs_acknowledge_watch(token);
cl349@5903 553 if (err)
cl349@5903 554 printk(KERN_WARNING "XENBUS ack %s fail %i\n",
cl349@5903 555 node, err);
cl349@5598 556 w = find_watch(token);
cl349@5598 557 BUG_ON(!w);
cl349@5598 558 w->callback(w, node);
cl349@5598 559 kfree(node);
cl349@6600 560 } else if (node)
cl349@5598 561 printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
cl349@5598 562 PTR_ERR(node));
cl349@5863 563 up(&xenbus_lock);
cl349@5598 564 }
cl349@5598 565 }
cl349@5598 566
cl349@5598 567 int xs_init(void)
cl349@5598 568 {
cl349@5598 569 int err;
cl349@5598 570 struct task_struct *watcher;
cl349@5598 571
cl349@5902 572 err = xb_init_comms();
cl349@5598 573 if (err)
cl349@5598 574 return err;
cl349@5598 575
cl349@5598 576 watcher = kthread_run(watch_thread, NULL, "kxbwatch");
cl349@5598 577 if (IS_ERR(watcher))
cl349@5598 578 return PTR_ERR(watcher);
cl349@5598 579 return 0;
cl349@5598 580 }