source: trunk/packages/xen-3.1/xen-3.1/tools/blktap/lib/xs_api.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 7.6 KB
Line 
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 */
34
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"
50
51#if 0
52#define DPRINTF(_f, _a...) printf ( _f , ## _a )
53#else
54#define DPRINTF(_f, _a...) ((void)0)
55#endif
56
57static LIST_HEAD(watches);
58#define BASE_DEV_VAL 2048
59
60int 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;
68
69again:
70        if ( (xth = xs_transaction_start(xs)) == XBT_NULL) {
71                DPRINTF("unable to start xs trasanction\n");
72                ret = ENOMEM;
73                return ret;
74        }
75       
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;
81               
82                if (asprintf(&path, "%s/%s", dir, name) == -1)
83                {
84                        printf("allocation error in xs_gather!\n");
85                        ret = ENOMEM;
86                        break;
87                }
88               
89                p = xs_read(xs, xth, path, &len);
90               
91               
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);
105
106        if (!xs_transaction_end(xs, xth, ret)) {
107                if (ret == 0 && errno == EAGAIN)
108                        goto again;
109                else
110                        ret = errno;
111        }
112
113        return ret;
114}
115
116
117/* Single printf and write: returns -errno or 0. */
118int 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;
124       
125        va_start(ap, fmt);
126        ret = vasprintf(&buf, fmt, ap);
127        va_end(ap);
128       
129        asprintf(&path, "%s/%s", dir, node);
130       
131        if ((path == NULL) || (buf == NULL))
132                return 0;
133
134        ret = xs_write(h, XBT_NULL, path, buf, strlen(buf)+1);
135       
136        free(buf);
137        free(path);
138       
139        return ret;
140}
141
142
143int xs_exists(struct xs_handle *h, const char *path)
144{
145        char **d;
146        unsigned int num;
147        xs_transaction_t xth;
148       
149        if ( (xth = xs_transaction_start(h)) == XBT_NULL) {
150                printf("unable to start xs trasanction\n");
151                return 0;
152        }       
153       
154        d = xs_directory(h, xth, path, &num);
155        xs_transaction_end(h, xth, 0);
156        if (d == NULL)
157                return 0;
158        free(d);
159        return 1;
160}
161
162
163
164/**
165 * This assumes that the domain name we are looking for is unique.
166 * Name parameter Domain-0
167 */
168char *get_dom_domid(struct xs_handle *h)
169{
170        char **e, *val, *domid = NULL;
171        unsigned int num, len;
172        int i;
173        char *path;
174        xs_transaction_t xth;
175       
176        if ( (xth = xs_transaction_start(h)) == XBT_NULL) {
177                warn("unable to start xs trasanction\n");
178                return NULL;
179        }
180       
181        e = xs_directory(h, xth, "/local/domain", &num);
182        if (e == NULL)
183                return NULL;
184
185        for (i = 0; (i < num) && (domid == NULL); i++) {
186                asprintf(&path, "/local/domain/%s/name", e[i]);
187                val = xs_read(h, xth, path, &len);
188                free(path);
189                if (val == NULL)
190                        continue;
191               
192                if (strcmp(val, DOMNAME) == 0) {
193                        /* match! */
194                        asprintf(&path, "/local/domain/%s/domid", e[i]);
195                        domid = xs_read(h, xth, path, &len);
196                        free(path);
197                }
198                free(val);
199        }
200        xs_transaction_end(h, xth, 0);
201       
202        free(e);
203        return domid;
204}
205
206int convert_dev_name_to_num(char *name) {
207        char *p_sd, *p_hd, *p_xvd, *p_plx, *p, *alpha,*ptr;
208        int majors[10] = {3,22,33,34,56,57,88,89,90,91};
209        int maj,i,ret = 0;
210
211        asprintf(&p_sd,"/dev/sd");
212        asprintf(&p_hd,"/dev/hd");
213        asprintf(&p_xvd,"/dev/xvd");
214        asprintf(&p_plx,"plx");
215        asprintf(&alpha,"abcdefghijklmnop");
216       
217
218        if (strstr(name, p_sd) != NULL) {
219                p = name + strlen(p_sd);
220                for(i = 0, ptr = alpha; i < strlen(alpha); i++) {
221                        if(*ptr == *p)
222                                break;
223                        *ptr++;
224                }
225                *p++;
226                ret = BASE_DEV_VAL + (16*i) + atoi(p);
227        } else if (strstr(name, p_hd) != NULL) {
228                p = name + strlen(p_hd);
229                for (i = 0, ptr = alpha; i < strlen(alpha); i++) {
230                        if(*ptr == *p) break;
231                        *ptr++;
232                }
233                *p++;
234                ret = (majors[i/2]*256) + atoi(p);
235
236        } else if (strstr(name, p_xvd) != NULL) {
237                p = name + strlen(p_xvd);
238                for(i = 0, ptr = alpha; i < strlen(alpha); i++) {
239                        if(*ptr == *p) break;
240                        *ptr++;
241                }
242                *p++;
243                ret = (202*256) + (16*i) + atoi(p);
244
245        } else if (strstr(name, p_plx) != NULL) {
246                p = name + strlen(p_plx);
247                ret = atoi(p);
248
249        } else {
250                DPRINTF("Unknown device type, setting to default.\n");
251                ret = BASE_DEV_VAL;
252        }
253
254        free(p_sd);
255        free(p_hd);
256        free(p_xvd);
257        free(p_plx);
258        free(alpha);
259
260        return ret;
261}
262
263/**
264 * A little paranoia: we don't just trust token.
265 */
266static struct xenbus_watch *find_watch(const char *token)
267{
268        struct xenbus_watch *i, *cmp;
269       
270        cmp = (void *)strtoul(token, NULL, 16);
271       
272        list_for_each_entry(i, &watches, list)
273                if (i == cmp)
274                        return i;
275        return NULL;
276}
277
278/**
279 * Register callback to watch this node.
280 * like xs_watch, return 0 on failure
281 */
282int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
283{
284        /* Pointer in ascii is the token. */
285        char token[sizeof(watch) * 2 + 1];
286
287        sprintf(token, "%lX", (long)watch);
288        if (find_watch(token)) {
289                DPRINTF("watch collision!\n");
290                return -EINVAL;
291        }
292       
293        if (!xs_watch(h, watch->node, token)) {
294                DPRINTF("unable to set watch!\n");
295                return -EINVAL;
296        }
297
298        list_add(&watch->list, &watches);
299
300        return 0;
301}
302
303int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch)
304{
305        char token[sizeof(watch) * 2 + 1];
306       
307        sprintf(token, "%lX", (long)watch);
308        if (!find_watch(token)) {
309                DPRINTF("no such watch!\n");
310                return -EINVAL;
311        }
312
313        if (!xs_unwatch(h, watch->node, token))
314                DPRINTF("XENBUS Failed to release watch %s\n",
315                        watch->node);
316
317        list_del(&watch->list);
318       
319        return 0;
320}
321
322/**
323 * Re-register callbacks to all watches.
324 */
325void reregister_xenbus_watches(struct xs_handle *h)
326{
327        struct xenbus_watch *watch;
328        char token[sizeof(watch) * 2 + 1];
329       
330        list_for_each_entry(watch, &watches, list) {
331                sprintf(token, "%lX", (long)watch);
332                xs_watch(h, watch->node, token);
333        }
334}
335
336/**
337 * based on watch_thread()
338 */
339int xs_fire_next_watch(struct xs_handle *h)
340{
341        char **res;
342        char *token;
343        char *node = NULL;
344        struct xenbus_watch *w;
345        int er;
346        unsigned int num;
347       
348        res = xs_read_watch(h, &num);
349        if (res == NULL) 
350                return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */
351       
352        node  = res[XS_WATCH_PATH];
353        token = res[XS_WATCH_TOKEN];
354
355        w = find_watch(token);
356        if (w) 
357                w->callback(h, w, node);
358
359        free(res);
360
361        return 1;
362}
Note: See TracBrowser for help on using the repository browser.