ia64/xen-unstable

view linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @ 7496:998e85f9963d

Need additional include for ia64
author djm@kirby.fc.hp.com
date Mon Oct 24 10:46:39 2005 -0600 (2005-10-24)
parents 5a728a884242
children eee0489b3a17
line source
1 /******************************************************************************
2 * xenbus_xs.c
3 *
4 * This is the kernel equivalent of the "xs" library. We don't need everything
5 * and we use xenbus_comms for communication.
6 *
7 * Copyright (C) 2005 Rusty Russell, IBM Corporation
8 *
9 * This file may be distributed separately from the Linux kernel, or
10 * incorporated into other software packages, subject to the following license:
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this source file (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use, copy, modify,
15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16 * and to permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
31 #include <linux/unistd.h>
32 #include <linux/errno.h>
33 #include <linux/types.h>
34 #include <linux/uio.h>
35 #include <linux/kernel.h>
36 #include <linux/string.h>
37 #include <linux/err.h>
38 #include <linux/slab.h>
39 #include <linux/fcntl.h>
40 #include <linux/kthread.h>
41 #include <asm-xen/xenbus.h>
42 #include "xenbus_comms.h"
44 #define streq(a, b) (strcmp((a), (b)) == 0)
46 struct xs_stored_msg {
47 struct list_head list;
49 struct xsd_sockmsg hdr;
51 union {
52 /* Queued replies. */
53 struct {
54 char *body;
55 } reply;
57 /* Queued watch events. */
58 struct {
59 struct xenbus_watch *handle;
60 char **vec;
61 unsigned int vec_size;
62 } watch;
63 } u;
64 };
66 struct xs_handle {
67 /* A list of replies. Currently only one will ever be outstanding. */
68 struct list_head reply_list;
69 spinlock_t reply_lock;
70 wait_queue_head_t reply_waitq;
72 /* One request at a time. */
73 struct semaphore request_mutex;
75 /* Protect transactions against save/restore. */
76 struct rw_semaphore suspend_mutex;
77 };
79 static struct xs_handle xs_state;
81 /* List of registered watches, and a lock to protect it. */
82 static LIST_HEAD(watches);
83 static DEFINE_SPINLOCK(watches_lock);
85 /* List of pending watch calbback events, and a lock to protect it. */
86 static LIST_HEAD(watch_events);
87 static DEFINE_SPINLOCK(watch_events_lock);
89 /*
90 * Details of the xenwatch callback kernel thread. The thread waits on the
91 * watch_events_waitq for work to do (queued on watch_events list). When it
92 * wakes up it acquires the xenwatch_mutex before reading the list and
93 * carrying out work.
94 */
95 static pid_t xenwatch_pid;
96 /* static */ DECLARE_MUTEX(xenwatch_mutex);
97 static DECLARE_WAIT_QUEUE_HEAD(watch_events_waitq);
99 static int get_error(const char *errorstring)
100 {
101 unsigned int i;
103 for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++) {
104 if (i == ARRAY_SIZE(xsd_errors) - 1) {
105 printk(KERN_WARNING
106 "XENBUS xen store gave: unknown error %s",
107 errorstring);
108 return EINVAL;
109 }
110 }
111 return xsd_errors[i].errnum;
112 }
114 static void *read_reply(enum xsd_sockmsg_type *type, unsigned int *len)
115 {
116 struct xs_stored_msg *msg;
117 char *body;
119 spin_lock(&xs_state.reply_lock);
121 while (list_empty(&xs_state.reply_list)) {
122 spin_unlock(&xs_state.reply_lock);
123 wait_event_interruptible(xs_state.reply_waitq,
124 !list_empty(&xs_state.reply_list));
125 spin_lock(&xs_state.reply_lock);
126 }
128 msg = list_entry(xs_state.reply_list.next,
129 struct xs_stored_msg, list);
130 list_del(&msg->list);
132 spin_unlock(&xs_state.reply_lock);
134 *type = msg->hdr.type;
135 if (len)
136 *len = msg->hdr.len;
137 body = msg->u.reply.body;
139 kfree(msg);
141 return body;
142 }
144 /* Emergency write. */
145 void xenbus_debug_write(const char *str, unsigned int count)
146 {
147 struct xsd_sockmsg msg = { 0 };
149 msg.type = XS_DEBUG;
150 msg.len = sizeof("print") + count + 1;
152 down(&xs_state.request_mutex);
153 xb_write(&msg, sizeof(msg));
154 xb_write("print", sizeof("print"));
155 xb_write(str, count);
156 xb_write("", 1);
157 up(&xs_state.request_mutex);
158 }
160 void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg)
161 {
162 void *ret;
163 struct xsd_sockmsg req_msg = *msg;
164 int err;
166 if (req_msg.type == XS_TRANSACTION_START)
167 down_read(&xs_state.suspend_mutex);
169 down(&xs_state.request_mutex);
171 err = xb_write(msg, sizeof(*msg) + msg->len);
172 if (err) {
173 msg->type = XS_ERROR;
174 ret = ERR_PTR(err);
175 } else {
176 ret = read_reply(&msg->type, &msg->len);
177 }
179 up(&xs_state.request_mutex);
181 if ((msg->type == XS_TRANSACTION_END) ||
182 ((req_msg.type == XS_TRANSACTION_START) &&
183 (msg->type == XS_ERROR)))
184 up_read(&xs_state.suspend_mutex);
186 return ret;
187 }
189 /* Send message to xs, get kmalloc'ed reply. ERR_PTR() on error. */
190 static void *xs_talkv(struct xenbus_transaction *t,
191 enum xsd_sockmsg_type type,
192 const struct kvec *iovec,
193 unsigned int num_vecs,
194 unsigned int *len)
195 {
196 struct xsd_sockmsg msg;
197 void *ret = NULL;
198 unsigned int i;
199 int err;
201 msg.tx_id = (u32)(unsigned long)t;
202 msg.type = type;
203 msg.len = 0;
204 for (i = 0; i < num_vecs; i++)
205 msg.len += iovec[i].iov_len;
207 down(&xs_state.request_mutex);
209 err = xb_write(&msg, sizeof(msg));
210 if (err) {
211 up(&xs_state.request_mutex);
212 return ERR_PTR(err);
213 }
215 for (i = 0; i < num_vecs; i++) {
216 err = xb_write(iovec[i].iov_base, iovec[i].iov_len);;
217 if (err) {
218 up(&xs_state.request_mutex);
219 return ERR_PTR(err);
220 }
221 }
223 ret = read_reply(&msg.type, len);
225 up(&xs_state.request_mutex);
227 if (IS_ERR(ret))
228 return ret;
230 if (msg.type == XS_ERROR) {
231 err = get_error(ret);
232 kfree(ret);
233 return ERR_PTR(-err);
234 }
236 BUG_ON(msg.type != type);
237 return ret;
238 }
240 /* Simplified version of xs_talkv: single message. */
241 static void *xs_single(struct xenbus_transaction *t,
242 enum xsd_sockmsg_type type,
243 const char *string,
244 unsigned int *len)
245 {
246 struct kvec iovec;
248 iovec.iov_base = (void *)string;
249 iovec.iov_len = strlen(string) + 1;
250 return xs_talkv(t, type, &iovec, 1, len);
251 }
253 /* Many commands only need an ack, don't care what it says. */
254 static int xs_error(char *reply)
255 {
256 if (IS_ERR(reply))
257 return PTR_ERR(reply);
258 kfree(reply);
259 return 0;
260 }
262 static unsigned int count_strings(const char *strings, unsigned int len)
263 {
264 unsigned int num;
265 const char *p;
267 for (p = strings, num = 0; p < strings + len; p += strlen(p) + 1)
268 num++;
270 return num;
271 }
273 /* Return the path to dir with /name appended. Buffer must be kfree()'ed. */
274 static char *join(const char *dir, const char *name)
275 {
276 char *buffer;
278 buffer = kmalloc(strlen(dir) + strlen("/") + strlen(name) + 1,
279 GFP_KERNEL);
280 if (buffer == NULL)
281 return ERR_PTR(-ENOMEM);
283 strcpy(buffer, dir);
284 if (!streq(name, "")) {
285 strcat(buffer, "/");
286 strcat(buffer, name);
287 }
289 return buffer;
290 }
292 static char **split(char *strings, unsigned int len, unsigned int *num)
293 {
294 char *p, **ret;
296 /* Count the strings. */
297 *num = count_strings(strings, len);
299 /* Transfer to one big alloc for easy freeing. */
300 ret = kmalloc(*num * sizeof(char *) + len, GFP_KERNEL);
301 if (!ret) {
302 kfree(strings);
303 return ERR_PTR(-ENOMEM);
304 }
305 memcpy(&ret[*num], strings, len);
306 kfree(strings);
308 strings = (char *)&ret[*num];
309 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
310 ret[(*num)++] = p;
312 return ret;
313 }
315 char **xenbus_directory(struct xenbus_transaction *t,
316 const char *dir, const char *node, unsigned int *num)
317 {
318 char *strings, *path;
319 unsigned int len;
321 path = join(dir, node);
322 if (IS_ERR(path))
323 return (char **)path;
325 strings = xs_single(t, XS_DIRECTORY, path, &len);
326 kfree(path);
327 if (IS_ERR(strings))
328 return (char **)strings;
330 return split(strings, len, num);
331 }
332 EXPORT_SYMBOL(xenbus_directory);
334 /* Check if a path exists. Return 1 if it does. */
335 int xenbus_exists(struct xenbus_transaction *t,
336 const char *dir, const char *node)
337 {
338 char **d;
339 int dir_n;
341 d = xenbus_directory(t, dir, node, &dir_n);
342 if (IS_ERR(d))
343 return 0;
344 kfree(d);
345 return 1;
346 }
347 EXPORT_SYMBOL(xenbus_exists);
349 /* Get the value of a single file.
350 * Returns a kmalloced value: call free() on it after use.
351 * len indicates length in bytes.
352 */
353 void *xenbus_read(struct xenbus_transaction *t,
354 const char *dir, const char *node, unsigned int *len)
355 {
356 char *path;
357 void *ret;
359 path = join(dir, node);
360 if (IS_ERR(path))
361 return (void *)path;
363 ret = xs_single(t, XS_READ, path, len);
364 kfree(path);
365 return ret;
366 }
367 EXPORT_SYMBOL(xenbus_read);
369 /* Write the value of a single file.
370 * Returns -err on failure.
371 */
372 int xenbus_write(struct xenbus_transaction *t,
373 const char *dir, const char *node, const char *string)
374 {
375 const char *path;
376 struct kvec iovec[2];
377 int ret;
379 path = join(dir, node);
380 if (IS_ERR(path))
381 return PTR_ERR(path);
383 iovec[0].iov_base = (void *)path;
384 iovec[0].iov_len = strlen(path) + 1;
385 iovec[1].iov_base = (void *)string;
386 iovec[1].iov_len = strlen(string);
388 ret = xs_error(xs_talkv(t, XS_WRITE, iovec, ARRAY_SIZE(iovec), NULL));
389 kfree(path);
390 return ret;
391 }
392 EXPORT_SYMBOL(xenbus_write);
394 /* Create a new directory. */
395 int xenbus_mkdir(struct xenbus_transaction *t,
396 const char *dir, const char *node)
397 {
398 char *path;
399 int ret;
401 path = join(dir, node);
402 if (IS_ERR(path))
403 return PTR_ERR(path);
405 ret = xs_error(xs_single(t, XS_MKDIR, path, NULL));
406 kfree(path);
407 return ret;
408 }
409 EXPORT_SYMBOL(xenbus_mkdir);
411 /* Destroy a file or directory (directories must be empty). */
412 int xenbus_rm(struct xenbus_transaction *t, const char *dir, const char *node)
413 {
414 char *path;
415 int ret;
417 path = join(dir, node);
418 if (IS_ERR(path))
419 return PTR_ERR(path);
421 ret = xs_error(xs_single(t, XS_RM, path, NULL));
422 kfree(path);
423 return ret;
424 }
425 EXPORT_SYMBOL(xenbus_rm);
427 /* Start a transaction: changes by others will not be seen during this
428 * transaction, and changes will not be visible to others until end.
429 */
430 struct xenbus_transaction *xenbus_transaction_start(void)
431 {
432 char *id_str;
433 unsigned long id;
435 down_read(&xs_state.suspend_mutex);
437 id_str = xs_single(NULL, XS_TRANSACTION_START, "", NULL);
438 if (IS_ERR(id_str)) {
439 up_read(&xs_state.suspend_mutex);
440 return (struct xenbus_transaction *)id_str;
441 }
443 id = simple_strtoul(id_str, NULL, 0);
444 kfree(id_str);
446 return (struct xenbus_transaction *)id;
447 }
448 EXPORT_SYMBOL(xenbus_transaction_start);
450 /* End a transaction.
451 * If abandon is true, transaction is discarded instead of committed.
452 */
453 int xenbus_transaction_end(struct xenbus_transaction *t, int abort)
454 {
455 char abortstr[2];
456 int err;
458 if (abort)
459 strcpy(abortstr, "F");
460 else
461 strcpy(abortstr, "T");
463 err = xs_error(xs_single(t, XS_TRANSACTION_END, abortstr, NULL));
465 up_read(&xs_state.suspend_mutex);
467 return err;
468 }
469 EXPORT_SYMBOL(xenbus_transaction_end);
471 /* Single read and scanf: returns -errno or num scanned. */
472 int xenbus_scanf(struct xenbus_transaction *t,
473 const char *dir, const char *node, const char *fmt, ...)
474 {
475 va_list ap;
476 int ret;
477 char *val;
479 val = xenbus_read(t, dir, node, NULL);
480 if (IS_ERR(val))
481 return PTR_ERR(val);
483 va_start(ap, fmt);
484 ret = vsscanf(val, fmt, ap);
485 va_end(ap);
486 kfree(val);
487 /* Distinctive errno. */
488 if (ret == 0)
489 return -ERANGE;
490 return ret;
491 }
492 EXPORT_SYMBOL(xenbus_scanf);
494 /* Single printf and write: returns -errno or 0. */
495 int xenbus_printf(struct xenbus_transaction *t,
496 const char *dir, const char *node, const char *fmt, ...)
497 {
498 va_list ap;
499 int ret;
500 #define PRINTF_BUFFER_SIZE 4096
501 char *printf_buffer;
503 printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
504 if (printf_buffer == NULL)
505 return -ENOMEM;
507 va_start(ap, fmt);
508 ret = vsnprintf(printf_buffer, PRINTF_BUFFER_SIZE, fmt, ap);
509 va_end(ap);
511 BUG_ON(ret > PRINTF_BUFFER_SIZE-1);
512 ret = xenbus_write(t, dir, node, printf_buffer);
514 kfree(printf_buffer);
516 return ret;
517 }
518 EXPORT_SYMBOL(xenbus_printf);
520 /**
521 * Return the path to the error node for the given device, or NULL on failure.
522 * If the value returned is non-NULL, then it is the caller's to kfree.
523 */
524 static char *error_path(struct xenbus_device *dev)
525 {
526 char *path_buffer = kmalloc(strlen("error/") + strlen(dev->nodename) +
527 1, GFP_KERNEL);
528 if (path_buffer == NULL) {
529 return NULL;
530 }
532 strcpy(path_buffer, "error/");
533 strcpy(path_buffer + strlen("error/"), dev->nodename);
535 return path_buffer;
536 }
538 /* Report a (negative) errno into the store, with explanation. */
539 void xenbus_dev_error(struct xenbus_device *dev, int err, const char *fmt, ...)
540 {
541 va_list ap;
542 int ret;
543 unsigned int len;
544 char *printf_buffer = NULL, *path_buffer = NULL;
546 printf_buffer = kmalloc(PRINTF_BUFFER_SIZE, GFP_KERNEL);
547 if (printf_buffer == NULL) {
548 printk("xenbus: failed to write error node for %s (%d): %d\n",
549 dev->nodename, err, errno);
550 goto fail;
551 }
553 len = sprintf(printf_buffer, "%i ", -err);
554 va_start(ap, fmt);
555 ret = vsnprintf(printf_buffer+len, PRINTF_BUFFER_SIZE-len, fmt, ap);
556 va_end(ap);
558 BUG_ON(len + ret > PRINTF_BUFFER_SIZE-1);
559 dev->has_error = 1;
561 path_buffer = error_path(dev);
563 if (path_buffer == NULL) {
564 printk("xenbus: failed to write error node for %s (%s): %d\n",
565 dev->nodename, printf_buffer, errno);
566 goto fail;
567 }
569 if (xenbus_write(NULL, path_buffer, "error", printf_buffer) != 0) {
570 printk("xenbus: failed to write error node for %s (%s)\n",
571 dev->nodename, printf_buffer);
572 goto fail;
573 }
575 fail:
576 if (printf_buffer)
577 kfree(printf_buffer);
578 if (path_buffer)
579 kfree(path_buffer);
580 }
581 EXPORT_SYMBOL(xenbus_dev_error);
583 /* Clear any error. */
584 void xenbus_dev_ok(struct xenbus_device *dev)
585 {
586 if (dev->has_error) {
587 char *path_buffer = error_path(dev);
589 if (path_buffer == NULL) {
590 printk("xenbus: failed to clear error node for %s: "
591 "%d\n", dev->nodename, errno);
592 return;
593 }
595 if (xenbus_rm(NULL, path_buffer, "error") != 0)
596 printk("xenbus: failed to clear error node for %s\n",
597 dev->nodename);
598 else
599 dev->has_error = 0;
601 kfree(path_buffer);
602 }
603 }
604 EXPORT_SYMBOL(xenbus_dev_ok);
606 /* Takes tuples of names, scanf-style args, and void **, NULL terminated. */
607 int xenbus_gather(struct xenbus_transaction *t, const char *dir, ...)
608 {
609 va_list ap;
610 const char *name;
611 int ret = 0;
613 va_start(ap, dir);
614 while (ret == 0 && (name = va_arg(ap, char *)) != NULL) {
615 const char *fmt = va_arg(ap, char *);
616 void *result = va_arg(ap, void *);
617 char *p;
619 p = xenbus_read(t, dir, name, NULL);
620 if (IS_ERR(p)) {
621 ret = PTR_ERR(p);
622 break;
623 }
624 if (fmt) {
625 if (sscanf(p, fmt, result) == 0)
626 ret = -EINVAL;
627 kfree(p);
628 } else
629 *(char **)result = p;
630 }
631 va_end(ap);
632 return ret;
633 }
634 EXPORT_SYMBOL(xenbus_gather);
636 static int xs_watch(const char *path, const char *token)
637 {
638 struct kvec iov[2];
640 iov[0].iov_base = (void *)path;
641 iov[0].iov_len = strlen(path) + 1;
642 iov[1].iov_base = (void *)token;
643 iov[1].iov_len = strlen(token) + 1;
645 return xs_error(xs_talkv(NULL, XS_WATCH, iov,
646 ARRAY_SIZE(iov), NULL));
647 }
649 static int xs_unwatch(const char *path, const char *token)
650 {
651 struct kvec iov[2];
653 iov[0].iov_base = (char *)path;
654 iov[0].iov_len = strlen(path) + 1;
655 iov[1].iov_base = (char *)token;
656 iov[1].iov_len = strlen(token) + 1;
658 return xs_error(xs_talkv(NULL, XS_UNWATCH, iov,
659 ARRAY_SIZE(iov), NULL));
660 }
662 static struct xenbus_watch *find_watch(const char *token)
663 {
664 struct xenbus_watch *i, *cmp;
666 cmp = (void *)simple_strtoul(token, NULL, 16);
668 list_for_each_entry(i, &watches, list)
669 if (i == cmp)
670 return i;
672 return NULL;
673 }
675 /* Register callback to watch this node. */
676 int register_xenbus_watch(struct xenbus_watch *watch)
677 {
678 /* Pointer in ascii is the token. */
679 char token[sizeof(watch) * 2 + 1];
680 int err;
682 sprintf(token, "%lX", (long)watch);
684 down_read(&xs_state.suspend_mutex);
686 spin_lock(&watches_lock);
687 BUG_ON(find_watch(token));
688 spin_unlock(&watches_lock);
690 err = xs_watch(watch->node, token);
692 /* Ignore errors due to multiple registration. */
693 if ((err == 0) || (err == -EEXIST)) {
694 spin_lock(&watches_lock);
695 list_add(&watch->list, &watches);
696 spin_unlock(&watches_lock);
697 }
699 up_read(&xs_state.suspend_mutex);
701 return err;
702 }
703 EXPORT_SYMBOL(register_xenbus_watch);
705 void unregister_xenbus_watch(struct xenbus_watch *watch)
706 {
707 struct xs_stored_msg *msg, *tmp;
708 char token[sizeof(watch) * 2 + 1];
709 int err;
711 sprintf(token, "%lX", (long)watch);
713 down_read(&xs_state.suspend_mutex);
715 spin_lock(&watches_lock);
716 BUG_ON(!find_watch(token));
717 list_del(&watch->list);
718 spin_unlock(&watches_lock);
720 err = xs_unwatch(watch->node, token);
721 if (err)
722 printk(KERN_WARNING
723 "XENBUS Failed to release watch %s: %i\n",
724 watch->node, err);
726 up_read(&xs_state.suspend_mutex);
728 /* Cancel pending watch events. */
729 spin_lock(&watch_events_lock);
730 list_for_each_entry_safe(msg, tmp, &watch_events, list) {
731 if (msg->u.watch.handle != watch)
732 continue;
733 list_del(&msg->list);
734 kfree(msg->u.watch.vec);
735 kfree(msg);
736 }
737 spin_unlock(&watch_events_lock);
739 /* Flush any currently-executing callback, unless we are it. :-) */
740 if (current->pid != xenwatch_pid) {
741 down(&xenwatch_mutex);
742 up(&xenwatch_mutex);
743 }
744 }
745 EXPORT_SYMBOL(unregister_xenbus_watch);
747 void xs_suspend(void)
748 {
749 down_write(&xs_state.suspend_mutex);
750 down(&xs_state.request_mutex);
751 }
753 void xs_resume(void)
754 {
755 struct xenbus_watch *watch;
756 char token[sizeof(watch) * 2 + 1];
758 up(&xs_state.request_mutex);
760 /* No need for watches_lock: the suspend_mutex is sufficient. */
761 list_for_each_entry(watch, &watches, list) {
762 sprintf(token, "%lX", (long)watch);
763 xs_watch(watch->node, token);
764 }
766 up_write(&xs_state.suspend_mutex);
767 }
769 static int xenwatch_thread(void *unused)
770 {
771 struct list_head *ent;
772 struct xs_stored_msg *msg;
774 for (;;) {
775 wait_event_interruptible(watch_events_waitq,
776 !list_empty(&watch_events));
778 down(&xenwatch_mutex);
780 spin_lock(&watch_events_lock);
781 ent = watch_events.next;
782 if (ent != &watch_events)
783 list_del(ent);
784 spin_unlock(&watch_events_lock);
786 if (ent != &watch_events) {
787 msg = list_entry(ent, struct xs_stored_msg, list);
788 msg->u.watch.handle->callback(
789 msg->u.watch.handle,
790 (const char **)msg->u.watch.vec,
791 msg->u.watch.vec_size);
792 kfree(msg->u.watch.vec);
793 kfree(msg);
794 }
796 up(&xenwatch_mutex);
797 }
798 }
800 static int process_msg(void)
801 {
802 struct xs_stored_msg *msg;
803 char *body;
804 int err;
806 msg = kmalloc(sizeof(*msg), GFP_KERNEL);
807 if (msg == NULL)
808 return -ENOMEM;
810 err = xb_read(&msg->hdr, sizeof(msg->hdr));
811 if (err) {
812 kfree(msg);
813 return err;
814 }
816 body = kmalloc(msg->hdr.len + 1, GFP_KERNEL);
817 if (body == NULL) {
818 kfree(msg);
819 return -ENOMEM;
820 }
822 err = xb_read(body, msg->hdr.len);
823 if (err) {
824 kfree(body);
825 kfree(msg);
826 return err;
827 }
828 body[msg->hdr.len] = '\0';
830 if (msg->hdr.type == XS_WATCH_EVENT) {
831 msg->u.watch.vec = split(body, msg->hdr.len,
832 &msg->u.watch.vec_size);
833 if (IS_ERR(msg->u.watch.vec)) {
834 kfree(msg);
835 return PTR_ERR(msg->u.watch.vec);
836 }
838 spin_lock(&watches_lock);
839 msg->u.watch.handle = find_watch(
840 msg->u.watch.vec[XS_WATCH_TOKEN]);
841 if (msg->u.watch.handle != NULL) {
842 spin_lock(&watch_events_lock);
843 list_add_tail(&msg->list, &watch_events);
844 wake_up(&watch_events_waitq);
845 spin_unlock(&watch_events_lock);
846 } else {
847 kfree(msg->u.watch.vec);
848 kfree(msg);
849 }
850 spin_unlock(&watches_lock);
851 } else {
852 msg->u.reply.body = body;
853 spin_lock(&xs_state.reply_lock);
854 list_add_tail(&msg->list, &xs_state.reply_list);
855 spin_unlock(&xs_state.reply_lock);
856 wake_up(&xs_state.reply_waitq);
857 }
859 return 0;
860 }
862 static int xenbus_thread(void *unused)
863 {
864 int err;
866 for (;;) {
867 err = process_msg();
868 if (err)
869 printk(KERN_WARNING "XENBUS error %d while reading "
870 "message\n", err);
871 }
872 }
874 int xs_init(void)
875 {
876 int err;
877 struct task_struct *task;
879 INIT_LIST_HEAD(&xs_state.reply_list);
880 spin_lock_init(&xs_state.reply_lock);
881 init_waitqueue_head(&xs_state.reply_waitq);
883 init_MUTEX(&xs_state.request_mutex);
884 init_rwsem(&xs_state.suspend_mutex);
886 /* Initialize the shared memory rings to talk to xenstored */
887 err = xb_init_comms();
888 if (err)
889 return err;
891 task = kthread_run(xenwatch_thread, NULL, "xenwatch");
892 if (IS_ERR(task))
893 return PTR_ERR(task);
894 xenwatch_pid = task->pid;
896 task = kthread_run(xenbus_thread, NULL, "xenbus");
897 if (IS_ERR(task))
898 return PTR_ERR(task);
900 return 0;
901 }
903 /*
904 * Local variables:
905 * c-file-style: "linux"
906 * indent-tabs-mode: t
907 * c-indent-level: 8
908 * c-basic-offset: 8
909 * tab-width: 8
910 * End:
911 */