debuggers.hg

view tools/xenstore/xs.c @ 22848:6341fe0f4e5a

Added tag 4.1.0-rc2 for changeset 9dca60d88c63
author Keir Fraser <keir@xen.org>
date Tue Jan 25 14:06:55 2011 +0000 (2011-01-25)
parents f46d49257da5
children
line source
1 /*
2 Xen Store Daemon interface providing simple tree-like database.
3 Copyright (C) 2005 Rusty Russell IBM Corporation
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <sys/uio.h>
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <stdbool.h>
29 #include <stdlib.h>
30 #include <assert.h>
31 #include <stdio.h>
32 #include <signal.h>
33 #include <stdint.h>
34 #include <errno.h>
35 #include "xs.h"
36 #include "list.h"
37 #include "utils.h"
39 struct xs_stored_msg {
40 struct list_head list;
41 struct xsd_sockmsg hdr;
42 char *body;
43 };
45 #ifdef USE_PTHREAD
47 #include <pthread.h>
49 struct xs_handle {
50 /* Communications channel to xenstore daemon. */
51 int fd;
53 /*
54 * A read thread which pulls messages off the comms channel and
55 * signals waiters.
56 */
57 pthread_t read_thr;
58 int read_thr_exists;
60 /*
61 * A list of fired watch messages, protected by a mutex. Users can
62 * wait on the conditional variable until a watch is pending.
63 */
64 struct list_head watch_list;
65 pthread_mutex_t watch_mutex;
66 pthread_cond_t watch_condvar;
68 /* Clients can select() on this pipe to wait for a watch to fire. */
69 int watch_pipe[2];
71 /*
72 * A list of replies. Currently only one will ever be outstanding
73 * because we serialise requests. The requester can wait on the
74 * conditional variable for its response.
75 */
76 struct list_head reply_list;
77 pthread_mutex_t reply_mutex;
78 pthread_cond_t reply_condvar;
80 /* One request at a time. */
81 pthread_mutex_t request_mutex;
83 /* Lock discipline:
84 * Only holder of the request lock may write to h->fd.
85 * Only holder of the request lock may access read_thr_exists.
86 * If read_thr_exists==0, only holder of request lock may read h->fd;
87 * If read_thr_exists==1, only the read thread may read h->fd.
88 * Only holder of the reply lock may access reply_list.
89 * Only holder of the watch lock may access watch_list.
90 * Lock hierarchy:
91 * The order in which to acquire locks is
92 * request_mutex
93 * reply_mutex
94 * watch_mutex
95 */
96 };
98 #define mutex_lock(m) pthread_mutex_lock(m)
99 #define mutex_unlock(m) pthread_mutex_unlock(m)
100 #define condvar_signal(c) pthread_cond_signal(c)
101 #define condvar_wait(c,m) pthread_cond_wait(c,m)
102 #define cleanup_push(f, a) \
103 pthread_cleanup_push((void (*)(void *))(f), (void *)(a))
104 /*
105 * Some definitions of pthread_cleanup_pop() are a macro starting with an
106 * end-brace. GCC then complains if we immediately precede that with a label.
107 * Hence we insert a dummy statement to appease the compiler in this situation.
108 */
109 #define cleanup_pop(run) ((void)0); pthread_cleanup_pop(run)
111 #define read_thread_exists(h) (h->read_thr_exists)
113 static void *read_thread(void *arg);
115 #else /* !defined(USE_PTHREAD) */
117 struct xs_handle {
118 int fd;
119 struct list_head reply_list;
120 struct list_head watch_list;
121 /* Clients can select() on this pipe to wait for a watch to fire. */
122 int watch_pipe[2];
123 };
125 #define mutex_lock(m) ((void)0)
126 #define mutex_unlock(m) ((void)0)
127 #define condvar_signal(c) ((void)0)
128 #define condvar_wait(c,m) ((void)0)
129 #define cleanup_push(f, a) ((void)0)
130 #define cleanup_pop(run) ((void)0)
131 #define read_thread_exists(h) (0)
133 #endif
135 static int read_message(struct xs_handle *h);
137 int xs_fileno(struct xs_handle *h)
138 {
139 char c = 0;
141 mutex_lock(&h->watch_mutex);
143 if ((h->watch_pipe[0] == -1) && (pipe(h->watch_pipe) != -1)) {
144 /* Kick things off if the watch list is already non-empty. */
145 if (!list_empty(&h->watch_list))
146 while (write(h->watch_pipe[1], &c, 1) != 1)
147 continue;
148 }
150 mutex_unlock(&h->watch_mutex);
152 return h->watch_pipe[0];
153 }
155 static int get_socket(const char *connect_to)
156 {
157 struct sockaddr_un addr;
158 int sock, saved_errno, flags;
160 sock = socket(PF_UNIX, SOCK_STREAM, 0);
161 if (sock < 0)
162 return -1;
164 if ((flags = fcntl(sock, F_GETFD)) < 0)
165 goto error;
166 flags |= FD_CLOEXEC;
167 if (fcntl(sock, F_SETFD, flags) < 0)
168 goto error;
170 addr.sun_family = AF_UNIX;
171 strcpy(addr.sun_path, connect_to);
173 if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) != 0)
174 goto error;
176 return sock;
178 error:
179 saved_errno = errno;
180 close(sock);
181 errno = saved_errno;
182 return -1;
183 }
185 static int get_dev(const char *connect_to, unsigned long flags)
186 {
187 if (flags & XS_OPEN_READONLY)
188 return open(connect_to, O_RDONLY);
189 else
190 return open(connect_to, O_RDWR);
191 }
193 static struct xs_handle *get_handle(const char *connect_to, unsigned long flags)
194 {
195 struct stat buf;
196 struct xs_handle *h = NULL;
197 int fd = -1, saved_errno;
199 if (stat(connect_to, &buf) != 0)
200 return NULL;
202 if (S_ISSOCK(buf.st_mode))
203 fd = get_socket(connect_to);
204 else
205 fd = get_dev(connect_to, flags);
207 if (fd == -1)
208 return NULL;
210 h = malloc(sizeof(*h));
211 if (h == NULL) {
212 saved_errno = errno;
213 close(fd);
214 errno = saved_errno;
215 return NULL;
216 }
218 memset(h, 0, sizeof(*h));
220 h->fd = fd;
222 INIT_LIST_HEAD(&h->reply_list);
223 INIT_LIST_HEAD(&h->watch_list);
225 /* Watch pipe is allocated on demand in xs_fileno(). */
226 h->watch_pipe[0] = h->watch_pipe[1] = -1;
228 #ifdef USE_PTHREAD
229 pthread_mutex_init(&h->watch_mutex, NULL);
230 pthread_cond_init(&h->watch_condvar, NULL);
232 pthread_mutex_init(&h->reply_mutex, NULL);
233 pthread_cond_init(&h->reply_condvar, NULL);
235 pthread_mutex_init(&h->request_mutex, NULL);
236 #endif
238 return h;
239 }
241 struct xs_handle *xs_daemon_open(void)
242 {
243 return xs_open(0);
244 }
246 struct xs_handle *xs_daemon_open_readonly(void)
247 {
248 return xs_open(XS_OPEN_READONLY);
249 }
251 struct xs_handle *xs_domain_open(void)
252 {
253 return xs_open(0);
254 }
256 struct xs_handle *xs_open(unsigned long flags)
257 {
258 struct xs_handle *xsh = NULL;
260 if (flags & XS_OPEN_READONLY)
261 xsh = get_handle(xs_daemon_socket_ro(), flags);
262 else
263 xsh = get_handle(xs_daemon_socket(), flags);
265 if (!xsh && !(flags & XS_OPEN_SOCKETONLY))
266 xsh = get_handle(xs_domain_dev(), flags);
268 return xsh;
269 }
271 static void close_free_msgs(struct xs_handle *h) {
272 struct xs_stored_msg *msg, *tmsg;
274 list_for_each_entry_safe(msg, tmsg, &h->reply_list, list) {
275 free(msg->body);
276 free(msg);
277 }
279 list_for_each_entry_safe(msg, tmsg, &h->watch_list, list) {
280 free(msg->body);
281 free(msg);
282 }
283 }
285 static void close_fds_free(struct xs_handle *h) {
286 if (h->watch_pipe[0] != -1) {
287 close(h->watch_pipe[0]);
288 close(h->watch_pipe[1]);
289 }
291 close(h->fd);
293 free(h);
294 }
296 void xs_daemon_destroy_postfork(struct xs_handle *h)
297 {
298 close_free_msgs(h);
299 close_fds_free(h);
300 }
302 void xs_daemon_close(struct xs_handle *h)
303 {
304 #ifdef USE_PTHREAD
305 if (h->read_thr_exists) {
306 pthread_cancel(h->read_thr);
307 pthread_join(h->read_thr, NULL);
308 }
309 #endif
311 mutex_lock(&h->request_mutex);
312 mutex_lock(&h->reply_mutex);
313 mutex_lock(&h->watch_mutex);
315 close_free_msgs(h);
317 mutex_unlock(&h->request_mutex);
318 mutex_unlock(&h->reply_mutex);
319 mutex_unlock(&h->watch_mutex);
321 close_fds_free(h);
322 }
324 void xs_close(struct xs_handle* xsh)
325 {
326 if (xsh)
327 xs_daemon_close(xsh);
328 }
330 static bool read_all(int fd, void *data, unsigned int len)
331 {
332 while (len) {
333 int done;
335 done = read(fd, data, len);
336 if (done < 0) {
337 if (errno == EINTR)
338 continue;
339 return false;
340 }
341 if (done == 0) {
342 /* It closed fd on us? EBADF is appropriate. */
343 errno = EBADF;
344 return false;
345 }
346 data += done;
347 len -= done;
348 }
350 return true;
351 }
353 #ifdef XSTEST
354 #define read_all read_all_choice
355 #define xs_write_all write_all_choice
356 #endif
358 static int get_error(const char *errorstring)
359 {
360 unsigned int i;
362 for (i = 0; !streq(errorstring, xsd_errors[i].errstring); i++)
363 if (i == ARRAY_SIZE(xsd_errors) - 1)
364 return EINVAL;
365 return xsd_errors[i].errnum;
366 }
368 /* Adds extra nul terminator, because we generally (always?) hold strings. */
369 static void *read_reply(
370 struct xs_handle *h, enum xsd_sockmsg_type *type, unsigned int *len)
371 {
372 struct xs_stored_msg *msg;
373 char *body;
374 int read_from_thread;
376 read_from_thread = read_thread_exists(h);
378 /* Read from comms channel ourselves if there is no reader thread. */
379 if (!read_from_thread && (read_message(h) == -1))
380 return NULL;
382 mutex_lock(&h->reply_mutex);
383 #ifdef USE_PTHREAD
384 while (list_empty(&h->reply_list) && read_from_thread && h->fd != -1)
385 condvar_wait(&h->reply_condvar, &h->reply_mutex);
386 #endif
387 if (list_empty(&h->reply_list)) {
388 mutex_unlock(&h->reply_mutex);
389 errno = EINVAL;
390 return NULL;
391 }
392 msg = list_top(&h->reply_list, struct xs_stored_msg, list);
393 list_del(&msg->list);
394 assert(list_empty(&h->reply_list));
395 mutex_unlock(&h->reply_mutex);
397 *type = msg->hdr.type;
398 if (len)
399 *len = msg->hdr.len;
400 body = msg->body;
402 free(msg);
404 return body;
405 }
407 /* Send message to xs, get malloc'ed reply. NULL and set errno on error. */
408 static void *xs_talkv(struct xs_handle *h, xs_transaction_t t,
409 enum xsd_sockmsg_type type,
410 const struct iovec *iovec,
411 unsigned int num_vecs,
412 unsigned int *len)
413 {
414 struct xsd_sockmsg msg;
415 void *ret = NULL;
416 int saved_errno;
417 unsigned int i;
418 struct sigaction ignorepipe, oldact;
420 msg.tx_id = t;
421 msg.req_id = 0;
422 msg.type = type;
423 msg.len = 0;
424 for (i = 0; i < num_vecs; i++)
425 msg.len += iovec[i].iov_len;
427 if (msg.len > XENSTORE_PAYLOAD_MAX) {
428 errno = E2BIG;
429 return 0;
430 }
432 ignorepipe.sa_handler = SIG_IGN;
433 sigemptyset(&ignorepipe.sa_mask);
434 ignorepipe.sa_flags = 0;
435 sigaction(SIGPIPE, &ignorepipe, &oldact);
437 mutex_lock(&h->request_mutex);
439 if (!xs_write_all(h->fd, &msg, sizeof(msg)))
440 goto fail;
442 for (i = 0; i < num_vecs; i++)
443 if (!xs_write_all(h->fd, iovec[i].iov_base, iovec[i].iov_len))
444 goto fail;
446 ret = read_reply(h, &msg.type, len);
447 if (!ret)
448 goto fail;
450 mutex_unlock(&h->request_mutex);
452 sigaction(SIGPIPE, &oldact, NULL);
453 if (msg.type == XS_ERROR) {
454 saved_errno = get_error(ret);
455 free(ret);
456 errno = saved_errno;
457 return NULL;
458 }
460 if (msg.type != type) {
461 free(ret);
462 saved_errno = EBADF;
463 goto close_fd;
464 }
465 return ret;
467 fail:
468 /* We're in a bad state, so close fd. */
469 saved_errno = errno;
470 mutex_unlock(&h->request_mutex);
471 sigaction(SIGPIPE, &oldact, NULL);
472 close_fd:
473 close(h->fd);
474 h->fd = -1;
475 errno = saved_errno;
476 return NULL;
477 }
479 /* free(), but don't change errno. */
480 static void free_no_errno(void *p)
481 {
482 int saved_errno = errno;
483 free(p);
484 errno = saved_errno;
485 }
487 /* Simplified version of xs_talkv: single message. */
488 static void *xs_single(struct xs_handle *h, xs_transaction_t t,
489 enum xsd_sockmsg_type type,
490 const char *string,
491 unsigned int *len)
492 {
493 struct iovec iovec;
495 iovec.iov_base = (void *)string;
496 iovec.iov_len = strlen(string) + 1;
497 return xs_talkv(h, t, type, &iovec, 1, len);
498 }
500 static bool xs_bool(char *reply)
501 {
502 if (!reply)
503 return false;
504 free(reply);
505 return true;
506 }
508 char **xs_directory(struct xs_handle *h, xs_transaction_t t,
509 const char *path, unsigned int *num)
510 {
511 char *strings, *p, **ret;
512 unsigned int len;
514 strings = xs_single(h, t, XS_DIRECTORY, path, &len);
515 if (!strings)
516 return NULL;
518 /* Count the strings. */
519 *num = xs_count_strings(strings, len);
521 /* Transfer to one big alloc for easy freeing. */
522 ret = malloc(*num * sizeof(char *) + len);
523 if (!ret) {
524 free_no_errno(strings);
525 return NULL;
526 }
527 memcpy(&ret[*num], strings, len);
528 free_no_errno(strings);
530 strings = (char *)&ret[*num];
531 for (p = strings, *num = 0; p < strings + len; p += strlen(p) + 1)
532 ret[(*num)++] = p;
533 return ret;
534 }
536 /* Get the value of a single file, nul terminated.
537 * Returns a malloced value: call free() on it after use.
538 * len indicates length in bytes, not including the nul.
539 */
540 void *xs_read(struct xs_handle *h, xs_transaction_t t,
541 const char *path, unsigned int *len)
542 {
543 return xs_single(h, t, XS_READ, path, len);
544 }
546 /* Write the value of a single file.
547 * Returns false on failure.
548 */
549 bool xs_write(struct xs_handle *h, xs_transaction_t t,
550 const char *path, const void *data, unsigned int len)
551 {
552 struct iovec iovec[2];
554 iovec[0].iov_base = (void *)path;
555 iovec[0].iov_len = strlen(path) + 1;
556 iovec[1].iov_base = (void *)data;
557 iovec[1].iov_len = len;
559 return xs_bool(xs_talkv(h, t, XS_WRITE, iovec,
560 ARRAY_SIZE(iovec), NULL));
561 }
563 /* Create a new directory.
564 * Returns false on failure, or success if it already exists.
565 */
566 bool xs_mkdir(struct xs_handle *h, xs_transaction_t t,
567 const char *path)
568 {
569 return xs_bool(xs_single(h, t, XS_MKDIR, path, NULL));
570 }
572 /* Destroy a file or directory (directories must be empty).
573 * Returns false on failure, or success if it doesn't exist.
574 */
575 bool xs_rm(struct xs_handle *h, xs_transaction_t t,
576 const char *path)
577 {
578 return xs_bool(xs_single(h, t, XS_RM, path, NULL));
579 }
581 /* Get permissions of node (first element is owner).
582 * Returns malloced array, or NULL: call free() after use.
583 */
584 struct xs_permissions *xs_get_permissions(struct xs_handle *h,
585 xs_transaction_t t,
586 const char *path, unsigned int *num)
587 {
588 char *strings;
589 unsigned int len;
590 struct xs_permissions *ret;
592 strings = xs_single(h, t, XS_GET_PERMS, path, &len);
593 if (!strings)
594 return NULL;
596 /* Count the strings: each one perms then domid. */
597 *num = xs_count_strings(strings, len);
599 /* Transfer to one big alloc for easy freeing. */
600 ret = malloc(*num * sizeof(struct xs_permissions));
601 if (!ret) {
602 free_no_errno(strings);
603 return NULL;
604 }
606 if (!xs_strings_to_perms(ret, *num, strings)) {
607 free_no_errno(ret);
608 ret = NULL;
609 }
611 free(strings);
612 return ret;
613 }
615 /* Set permissions of node (must be owner).
616 * Returns false on failure.
617 */
618 bool xs_set_permissions(struct xs_handle *h,
619 xs_transaction_t t,
620 const char *path,
621 struct xs_permissions *perms,
622 unsigned int num_perms)
623 {
624 unsigned int i;
625 struct iovec iov[1+num_perms];
627 iov[0].iov_base = (void *)path;
628 iov[0].iov_len = strlen(path) + 1;
630 for (i = 0; i < num_perms; i++) {
631 char buffer[MAX_STRLEN(unsigned int)+1];
633 if (!xs_perm_to_string(&perms[i], buffer, sizeof(buffer)))
634 goto unwind;
636 iov[i+1].iov_base = strdup(buffer);
637 iov[i+1].iov_len = strlen(buffer) + 1;
638 if (!iov[i+1].iov_base)
639 goto unwind;
640 }
642 if (!xs_bool(xs_talkv(h, t, XS_SET_PERMS, iov, 1+num_perms, NULL)))
643 goto unwind;
644 for (i = 0; i < num_perms; i++)
645 free(iov[i+1].iov_base);
646 return true;
648 unwind:
649 num_perms = i;
650 for (i = 0; i < num_perms; i++)
651 free_no_errno(iov[i+1].iov_base);
652 return false;
653 }
655 bool xs_restrict(struct xs_handle *h, unsigned domid)
656 {
657 char buf[16];
659 sprintf(buf, "%d", domid);
660 return xs_bool(xs_single(h, XBT_NULL, XS_RESTRICT, buf, NULL));
661 }
663 /* Watch a node for changes (poll on fd to detect, or call read_watch()).
664 * When the node (or any child) changes, fd will become readable.
665 * Token is returned when watch is read, to allow matching.
666 * Returns false on failure.
667 */
668 bool xs_watch(struct xs_handle *h, const char *path, const char *token)
669 {
670 struct iovec iov[2];
672 #ifdef USE_PTHREAD
673 /* We dynamically create a reader thread on demand. */
674 mutex_lock(&h->request_mutex);
675 if (!h->read_thr_exists) {
676 if (pthread_create(&h->read_thr, NULL, read_thread, h) != 0) {
677 mutex_unlock(&h->request_mutex);
678 return false;
679 }
680 h->read_thr_exists = 1;
681 }
682 mutex_unlock(&h->request_mutex);
683 #endif
685 iov[0].iov_base = (void *)path;
686 iov[0].iov_len = strlen(path) + 1;
687 iov[1].iov_base = (void *)token;
688 iov[1].iov_len = strlen(token) + 1;
690 return xs_bool(xs_talkv(h, XBT_NULL, XS_WATCH, iov,
691 ARRAY_SIZE(iov), NULL));
692 }
694 /* Find out what node change was on (will block if nothing pending).
695 * Returns array of two pointers: path and token, or NULL.
696 * Call free() after use.
697 */
698 char **xs_read_watch(struct xs_handle *h, unsigned int *num)
699 {
700 struct xs_stored_msg *msg;
701 char **ret, *strings, c = 0;
702 unsigned int num_strings, i;
704 mutex_lock(&h->watch_mutex);
706 #ifdef USE_PTHREAD
707 /* Wait on the condition variable for a watch to fire.
708 * If the reader thread doesn't exist yet, then that's because
709 * we haven't called xs_watch. Presumably the application
710 * will do so later; in the meantime we just block.
711 */
712 while (list_empty(&h->watch_list) && h->fd != -1)
713 condvar_wait(&h->watch_condvar, &h->watch_mutex);
714 #else /* !defined(USE_PTHREAD) */
715 /* Read from comms channel ourselves if there are no threads
716 * and therefore no reader thread. */
718 assert(!read_thread_exists(h)); /* not threadsafe but worth a check */
719 if ((read_message(h) == -1))
720 return NULL;
722 #endif /* !defined(USE_PTHREAD) */
724 if (list_empty(&h->watch_list)) {
725 mutex_unlock(&h->watch_mutex);
726 errno = EINVAL;
727 return NULL;
728 }
729 msg = list_top(&h->watch_list, struct xs_stored_msg, list);
730 list_del(&msg->list);
732 /* Clear the pipe token if there are no more pending watches. */
733 if (list_empty(&h->watch_list) && (h->watch_pipe[0] != -1))
734 while (read(h->watch_pipe[0], &c, 1) != 1)
735 continue;
737 mutex_unlock(&h->watch_mutex);
739 assert(msg->hdr.type == XS_WATCH_EVENT);
741 strings = msg->body;
742 num_strings = xs_count_strings(strings, msg->hdr.len);
744 ret = malloc(sizeof(char*) * num_strings + msg->hdr.len);
745 if (!ret) {
746 free_no_errno(strings);
747 free_no_errno(msg);
748 return NULL;
749 }
751 ret[0] = (char *)(ret + num_strings);
752 memcpy(ret[0], strings, msg->hdr.len);
754 free(strings);
755 free(msg);
757 for (i = 1; i < num_strings; i++)
758 ret[i] = ret[i - 1] + strlen(ret[i - 1]) + 1;
760 *num = num_strings;
762 return ret;
763 }
765 /* Remove a watch on a node.
766 * Returns false on failure (no watch on that node).
767 */
768 bool xs_unwatch(struct xs_handle *h, const char *path, const char *token)
769 {
770 struct iovec iov[2];
772 iov[0].iov_base = (char *)path;
773 iov[0].iov_len = strlen(path) + 1;
774 iov[1].iov_base = (char *)token;
775 iov[1].iov_len = strlen(token) + 1;
777 return xs_bool(xs_talkv(h, XBT_NULL, XS_UNWATCH, iov,
778 ARRAY_SIZE(iov), NULL));
779 }
781 /* Start a transaction: changes by others will not be seen during this
782 * transaction, and changes will not be visible to others until end.
783 * Returns XBT_NULL on failure.
784 */
785 xs_transaction_t xs_transaction_start(struct xs_handle *h)
786 {
787 char *id_str;
788 xs_transaction_t id;
790 id_str = xs_single(h, XBT_NULL, XS_TRANSACTION_START, "", NULL);
791 if (id_str == NULL)
792 return XBT_NULL;
794 id = strtoul(id_str, NULL, 0);
795 free(id_str);
797 return id;
798 }
800 /* End a transaction.
801 * If abandon is true, transaction is discarded instead of committed.
802 * Returns false on failure, which indicates an error: transactions will
803 * not fail spuriously.
804 */
805 bool xs_transaction_end(struct xs_handle *h, xs_transaction_t t,
806 bool abort)
807 {
808 char abortstr[2];
810 if (abort)
811 strcpy(abortstr, "F");
812 else
813 strcpy(abortstr, "T");
815 return xs_bool(xs_single(h, t, XS_TRANSACTION_END, abortstr, NULL));
816 }
818 /* Introduce a new domain.
819 * This tells the store daemon about a shared memory page and event channel
820 * associated with a domain: the domain uses these to communicate.
821 */
822 bool xs_introduce_domain(struct xs_handle *h,
823 unsigned int domid, unsigned long mfn,
824 unsigned int eventchn)
825 {
826 char domid_str[MAX_STRLEN(domid)];
827 char mfn_str[MAX_STRLEN(mfn)];
828 char eventchn_str[MAX_STRLEN(eventchn)];
829 struct iovec iov[3];
831 snprintf(domid_str, sizeof(domid_str), "%u", domid);
832 snprintf(mfn_str, sizeof(mfn_str), "%lu", mfn);
833 snprintf(eventchn_str, sizeof(eventchn_str), "%u", eventchn);
835 iov[0].iov_base = domid_str;
836 iov[0].iov_len = strlen(domid_str) + 1;
837 iov[1].iov_base = mfn_str;
838 iov[1].iov_len = strlen(mfn_str) + 1;
839 iov[2].iov_base = eventchn_str;
840 iov[2].iov_len = strlen(eventchn_str) + 1;
842 return xs_bool(xs_talkv(h, XBT_NULL, XS_INTRODUCE, iov,
843 ARRAY_SIZE(iov), NULL));
844 }
846 bool xs_set_target(struct xs_handle *h,
847 unsigned int domid, unsigned int target)
848 {
849 char domid_str[MAX_STRLEN(domid)];
850 char target_str[MAX_STRLEN(target)];
851 struct iovec iov[2];
853 snprintf(domid_str, sizeof(domid_str), "%u", domid);
854 snprintf(target_str, sizeof(target_str), "%u", target);
856 iov[0].iov_base = domid_str;
857 iov[0].iov_len = strlen(domid_str) + 1;
858 iov[1].iov_base = target_str;
859 iov[1].iov_len = strlen(target_str) + 1;
861 return xs_bool(xs_talkv(h, XBT_NULL, XS_SET_TARGET, iov,
862 ARRAY_SIZE(iov), NULL));
863 }
865 static void * single_with_domid(struct xs_handle *h,
866 enum xsd_sockmsg_type type,
867 unsigned int domid)
868 {
869 char domid_str[MAX_STRLEN(domid)];
871 snprintf(domid_str, sizeof(domid_str), "%u", domid);
873 return xs_single(h, XBT_NULL, type, domid_str, NULL);
874 }
876 bool xs_release_domain(struct xs_handle *h, unsigned int domid)
877 {
878 return xs_bool(single_with_domid(h, XS_RELEASE, domid));
879 }
881 /* clear the shutdown bit for the given domain */
882 bool xs_resume_domain(struct xs_handle *h, unsigned int domid)
883 {
884 return xs_bool(single_with_domid(h, XS_RESUME, domid));
885 }
887 char *xs_get_domain_path(struct xs_handle *h, unsigned int domid)
888 {
889 char domid_str[MAX_STRLEN(domid)];
891 snprintf(domid_str, sizeof(domid_str), "%u", domid);
893 return xs_single(h, XBT_NULL, XS_GET_DOMAIN_PATH, domid_str, NULL);
894 }
896 bool xs_is_domain_introduced(struct xs_handle *h, unsigned int domid)
897 {
898 char *domain = single_with_domid(h, XS_IS_DOMAIN_INTRODUCED, domid);
899 int rc = strcmp("F", domain);
901 free(domain);
902 return rc;
903 }
905 int xs_suspend_evtchn_port(int domid)
906 {
907 char path[128];
908 char *portstr;
909 int port;
910 unsigned int plen;
911 struct xs_handle *xs;
913 xs = xs_daemon_open();
914 if (!xs)
915 return -1;
917 sprintf(path, "/local/domain/%d/device/suspend/event-channel", domid);
918 portstr = xs_read(xs, XBT_NULL, path, &plen);
919 xs_daemon_close(xs);
921 if (!portstr || !plen)
922 return -1;
924 port = atoi(portstr);
925 free(portstr);
927 return port;
928 }
930 /* Only useful for DEBUG versions */
931 char *xs_debug_command(struct xs_handle *h, const char *cmd,
932 void *data, unsigned int len)
933 {
934 struct iovec iov[2];
936 iov[0].iov_base = (void *)cmd;
937 iov[0].iov_len = strlen(cmd) + 1;
938 iov[1].iov_base = data;
939 iov[1].iov_len = len;
941 return xs_talkv(h, XBT_NULL, XS_DEBUG, iov,
942 ARRAY_SIZE(iov), NULL);
943 }
945 static int read_message(struct xs_handle *h)
946 {
947 /* IMPORTANT: It is forbidden to call this function without
948 * acquiring the request lock and checking that h->read_thr_exists
949 * is false. See "Lock discipline" in struct xs_handle, above. */
951 struct xs_stored_msg *msg = NULL;
952 char *body = NULL;
953 int saved_errno = 0;
954 int ret = -1;
956 /* Allocate message structure and read the message header. */
957 msg = malloc(sizeof(*msg));
958 if (msg == NULL)
959 goto error;
960 cleanup_push(free, msg);
961 if (!read_all(h->fd, &msg->hdr, sizeof(msg->hdr))) { /* Cancellation point */
962 saved_errno = errno;
963 goto error_freemsg;
964 }
966 /* Allocate and read the message body. */
967 body = msg->body = malloc(msg->hdr.len + 1);
968 if (body == NULL)
969 goto error_freemsg;
970 cleanup_push(free, body);
971 if (!read_all(h->fd, body, msg->hdr.len)) { /* Cancellation point */
972 saved_errno = errno;
973 goto error_freebody;
974 }
976 body[msg->hdr.len] = '\0';
978 if (msg->hdr.type == XS_WATCH_EVENT) {
979 mutex_lock(&h->watch_mutex);
980 cleanup_push(pthread_mutex_unlock, &h->watch_mutex);
982 /* Kick users out of their select() loop. */
983 if (list_empty(&h->watch_list) &&
984 (h->watch_pipe[1] != -1))
985 while (write(h->watch_pipe[1], body, 1) != 1) /* Cancellation point */
986 continue;
988 list_add_tail(&msg->list, &h->watch_list);
990 condvar_signal(&h->watch_condvar);
992 cleanup_pop(1);
993 } else {
994 mutex_lock(&h->reply_mutex);
996 /* There should only ever be one response pending! */
997 if (!list_empty(&h->reply_list)) {
998 mutex_unlock(&h->reply_mutex);
999 goto error_freebody;
1002 list_add_tail(&msg->list, &h->reply_list);
1003 condvar_signal(&h->reply_condvar);
1005 mutex_unlock(&h->reply_mutex);
1008 ret = 0;
1010 error_freebody:
1011 cleanup_pop(ret == -1);
1012 error_freemsg:
1013 cleanup_pop(ret == -1);
1014 error:
1015 errno = saved_errno;
1017 return ret;
1020 #ifdef USE_PTHREAD
1021 static void *read_thread(void *arg)
1023 struct xs_handle *h = arg;
1024 int fd;
1026 while (read_message(h) != -1)
1027 continue;
1029 /* An error return from read_message leaves the socket in an undefined
1030 * state; we might have read only the header and not the message after
1031 * it, or (more commonly) the other end has closed the connection.
1032 * Since further communication is unsafe, close the socket.
1033 */
1034 fd = h->fd;
1035 h->fd = -1;
1036 close(fd);
1038 /* wake up all waiters */
1039 pthread_mutex_lock(&h->reply_mutex);
1040 pthread_cond_broadcast(&h->reply_condvar);
1041 pthread_mutex_unlock(&h->reply_mutex);
1043 pthread_mutex_lock(&h->watch_mutex);
1044 pthread_cond_broadcast(&h->watch_condvar);
1045 pthread_mutex_unlock(&h->watch_mutex);
1047 return NULL;
1049 #endif
1051 /*
1052 * Local variables:
1053 * c-file-style: "linux"
1054 * indent-tabs-mode: t
1055 * c-indent-level: 8
1056 * c-basic-offset: 8
1057 * tab-width: 8
1058 * End:
1059 */