debuggers.hg

view tools/blktap/lib/xs_api.c @ 16564:1b863ae2bf1e

blktap: cleanups for *BSD.
Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Dec 05 09:59:23 2007 +0000 (2007-12-05)
parents b1da8762f853
children 80365bc6df42
line source
1 /*
2 * xs_api.c
3 *
4 * blocktap interface functions to xenstore
5 *
6 * (c) 2005 Andrew Warfield and Julian Chesterfield
7 *
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation; or, when distributed
12 * separately from the Linux kernel or incorporated into other
13 * software packages, subject to the following license:
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining a copy
16 * of this source file (the "Software"), to deal in the Software without
17 * restriction, including without limitation the rights to use, copy, modify,
18 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
19 * and to permit persons to whom the Software is furnished to do so, subject to
20 * the following conditions:
21 *
22 * The above copyright notice and this permission notice shall be included in
23 * all copies or substantial portions of the Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
28 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
29 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
30 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
31 * IN THE SOFTWARE.
32 *
33 */
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <err.h>
39 #include <stdarg.h>
40 #include <errno.h>
41 #include <xs.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <fcntl.h>
45 #include <poll.h>
46 #include "blktaplib.h"
47 #include "list.h"
48 #include "xs_api.h"
50 #if 0
51 #define DPRINTF(_f, _a...) printf ( _f , ## _a )
52 #else
53 #define DPRINTF(_f, _a...) ((void)0)
54 #endif
56 static LIST_HEAD(watches);
57 #define BASE_DEV_VAL 2048
59 int xs_gather(struct xs_handle *xs, const char *dir, ...)
60 {
61 va_list ap;
62 const char *name;
63 char *path, **e;
64 int ret = 0, num,i;
65 unsigned int len;
66 xs_transaction_t xth;
68 again:
69 if ( (xth = xs_transaction_start(xs)) == XBT_NULL) {
70 DPRINTF("unable to start xs trasanction\n");
71 ret = ENOMEM;
72 return ret;
73 }
75 va_start(ap, dir);
76 while ( (ret == 0) && (name = va_arg(ap, char *)) != NULL) {
77 const char *fmt = va_arg(ap, char *);
78 void *result = va_arg(ap, void *);
79 char *p;
81 if (asprintf(&path, "%s/%s", dir, name) == -1)
82 {
83 printf("allocation error in xs_gather!\n");
84 ret = ENOMEM;
85 break;
86 }
88 p = xs_read(xs, xth, path, &len);
91 free(path);
92 if (p == NULL) {
93 ret = ENOENT;
94 break;
95 }
96 if (fmt) {
97 if (sscanf(p, fmt, result) == 0)
98 ret = EINVAL;
99 free(p);
100 } else
101 *(char **)result = p;
102 }
103 va_end(ap);
105 if (!xs_transaction_end(xs, xth, ret)) {
106 if (ret == 0 && errno == EAGAIN)
107 goto again;
108 else
109 ret = errno;
110 }
112 return ret;
113 }
116 /* Single printf and write: returns -errno or 0. */
117 int xs_printf(struct xs_handle *h, const char *dir, const char *node,
118 const char *fmt, ...)
119 {
120 char *buf, *path;
121 va_list ap;
122 int ret;
124 va_start(ap, fmt);
125 ret = vasprintf(&buf, fmt, ap);
126 va_end(ap);
128 if (ret == -1)
129 return ENOMEM;
130 if (asprintf(&path, "%s/%s", dir, node) == -1) {
131 free(buf);
132 return ENOMEM;
133 }
135 ret = xs_write(h, XBT_NULL, path, buf, strlen(buf)+1);
137 free(buf);
138 free(path);
140 return ret;
141 }
144 int xs_exists(struct xs_handle *h, const char *path)
145 {
146 char **d;
147 unsigned int num;
148 xs_transaction_t xth;
150 if ( (xth = xs_transaction_start(h)) == XBT_NULL) {
151 printf("unable to start xs trasanction\n");
152 return 0;
153 }
155 d = xs_directory(h, xth, path, &num);
156 xs_transaction_end(h, xth, 0);
157 if (d == NULL)
158 return 0;
159 free(d);
160 return 1;
161 }
165 /**
166 * This assumes that the domain name we are looking for is unique.
167 * Name parameter Domain-0
168 */
169 char *get_dom_domid(struct xs_handle *h)
170 {
171 char **e, *val, *domid = NULL;
172 unsigned int num, len;
173 int i;
174 char *path;
175 xs_transaction_t xth;
177 if ( (xth = xs_transaction_start(h)) == XBT_NULL) {
178 warn("unable to start xs trasanction\n");
179 return NULL;
180 }
182 e = xs_directory(h, xth, "/local/domain", &num);
183 if (e == NULL)
184 goto done;
186 for (i = 0; (i < num) && (domid == NULL); i++) {
187 if (asprintf(&path, "/local/domain/%s/name", e[i]) == -1)
188 break;
189 val = xs_read(h, xth, path, &len);
190 free(path);
191 if (val == NULL)
192 continue;
194 if (strcmp(val, DOMNAME) == 0) {
195 /* match! */
196 if (asprintf(&path, "/local/domain/%s/domid", e[i]) == -1) {
197 free(val);
198 break;
199 }
200 domid = xs_read(h, xth, path, &len);
201 free(path);
202 }
203 free(val);
204 }
205 done:
206 xs_transaction_end(h, xth, 0);
207 if (e)
208 free(e);
209 return domid;
210 }
212 int convert_dev_name_to_num(char *name) {
213 char *p, *ptr;
214 int majors[10] = {3,22,33,34,56,57,88,89,90,91};
215 int maj,i,ret = 0;
216 char *p_sd = "/dev/sd";
217 char *p_hd = "/dev/hd";
218 char *p_xvd = "/dev/xvd";
219 char *p_plx = "plx";
220 char *alpha = "abcdefghijklmnop";
222 if (strstr(name, p_sd) != NULL) {
223 p = name + strlen(p_sd);
224 for(i = 0, ptr = alpha; i < strlen(alpha); i++) {
225 if(*ptr == *p)
226 break;
227 *ptr++;
228 }
229 *p++;
230 ret = BASE_DEV_VAL + (16*i) + atoi(p);
231 } else if (strstr(name, p_hd) != NULL) {
232 p = name + strlen(p_hd);
233 for (i = 0, ptr = alpha; i < strlen(alpha); i++) {
234 if(*ptr == *p) break;
235 *ptr++;
236 }
237 *p++;
238 ret = (majors[i/2]*256) + atoi(p);
240 } else if (strstr(name, p_xvd) != NULL) {
241 p = name + strlen(p_xvd);
242 for(i = 0, ptr = alpha; i < strlen(alpha); i++) {
243 if(*ptr == *p) break;
244 *ptr++;
245 }
246 *p++;
247 ret = (202*256) + (16*i) + atoi(p);
249 } else if (strstr(name, p_plx) != NULL) {
250 p = name + strlen(p_plx);
251 ret = atoi(p);
253 } else {
254 DPRINTF("Unknown device type, setting to default.\n");
255 ret = BASE_DEV_VAL;
256 }
258 return ret;
259 }
261 /**
262 * A little paranoia: we don't just trust token.
263 */
264 static struct xenbus_watch *find_watch(const char *token)
265 {
266 struct xenbus_watch *i, *cmp;
268 cmp = (void *)strtoul(token, NULL, 16);
270 list_for_each_entry(i, &watches, list)
271 if (i == cmp)
272 return i;
273 return NULL;
274 }
276 /**
277 * Register callback to watch this node.
278 * like xs_watch, return 0 on failure
279 */
280 int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
281 {
282 /* Pointer in ascii is the token. */
283 char token[sizeof(watch) * 2 + 1];
285 snprintf(token, sizeof(token), "%lX", (long)watch);
286 if (find_watch(token)) {
287 DPRINTF("watch collision!\n");
288 return -EINVAL;
289 }
291 if (!xs_watch(h, watch->node, token)) {
292 DPRINTF("unable to set watch!\n");
293 return -EINVAL;
294 }
296 list_add(&watch->list, &watches);
298 return 0;
299 }
301 int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
302 {
303 char token[sizeof(watch) * 2 + 1];
305 snprintf(token, sizeof(token), "%lX", (long)watch);
306 if (!find_watch(token)) {
307 DPRINTF("no such watch!\n");
308 return -EINVAL;
309 }
311 if (!xs_unwatch(h, watch->node, token))
312 DPRINTF("XENBUS Failed to release watch %s\n",
313 watch->node);
315 list_del(&watch->list);
317 return 0;
318 }
320 /**
321 * Re-register callbacks to all watches.
322 */
323 void reregister_xenbus_watches(struct xs_handle *h)
324 {
325 struct xenbus_watch *watch;
326 char token[sizeof(watch) * 2 + 1];
328 list_for_each_entry(watch, &watches, list) {
329 snprintf(token, sizeof(token), "%lX", (long)watch);
330 xs_watch(h, watch->node, token);
331 }
332 }
334 /**
335 * based on watch_thread()
336 */
337 int xs_fire_next_watch(struct xs_handle *h)
338 {
339 char **res;
340 char *token;
341 char *node = NULL;
342 struct xenbus_watch *w;
343 int er;
344 unsigned int num;
346 res = xs_read_watch(h, &num);
347 if (res == NULL)
348 return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */
350 node = res[XS_WATCH_PATH];
351 token = res[XS_WATCH_TOKEN];
353 w = find_watch(token);
354 if (w)
355 w->callback(h, w, node);
357 free(res);
359 return 1;
360 }