xen-vtx-unstable

annotate linux-2.6.11-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @ 5598:864b050694f8

bitkeeper revision 1.1766 (42c17071SPDLo7qPlXAiQzrKjMu6Mw)

Add xenbus driver.
XendDomainInfo.py:
Connect/Disconnect domains to/from store.
Signed-off-by: Rusty Russel <rusty@rustcorp.com.au> (authored)
Signed-off-by: Mike Wray <mike.wray@hp.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
author cl349@firebug.cl.cam.ac.uk
date Tue Jun 28 15:44:49 2005 +0000 (2005-06-28)
parents
children 47295d6ca1d7
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@5598 5 * and we use xenbus_comms to 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 "xenstore/xenstored.h"
cl349@5598 34 #include <linux/uio.h>
cl349@5598 35 #include <linux/kernel.h>
cl349@5598 36 #include <linux/string.h>
cl349@5598 37 #include <linux/err.h>
cl349@5598 38 #include <linux/slab.h>
cl349@5598 39 #include <linux/fcntl.h>
cl349@5598 40 #include <linux/kthread.h>
cl349@5598 41 #include <asm-xen/xenbus.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@5598 46 static void *xs_in, *xs_out;
cl349@5598 47 static LIST_HEAD(watches);
cl349@5598 48 static DECLARE_MUTEX(watches_lock);
cl349@5598 49 DECLARE_MUTEX(xs_lock);
cl349@5598 50
cl349@5598 51 static int get_error(const char *errorstring)
cl349@5598 52 {
cl349@5598 53 unsigned int i;
cl349@5598 54
cl349@5598 55 for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
cl349@5598 56 if (i == ARRAY_SIZE(xsd_errors) - 1) {
cl349@5598 57 printk(KERN_WARNING "XENBUS xen store gave: unknown error %s",
cl349@5598 58 errorstring);
cl349@5598 59 return EINVAL;
cl349@5598 60 }
cl349@5598 61 }
cl349@5598 62 return xsd_errors[i].errnum;
cl349@5598 63 }
cl349@5598 64
cl349@5598 65 static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
cl349@5598 66 {
cl349@5598 67 struct xsd_sockmsg msg;
cl349@5598 68 void *ret;
cl349@5598 69 int err;
cl349@5598 70
cl349@5598 71 err = xb_read(xs_in, &msg, sizeof(msg));
cl349@5598 72 if (err)
cl349@5598 73 return ERR_PTR(err);
cl349@5598 74
cl349@5598 75 ret = kmalloc(msg.len + 1, GFP_KERNEL);
cl349@5598 76 if (!ret)
cl349@5598 77 return ERR_PTR(-ENOMEM);
cl349@5598 78
cl349@5598 79 err = xb_read(xs_in, ret, msg.len);
cl349@5598 80 if (err) {
cl349@5598 81 kfree(ret);
cl349@5598 82 return ERR_PTR(err);
cl349@5598 83 }
cl349@5598 84 ((char*)ret)[msg.len] = '\0';
cl349@5598 85
cl349@5598 86 *type = msg.type;
cl349@5598 87 if (len)
cl349@5598 88 *len = msg.len;
cl349@5598 89 return ret;
cl349@5598 90 }
cl349@5598 91
cl349@5598 92 /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
cl349@5598 93 static void *xs_talkv(enum xsd_sockmsg_type type,
cl349@5598 94 const struct kvec *iovec,
cl349@5598 95 unsigned int num_vecs,
cl349@5598 96 unsigned int *len)
cl349@5598 97 {
cl349@5598 98 struct xsd_sockmsg msg;
cl349@5598 99 void *ret = NULL;
cl349@5598 100 unsigned int i;
cl349@5598 101 int err;
cl349@5598 102
cl349@5598 103 WARN_ON(down_trylock(&xs_lock) == 0);
cl349@5598 104
cl349@5598 105 msg.type = type;
cl349@5598 106 msg.len = 0;
cl349@5598 107 for (i = 0; i < num_vecs; i++)
cl349@5598 108 msg.len += iovec[i].iov_len;
cl349@5598 109
cl349@5598 110 err = xb_write(xs_out, &msg, sizeof(msg));
cl349@5598 111 if (err)
cl349@5598 112 return ERR_PTR(err);
cl349@5598 113
cl349@5598 114 for (i = 0; i < num_vecs; i++) {
cl349@5598 115 err = xb_write(xs_out, iovec[i].iov_base, iovec[i].iov_len);;
cl349@5598 116 if (err)
cl349@5598 117 return ERR_PTR(err);
cl349@5598 118 }
cl349@5598 119
cl349@5598 120 /* Watches can have fired before reply comes: daemon detects
cl349@5598 121 * and re-transmits, so we can ignore this. */
cl349@5598 122 do {
cl349@5598 123 kfree(ret);
cl349@5598 124 ret = read_reply(&msg.type, len);
cl349@5598 125 if (IS_ERR(ret))
cl349@5598 126 return ret;
cl349@5598 127 } while (msg.type == XS_WATCH_EVENT);
cl349@5598 128
cl349@5598 129 if (msg.type == XS_ERROR) {
cl349@5598 130 err = get_error(ret);
cl349@5598 131 kfree(ret);
cl349@5598 132 return ERR_PTR(-err);
cl349@5598 133 }
cl349@5598 134
cl349@5598 135 BUG_ON(msg.type != type);
cl349@5598 136 return ret;
cl349@5598 137 }
cl349@5598 138
cl349@5598 139 /* Simplified version of xs_talkv: single message. */
cl349@5598 140 static void *xs_single(enum xsd_sockmsg_type type,
cl349@5598 141 const char *string, unsigned int *len)
cl349@5598 142 {
cl349@5598 143 struct kvec iovec;
cl349@5598 144
cl349@5598 145 iovec.iov_base = (void *)string;
cl349@5598 146 iovec.iov_len = strlen(string) + 1;
cl349@5598 147 return xs_talkv(type, &iovec, 1, len);
cl349@5598 148 }
cl349@5598 149
cl349@5598 150 /* Many commands only need an ack, don't care what it says. */
cl349@5598 151 static int xs_error(char *reply)
cl349@5598 152 {
cl349@5598 153 if (IS_ERR(reply))
cl349@5598 154 return PTR_ERR(reply);
cl349@5598 155 kfree(reply);
cl349@5598 156 return 0;
cl349@5598 157 }
cl349@5598 158
cl349@5598 159 static unsigned int count_strings(const char *strings, unsigned int len)
cl349@5598 160 {
cl349@5598 161 unsigned int num;
cl349@5598 162 const char *p;
cl349@5598 163
cl349@5598 164 for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
cl349@5598 165 num++;
cl349@5598 166
cl349@5598 167 return num;
cl349@5598 168 }
cl349@5598 169
cl349@5598 170 char **xs_directory(const char *path, unsigned int *num)
cl349@5598 171 {
cl349@5598 172 char *strings, *p, **ret;
cl349@5598 173 unsigned int len;
cl349@5598 174
cl349@5598 175 strings = xs_single(XS_DIRECTORY, path, &len);
cl349@5598 176 if (IS_ERR(strings))
cl349@5598 177 return (char **)strings;
cl349@5598 178
cl349@5598 179 /* Count the strings. */
cl349@5598 180 *num = count_strings(strings, len);
cl349@5598 181
cl349@5598 182 /* Transfer to one big alloc for easy freeing. */
cl349@5598 183 ret = kmalloc(*num * sizeof(char *) + len, GFP_ATOMIC);
cl349@5598 184 if (!ret) {
cl349@5598 185 kfree(strings);
cl349@5598 186 return ERR_PTR(-ENOMEM);
cl349@5598 187 }
cl349@5598 188 memcpy(&ret[*num], strings, len);
cl349@5598 189 kfree(strings);
cl349@5598 190
cl349@5598 191 strings = (char *)&ret[*num];
cl349@5598 192 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
cl349@5598 193 ret[(*num)++] = p;
cl349@5598 194 return ret;
cl349@5598 195 }
cl349@5598 196
cl349@5598 197 /* Check if a path exists. Return 1 if it does. */
cl349@5598 198 int xs_exists(const char *path)
cl349@5598 199 {
cl349@5598 200 char **dir;
cl349@5598 201 int dir_n;
cl349@5598 202
cl349@5598 203 dir = xs_directory(path, &dir_n);
cl349@5598 204 if(IS_ERR(dir))
cl349@5598 205 return 0;
cl349@5598 206 kfree(dir);
cl349@5598 207 return 1;
cl349@5598 208 }
cl349@5598 209
cl349@5598 210 /* Make a directory, creating dirs on the path to it if necessary.
cl349@5598 211 * Return 0 on success, error code otherwise.
cl349@5598 212 */
cl349@5598 213 int xs_mkdirs(const char *path)
cl349@5598 214 {
cl349@5598 215 int err = 0;
cl349@5598 216 char s[strlen(path) + 1], *p = s;
cl349@5598 217
cl349@5598 218 if(xs_exists(path))
cl349@5598 219 goto out;
cl349@5598 220 strcpy(p, path);
cl349@5598 221 if(*p == '/')
cl349@5598 222 p++;
cl349@5598 223 for( ; ; ){
cl349@5598 224 p = strchr(p, '/');
cl349@5598 225 if(p)
cl349@5598 226 *p = '\0';
cl349@5598 227 if(!xs_exists(s)){
cl349@5598 228 err = xs_mkdir(s);
cl349@5598 229 if(err)
cl349@5598 230 goto out;
cl349@5598 231
cl349@5598 232 }
cl349@5598 233 if(!p)
cl349@5598 234 break;
cl349@5598 235 *p++ = '/';
cl349@5598 236 }
cl349@5598 237 out:
cl349@5598 238 return err;
cl349@5598 239 }
cl349@5598 240
cl349@5598 241
cl349@5598 242 /* Get the value of a single file.
cl349@5598 243 * Returns a kmalloced value: call free() on it after use.
cl349@5598 244 * len indicates length in bytes.
cl349@5598 245 */
cl349@5598 246 void *xs_read(const char *path, unsigned int *len)
cl349@5598 247 {
cl349@5598 248 return xs_single(XS_READ, path, len);
cl349@5598 249 }
cl349@5598 250
cl349@5598 251 /* Write the value of a single file.
cl349@5598 252 * Returns -err on failure. createflags can be 0, O_CREAT, or O_CREAT|O_EXCL.
cl349@5598 253 */
cl349@5598 254 int xs_write(const char *path,
cl349@5598 255 const void *data, unsigned int len, int createflags)
cl349@5598 256 {
cl349@5598 257 const char *flags;
cl349@5598 258 struct kvec iovec[3];
cl349@5598 259
cl349@5598 260 /* Format: Flags (as string), path, data. */
cl349@5598 261 if (createflags == 0)
cl349@5598 262 flags = XS_WRITE_NONE;
cl349@5598 263 else if (createflags == O_CREAT)
cl349@5598 264 flags = XS_WRITE_CREATE;
cl349@5598 265 else if (createflags == (O_CREAT|O_EXCL))
cl349@5598 266 flags = XS_WRITE_CREATE_EXCL;
cl349@5598 267 else
cl349@5598 268 return -EINVAL;
cl349@5598 269
cl349@5598 270 iovec[0].iov_base = (void *)path;
cl349@5598 271 iovec[0].iov_len = strlen(path) + 1;
cl349@5598 272 iovec[1].iov_base = (void *)flags;
cl349@5598 273 iovec[1].iov_len = strlen(flags) + 1;
cl349@5598 274 iovec[2].iov_base = (void *)data;
cl349@5598 275 iovec[2].iov_len = len;
cl349@5598 276
cl349@5598 277 return xs_error(xs_talkv(XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
cl349@5598 278 }
cl349@5598 279
cl349@5598 280 /* Create a new directory. */
cl349@5598 281 int xs_mkdir(const char *path)
cl349@5598 282 {
cl349@5598 283 return xs_error(xs_single(XS_MKDIR, path, NULL));
cl349@5598 284 }
cl349@5598 285
cl349@5598 286 /* Destroy a file or directory (directories must be empty). */
cl349@5598 287 int xs_rm(const char *path)
cl349@5598 288 {
cl349@5598 289 return xs_error(xs_single(XS_RM, path, NULL));
cl349@5598 290 }
cl349@5598 291
cl349@5598 292 /* Start a transaction: changes by others will not be seen during this
cl349@5598 293 * transaction, and changes will not be visible to others until end.
cl349@5598 294 * Transaction only applies to the given subtree.
cl349@5598 295 * You can only have one transaction at any time.
cl349@5598 296 */
cl349@5598 297 int xs_transaction_start(const char *subtree)
cl349@5598 298 {
cl349@5598 299 return xs_error(xs_single(XS_TRANSACTION_START, subtree, NULL));
cl349@5598 300 }
cl349@5598 301
cl349@5598 302 /* End a transaction.
cl349@5598 303 * If abandon is true, transaction is discarded instead of committed.
cl349@5598 304 */
cl349@5598 305 int xs_transaction_end(int abort)
cl349@5598 306 {
cl349@5598 307 char abortstr[2];
cl349@5598 308
cl349@5598 309 if (abort)
cl349@5598 310 strcpy(abortstr, "F");
cl349@5598 311 else
cl349@5598 312 strcpy(abortstr, "T");
cl349@5598 313 return xs_error(xs_single(XS_TRANSACTION_END, abortstr, NULL));
cl349@5598 314 }
cl349@5598 315
cl349@5598 316 char *xs_get_domain_path(domid_t domid)
cl349@5598 317 {
cl349@5598 318 char domid_str[32];
cl349@5598 319
cl349@5598 320 sprintf(domid_str, "%u", domid);
cl349@5598 321 return xs_single(XS_GETDOMAINPATH, domid_str, NULL);
cl349@5598 322 }
cl349@5598 323
cl349@5598 324 static int xs_watch(const char *path, const char *token, unsigned int priority)
cl349@5598 325 {
cl349@5598 326 char prio[32];
cl349@5598 327 struct kvec iov[3];
cl349@5598 328
cl349@5598 329 sprintf(prio, "%u", priority);
cl349@5598 330 iov[0].iov_base = (void *)path;
cl349@5598 331 iov[0].iov_len = strlen(path) + 1;
cl349@5598 332 iov[1].iov_base = (void *)token;
cl349@5598 333 iov[1].iov_len = strlen(token) + 1;
cl349@5598 334 iov[2].iov_base = prio;
cl349@5598 335 iov[2].iov_len = strlen(prio) + 1;
cl349@5598 336
cl349@5598 337 return xs_error(xs_talkv(XS_WATCH, iov, ARRAY_SIZE(iov), NULL));
cl349@5598 338 }
cl349@5598 339
cl349@5598 340 static char *xs_read_watch(char **token)
cl349@5598 341 {
cl349@5598 342 enum xsd_sockmsg_type type;
cl349@5598 343 char *ret;
cl349@5598 344
cl349@5598 345 ret = read_reply(&type, NULL);
cl349@5598 346 if (IS_ERR(ret))
cl349@5598 347 return ret;
cl349@5598 348
cl349@5598 349 BUG_ON(type != XS_WATCH_EVENT);
cl349@5598 350 *token = ret + strlen(ret) + 1;
cl349@5598 351 return ret;
cl349@5598 352 }
cl349@5598 353
cl349@5598 354 static int xs_acknowledge_watch(const char *token)
cl349@5598 355 {
cl349@5598 356 return xs_error(xs_single(XS_WATCH_ACK, token, NULL));
cl349@5598 357 }
cl349@5598 358
cl349@5598 359 static int xs_unwatch(const char *path, const char *token)
cl349@5598 360 {
cl349@5598 361 struct kvec iov[2];
cl349@5598 362
cl349@5598 363 iov[0].iov_base = (char *)path;
cl349@5598 364 iov[0].iov_len = strlen(path) + 1;
cl349@5598 365 iov[1].iov_base = (char *)token;
cl349@5598 366 iov[1].iov_len = strlen(token) + 1;
cl349@5598 367
cl349@5598 368 return xs_error(xs_talkv(XS_UNWATCH, iov, ARRAY_SIZE(iov), NULL));
cl349@5598 369 }
cl349@5598 370
cl349@5598 371 /* A little paranoia: we don't just trust token. */
cl349@5598 372 static struct xenbus_watch *find_watch(const char *token)
cl349@5598 373 {
cl349@5598 374 struct xenbus_watch *i, *cmp;
cl349@5598 375
cl349@5598 376 cmp = (void *)simple_strtoul(token, NULL, 16);
cl349@5598 377
cl349@5598 378 list_for_each_entry(i, &watches, list)
cl349@5598 379 if (i == cmp)
cl349@5598 380 return i;
cl349@5598 381 return NULL;
cl349@5598 382 }
cl349@5598 383
cl349@5598 384 /* Register callback to watch this node. */
cl349@5598 385 int register_xenbus_watch(struct xenbus_watch *watch)
cl349@5598 386 {
cl349@5598 387 /* Pointer in ascii is the token. */
cl349@5598 388 char token[sizeof(watch) * 2 + 1];
cl349@5598 389 int err;
cl349@5598 390
cl349@5598 391 sprintf(token, "%lX", (long)watch);
cl349@5598 392 down(&watches_lock);
cl349@5598 393 BUG_ON(find_watch(token));
cl349@5598 394
cl349@5598 395 down(&xs_lock);
cl349@5598 396 err = xs_watch(watch->node, token, watch->priority);
cl349@5598 397 up(&xs_lock);
cl349@5598 398 if (!err)
cl349@5598 399 list_add(&watch->list, &watches);
cl349@5598 400 up(&watches_lock);
cl349@5598 401 return err;
cl349@5598 402 }
cl349@5598 403
cl349@5598 404 void unregister_xenbus_watch(struct xenbus_watch *watch)
cl349@5598 405 {
cl349@5598 406 char token[sizeof(watch) * 2 + 1];
cl349@5598 407 int err;
cl349@5598 408
cl349@5598 409 sprintf(token, "%lX", (long)watch);
cl349@5598 410 down(&watches_lock);
cl349@5598 411 BUG_ON(!find_watch(token));
cl349@5598 412
cl349@5598 413 down(&xs_lock);
cl349@5598 414 err = xs_unwatch(watch->node, token);
cl349@5598 415 up(&xs_lock);
cl349@5598 416 list_del(&watch->list);
cl349@5598 417 up(&watches_lock);
cl349@5598 418
cl349@5598 419 if (err)
cl349@5598 420 printk(KERN_WARNING "XENBUS Failed to release watch %s: %i\n",
cl349@5598 421 watch->node, err);
cl349@5598 422 }
cl349@5598 423
cl349@5598 424 static int watch_thread(void *unused)
cl349@5598 425 {
cl349@5598 426 int err;
cl349@5598 427 unsigned long mtu;
cl349@5598 428
cl349@5598 429 set_current_state(TASK_INTERRUPTIBLE);
cl349@5598 430 schedule_timeout(HZ*10);
cl349@5598 431 printk("watch_thread, doing read\n");
cl349@5598 432 down(&xs_lock);
cl349@5598 433 err = xenbus_read_long("", "mtu", &mtu);
cl349@5598 434 up(&xs_lock);
cl349@5598 435 printk("fake field read: %i (%lu)\n", err, mtu);
cl349@5598 436
cl349@5598 437 for (;;) {
cl349@5598 438 char *token;
cl349@5598 439 char *node = NULL;
cl349@5598 440
cl349@5598 441 wait_event(xb_waitq, xs_input_avail(xs_in));
cl349@5598 442
cl349@5598 443 /* If this is a spurious wakeup caused by someone
cl349@5598 444 * doing an op, they'll hold the lock and the buffer
cl349@5598 445 * will be empty by the time we get there.
cl349@5598 446 */
cl349@5598 447 down(&xs_lock);
cl349@5598 448 if (xs_input_avail(xs_in))
cl349@5598 449 node = xs_read_watch(&token);
cl349@5598 450 /* Release lock before calling callback. */
cl349@5598 451 up(&xs_lock);
cl349@5598 452 if (node && !IS_ERR(node)) {
cl349@5598 453 struct xenbus_watch *w;
cl349@5598 454 int err;
cl349@5598 455
cl349@5598 456 down(&watches_lock);
cl349@5598 457 w = find_watch(token);
cl349@5598 458 BUG_ON(!w);
cl349@5598 459 w->callback(w, node);
cl349@5598 460 up(&watches_lock);
cl349@5598 461 down(&xs_lock);
cl349@5598 462 err = xs_acknowledge_watch(token);
cl349@5598 463 if (err)
cl349@5598 464 printk(KERN_WARNING
cl349@5598 465 "XENBUS acknowledge %s failed %i\n",
cl349@5598 466 node, err);
cl349@5598 467 up(&xs_lock);
cl349@5598 468 kfree(node);
cl349@5598 469 } else
cl349@5598 470 printk(KERN_WARNING "XENBUS xs_read_watch: %li\n",
cl349@5598 471 PTR_ERR(node));
cl349@5598 472 }
cl349@5598 473 }
cl349@5598 474
cl349@5598 475 int xs_init(void)
cl349@5598 476 {
cl349@5598 477 int err;
cl349@5598 478 struct task_struct *watcher;
cl349@5598 479
cl349@5598 480 err = xb_init_comms(&xs_in, &xs_out);
cl349@5598 481 if (err)
cl349@5598 482 return err;
cl349@5598 483
cl349@5598 484 watcher = kthread_run(watch_thread, NULL, "kxbwatch");
cl349@5598 485 if (IS_ERR(watcher))
cl349@5598 486 return PTR_ERR(watcher);
cl349@5598 487 return 0;
cl349@5598 488 }