ia64/xen-unstable

view tools/blktap/lib/xs_api.c @ 15783:c93e2a822d6f

[xen, xencomm] xencomm multiple page support
Current implementation doesn't allow struct xencomm_desc::address
array to be more than single page. On IA64 it causes 64GB+ domain
creation failure. This patch generalizes xencomm to allow multipage

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
author kfraser@localhost.localdomain
date Tue Aug 28 15:32:27 2007 +0100 (2007-08-28)
parents b515e66234e8
children b1da8762f853
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 <printf.h>
38 #include <string.h>
39 #include <err.h>
40 #include <stdarg.h>
41 #include <errno.h>
42 #include <xs.h>
43 #include <sys/types.h>
44 #include <sys/stat.h>
45 #include <fcntl.h>
46 #include <poll.h>
47 #include "blktaplib.h"
48 #include "list.h"
49 #include "xs_api.h"
51 #if 0
52 #define DPRINTF(_f, _a...) printf ( _f , ## _a )
53 #else
54 #define DPRINTF(_f, _a...) ((void)0)
55 #endif
57 static LIST_HEAD(watches);
58 #define BASE_DEV_VAL 2048
60 int xs_gather(struct xs_handle *xs, const char *dir, ...)
61 {
62 va_list ap;
63 const char *name;
64 char *path, **e;
65 int ret = 0, num,i;
66 unsigned int len;
67 xs_transaction_t xth;
69 again:
70 if ( (xth = xs_transaction_start(xs)) == XBT_NULL) {
71 DPRINTF("unable to start xs trasanction\n");
72 ret = ENOMEM;
73 return ret;
74 }
76 va_start(ap, dir);
77 while ( (ret == 0) && (name = va_arg(ap, char *)) != NULL) {
78 const char *fmt = va_arg(ap, char *);
79 void *result = va_arg(ap, void *);
80 char *p;
82 if (asprintf(&path, "%s/%s", dir, name) == -1)
83 {
84 printf("allocation error in xs_gather!\n");
85 ret = ENOMEM;
86 break;
87 }
89 p = xs_read(xs, xth, path, &len);
92 free(path);
93 if (p == NULL) {
94 ret = ENOENT;
95 break;
96 }
97 if (fmt) {
98 if (sscanf(p, fmt, result) == 0)
99 ret = EINVAL;
100 free(p);
101 } else
102 *(char **)result = p;
103 }
104 va_end(ap);
106 if (!xs_transaction_end(xs, xth, ret)) {
107 if (ret == 0 && errno == EAGAIN)
108 goto again;
109 else
110 ret = errno;
111 }
113 return ret;
114 }
117 /* Single printf and write: returns -errno or 0. */
118 int xs_printf(struct xs_handle *h, const char *dir, const char *node,
119 const char *fmt, ...)
120 {
121 char *buf, *path;
122 va_list ap;
123 int ret;
125 va_start(ap, fmt);
126 ret = vasprintf(&buf, fmt, ap);
127 va_end(ap);
129 if (ret == -1)
130 return ENOMEM;
131 if (asprintf(&path, "%s/%s", dir, node) == -1) {
132 free(buf);
133 return ENOMEM;
134 }
136 ret = xs_write(h, XBT_NULL, path, buf, strlen(buf)+1);
138 free(buf);
139 free(path);
141 return ret;
142 }
145 int xs_exists(struct xs_handle *h, const char *path)
146 {
147 char **d;
148 unsigned int num;
149 xs_transaction_t xth;
151 if ( (xth = xs_transaction_start(h)) == XBT_NULL) {
152 printf("unable to start xs trasanction\n");
153 return 0;
154 }
156 d = xs_directory(h, xth, path, &num);
157 xs_transaction_end(h, xth, 0);
158 if (d == NULL)
159 return 0;
160 free(d);
161 return 1;
162 }
166 /**
167 * This assumes that the domain name we are looking for is unique.
168 * Name parameter Domain-0
169 */
170 char *get_dom_domid(struct xs_handle *h)
171 {
172 char **e, *val, *domid = NULL;
173 unsigned int num, len;
174 int i;
175 char *path;
176 xs_transaction_t xth;
178 if ( (xth = xs_transaction_start(h)) == XBT_NULL) {
179 warn("unable to start xs trasanction\n");
180 return NULL;
181 }
183 e = xs_directory(h, xth, "/local/domain", &num);
184 if (e == NULL)
185 goto done;
187 for (i = 0; (i < num) && (domid == NULL); i++) {
188 if (asprintf(&path, "/local/domain/%s/name", e[i]) == -1)
189 break;
190 val = xs_read(h, xth, path, &len);
191 free(path);
192 if (val == NULL)
193 continue;
195 if (strcmp(val, DOMNAME) == 0) {
196 /* match! */
197 if (asprintf(&path, "/local/domain/%s/domid", e[i]) == -1) {
198 free(val);
199 break;
200 }
201 domid = xs_read(h, xth, path, &len);
202 free(path);
203 }
204 free(val);
205 }
206 done:
207 xs_transaction_end(h, xth, 0);
208 if (e)
209 free(e);
210 return domid;
211 }
213 int convert_dev_name_to_num(char *name) {
214 char *p, *ptr;
215 int majors[10] = {3,22,33,34,56,57,88,89,90,91};
216 int maj,i,ret = 0;
217 char *p_sd = "/dev/sd";
218 char *p_hd = "/dev/hd";
219 char *p_xvd = "/dev/xvd";
220 char *p_plx = "plx";
221 char *alpha = "abcdefghijklmnop";
223 if (strstr(name, p_sd) != NULL) {
224 p = name + strlen(p_sd);
225 for(i = 0, ptr = alpha; i < strlen(alpha); i++) {
226 if(*ptr == *p)
227 break;
228 *ptr++;
229 }
230 *p++;
231 ret = BASE_DEV_VAL + (16*i) + atoi(p);
232 } else if (strstr(name, p_hd) != NULL) {
233 p = name + strlen(p_hd);
234 for (i = 0, ptr = alpha; i < strlen(alpha); i++) {
235 if(*ptr == *p) break;
236 *ptr++;
237 }
238 *p++;
239 ret = (majors[i/2]*256) + atoi(p);
241 } else if (strstr(name, p_xvd) != NULL) {
242 p = name + strlen(p_xvd);
243 for(i = 0, ptr = alpha; i < strlen(alpha); i++) {
244 if(*ptr == *p) break;
245 *ptr++;
246 }
247 *p++;
248 ret = (202*256) + (16*i) + atoi(p);
250 } else if (strstr(name, p_plx) != NULL) {
251 p = name + strlen(p_plx);
252 ret = atoi(p);
254 } else {
255 DPRINTF("Unknown device type, setting to default.\n");
256 ret = BASE_DEV_VAL;
257 }
259 return ret;
260 }
262 /**
263 * A little paranoia: we don't just trust token.
264 */
265 static struct xenbus_watch *find_watch(const char *token)
266 {
267 struct xenbus_watch *i, *cmp;
269 cmp = (void *)strtoul(token, NULL, 16);
271 list_for_each_entry(i, &watches, list)
272 if (i == cmp)
273 return i;
274 return NULL;
275 }
277 /**
278 * Register callback to watch this node.
279 * like xs_watch, return 0 on failure
280 */
281 int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
282 {
283 /* Pointer in ascii is the token. */
284 char token[sizeof(watch) * 2 + 1];
286 sprintf(token, "%lX", (long)watch);
287 if (find_watch(token)) {
288 DPRINTF("watch collision!\n");
289 return -EINVAL;
290 }
292 if (!xs_watch(h, watch->node, token)) {
293 DPRINTF("unable to set watch!\n");
294 return -EINVAL;
295 }
297 list_add(&watch->list, &watches);
299 return 0;
300 }
302 int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
303 {
304 char token[sizeof(watch) * 2 + 1];
306 sprintf(token, "%lX", (long)watch);
307 if (!find_watch(token)) {
308 DPRINTF("no such watch!\n");
309 return -EINVAL;
310 }
312 if (!xs_unwatch(h, watch->node, token))
313 DPRINTF("XENBUS Failed to release watch %s\n",
314 watch->node);
316 list_del(&watch->list);
318 return 0;
319 }
321 /**
322 * Re-register callbacks to all watches.
323 */
324 void reregister_xenbus_watches(struct xs_handle *h)
325 {
326 struct xenbus_watch *watch;
327 char token[sizeof(watch) * 2 + 1];
329 list_for_each_entry(watch, &watches, list) {
330 sprintf(token, "%lX", (long)watch);
331 xs_watch(h, watch->node, token);
332 }
333 }
335 /**
336 * based on watch_thread()
337 */
338 int xs_fire_next_watch(struct xs_handle *h)
339 {
340 char **res;
341 char *token;
342 char *node = NULL;
343 struct xenbus_watch *w;
344 int er;
345 unsigned int num;
347 res = xs_read_watch(h, &num);
348 if (res == NULL)
349 return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */
351 node = res[XS_WATCH_PATH];
352 token = res[XS_WATCH_TOKEN];
354 w = find_watch(token);
355 if (w)
356 w->callback(h, w, node);
358 free(res);
360 return 1;
361 }