direct-io.hg

view tools/ioemu/xenstore.c @ 15471:7ac7f1472414

hvm: Allow blktap to be able to be booted as system volume for PV-on-HVM

When blktap was booting system volume, PV-on-HVM domain was not able
to be started.

The configuration file is specified as follows.
disk = [ 'tap:aio:/xen/test/rhel5ga_full.img,hda,w' ]

The error occurred by the initialization of system volume in qemu-dm.
qemu: could not open hard disk image 'aio:/xen/test/rhel5ga_full.img'

Signed-off-by: Takanori Kasai <kasai.takanori@jp.fujitsu.com>
Signed-off-by: Tomonari Horikoshi <t.horikoshi@jp.fujitsu.com>
Signed-off-by: Tsunehisa Doi <Doi.Tsunehisa@jp.fujitsu.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Jul 06 14:22:59 2007 +0100 (2007-07-06)
parents 6d45351273da
children 538c3d8aa4b1
line source
1 /*
2 * This file is subject to the terms and conditions of the GNU General
3 * Public License. See the file "COPYING" in the main directory of
4 * this archive for more details.
5 *
6 * Copyright (C) 2006 Christian Limpach
7 * Copyright (C) 2006 XenSource Ltd.
8 *
9 */
11 #include "vl.h"
12 #include "block_int.h"
13 #include <unistd.h>
14 #include <sys/ipc.h>
15 #include <sys/shm.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
20 static struct xs_handle *xsh = NULL;
21 static char *media_filename[MAX_DISKS + MAX_SCSI_DISKS];
22 static QEMUTimer *insert_timer = NULL;
24 #define UWAIT_MAX (30*1000000) /* thirty seconds */
25 #define UWAIT (100000) /* 1/10th second */
27 static int pasprintf(char **buf, const char *fmt, ...)
28 {
29 va_list ap;
30 int ret = 0;
32 if (*buf)
33 free(*buf);
34 va_start(ap, fmt);
35 if (vasprintf(buf, fmt, ap) == -1) {
36 buf = NULL;
37 ret = -1;
38 }
39 va_end(ap);
40 return ret;
41 }
43 static void insert_media(void *opaque)
44 {
45 int i;
47 for (i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++) {
48 if (media_filename[i] && bs_table[i]) {
49 do_change(bs_table[i]->device_name, media_filename[i]);
50 free(media_filename[i]);
51 media_filename[i] = NULL;
52 }
53 }
54 }
56 void xenstore_check_new_media_present(int timeout)
57 {
59 if (insert_timer == NULL)
60 insert_timer = qemu_new_timer(rt_clock, insert_media, NULL);
61 qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout);
62 }
64 static void waitForDevice(char *fn)
65 {
66 struct stat sbuf;
67 int status;
68 int uwait = UWAIT_MAX;
70 do {
71 status = stat(fn, &sbuf);
72 if (!status) break;
73 usleep(UWAIT);
74 uwait -= UWAIT;
75 } while (uwait > 0);
77 return;
78 }
80 void xenstore_parse_domain_config(int domid)
81 {
82 char **e = NULL;
83 char *buf = NULL, *path;
84 char *fpath = NULL, *bpath = NULL,
85 *dev = NULL, *params = NULL, *type = NULL;
86 int i, is_scsi;
87 unsigned int len, num, hd_index;
89 for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++)
90 media_filename[i] = NULL;
92 xsh = xs_daemon_open();
93 if (xsh == NULL) {
94 fprintf(logfile, "Could not contact xenstore for domain config\n");
95 return;
96 }
98 path = xs_get_domain_path(xsh, domid);
99 if (path == NULL) {
100 fprintf(logfile, "xs_get_domain_path() error\n");
101 goto out;
102 }
104 if (pasprintf(&buf, "%s/device/vbd", path) == -1)
105 goto out;
107 e = xs_directory(xsh, XBT_NULL, buf, &num);
108 if (e == NULL)
109 goto out;
111 for (i = 0; i < num; i++) {
112 /* read the backend path */
113 if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
114 continue;
115 free(bpath);
116 bpath = xs_read(xsh, XBT_NULL, buf, &len);
117 if (bpath == NULL)
118 continue;
119 /* read the name of the device */
120 if (pasprintf(&buf, "%s/dev", bpath) == -1)
121 continue;
122 free(dev);
123 dev = xs_read(xsh, XBT_NULL, buf, &len);
124 if (dev == NULL)
125 continue;
126 is_scsi = !strncmp(dev, "sd", 2);
127 if ((strncmp(dev, "hd", 2) && !is_scsi) || strlen(dev) != 3 )
128 continue;
129 hd_index = dev[2] - 'a';
130 if (hd_index >= (is_scsi ? MAX_SCSI_DISKS : MAX_DISKS))
131 continue;
132 /* read the type of the device */
133 if (pasprintf(&buf, "%s/device/vbd/%s/device-type", path, e[i]) == -1)
134 continue;
135 free(type);
136 type = xs_read(xsh, XBT_NULL, buf, &len);
137 if (pasprintf(&buf, "%s/params", bpath) == -1)
138 continue;
139 free(params);
140 params = xs_read(xsh, XBT_NULL, buf, &len);
141 if (params == NULL)
142 continue;
143 /*
144 * check if device has a phantom vbd; the phantom is hooked
145 * to the frontend device (for ease of cleanup), so lookup
146 * the frontend device, and see if there is a phantom_vbd
147 * if there is, we will use resolution as the filename
148 */
149 if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1)
150 continue;
151 free(fpath);
152 fpath = xs_read(xsh, XBT_NULL, buf, &len);
153 if (fpath) {
154 if (pasprintf(&buf, "%s/dev", fpath) == -1)
155 continue;
156 free(params);
157 params = xs_read(xsh, XBT_NULL, buf , &len);
158 if (params) {
159 /*
160 * wait for device, on timeout silently fail because we will
161 * fail to open below
162 */
163 waitForDevice(params);
164 }
165 }
167 bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)] = bdrv_new(dev);
168 /* check if it is a cdrom */
169 if (type && !strcmp(type, "cdrom")) {
170 bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM);
171 if (pasprintf(&buf, "%s/params", bpath) != -1)
172 xs_watch(xsh, buf, dev);
173 }
174 /* open device now if media present */
175 if (params[0]) {
176 char *p = strchr(params, ':');
177 p = p ? p+1 : params; /* skip colon separator if present */
178 if (bdrv_open(bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)],
179 p, 0 /* snapshot */) < 0)
180 fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
181 p);
182 }
183 }
185 /* Set a watch for log-dirty requests from the migration tools */
186 if (pasprintf(&buf, "%s/logdirty/next-active", path) != -1) {
187 xs_watch(xsh, buf, "logdirty");
188 fprintf(logfile, "Watching %s\n", buf);
189 }
192 out:
193 free(type);
194 free(params);
195 free(dev);
196 free(bpath);
197 free(buf);
198 free(path);
199 free(e);
200 return;
201 }
203 int xenstore_fd(void)
204 {
205 if (xsh)
206 return xs_fileno(xsh);
207 return -1;
208 }
210 unsigned long *logdirty_bitmap = NULL;
211 unsigned long logdirty_bitmap_size;
212 extern int vga_ram_size, bios_size;
214 void xenstore_process_logdirty_event(void)
215 {
216 char *act;
217 static char *active_path = NULL;
218 static char *next_active_path = NULL;
219 static char *seg = NULL;
220 unsigned int len;
221 int i;
223 fprintf(logfile, "Triggered log-dirty buffer switch\n");
225 if (!seg) {
226 char *path, *p, *key_ascii, key_terminated[17] = {0,};
227 key_t key;
228 int shmid;
230 /* Find and map the shared memory segment for log-dirty bitmaps */
231 if (!(path = xs_get_domain_path(xsh, domid))) {
232 fprintf(logfile, "Log-dirty: can't get domain path in store\n");
233 exit(1);
234 }
235 if (!(path = realloc(path, strlen(path)
236 + strlen("/logdirty/next-active") + 1))) {
237 fprintf(logfile, "Log-dirty: out of memory\n");
238 exit(1);
239 }
240 strcat(path, "/logdirty/");
241 p = path + strlen(path);
242 strcpy(p, "key");
244 key_ascii = xs_read(xsh, XBT_NULL, path, &len);
245 if (!key_ascii) {
246 /* No key yet: wait for the next watch */
247 free(path);
248 return;
249 }
250 strncpy(key_terminated, key_ascii, 16);
251 free(key_ascii);
252 key = (key_t) strtoull(key_terminated, NULL, 16);
254 /* Figure out how bit the log-dirty bitmaps are */
255 logdirty_bitmap_size = xc_memory_op(xc_handle,
256 XENMEM_maximum_gpfn, &domid) + 1;
257 logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
258 / HOST_LONG_BITS); /* longs */
259 logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
261 /* Map the shared-memory segment */
262 if ((shmid = shmget(key,
263 2 * logdirty_bitmap_size,
264 S_IRUSR|S_IWUSR)) == -1
265 || (seg = shmat(shmid, NULL, 0)) == (void *)-1) {
266 fprintf(logfile, "Log-dirty: can't map segment %16.16llx (%s)\n",
267 (unsigned long long) key, strerror(errno));
268 exit(1);
269 }
271 fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
273 /* Double-check that the bitmaps are the size we expect */
274 if (logdirty_bitmap_size != *(uint32_t *)seg) {
275 fprintf(logfile, "Log-dirty: got %u, calc %lu\n",
276 *(uint32_t *)seg, logdirty_bitmap_size);
277 return;
278 }
280 /* Remember the paths for the next-active and active entries */
281 strcpy(p, "active");
282 if (!(active_path = strdup(path))) {
283 fprintf(logfile, "Log-dirty: out of memory\n");
284 exit(1);
285 }
286 strcpy(p, "next-active");
287 if (!(next_active_path = strdup(path))) {
288 fprintf(logfile, "Log-dirty: out of memory\n");
289 exit(1);
290 }
291 free(path);
292 }
294 /* Read the required active buffer from the store */
295 act = xs_read(xsh, XBT_NULL, next_active_path, &len);
296 if (!act) {
297 fprintf(logfile, "Log-dirty: can't read next-active\n");
298 exit(1);
299 }
301 /* Switch buffers */
302 i = act[0] - '0';
303 if (i != 0 && i != 1) {
304 fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
305 exit(1);
306 }
307 logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
309 /* Ack that we've switched */
310 xs_write(xsh, XBT_NULL, active_path, act, len);
311 free(act);
312 }
316 void xenstore_process_event(void *opaque)
317 {
318 char **vec, *image = NULL;
319 unsigned int len, num, hd_index;
321 vec = xs_read_watch(xsh, &num);
322 if (!vec)
323 return;
325 if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) {
326 xenstore_process_logdirty_event();
327 goto out;
328 }
330 if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) ||
331 strlen(vec[XS_WATCH_TOKEN]) != 3)
332 goto out;
333 hd_index = vec[XS_WATCH_TOKEN][2] - 'a';
334 image = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len);
335 if (image == NULL || !strcmp(image, bs_table[hd_index]->filename))
336 goto out; /* gone or identical */
338 do_eject(0, vec[XS_WATCH_TOKEN]);
339 bs_table[hd_index]->filename[0] = 0;
340 if (media_filename[hd_index]) {
341 free(media_filename[hd_index]);
342 media_filename[hd_index] = NULL;
343 }
345 if (image[0]) {
346 media_filename[hd_index] = strdup(image);
347 xenstore_check_new_media_present(5000);
348 }
350 out:
351 free(image);
352 free(vec);
353 }
355 void xenstore_write_vncport(int display)
356 {
357 char *buf = NULL, *path;
358 char *portstr = NULL;
360 if (xsh == NULL)
361 return;
363 path = xs_get_domain_path(xsh, domid);
364 if (path == NULL) {
365 fprintf(logfile, "xs_get_domain_path() error\n");
366 goto out;
367 }
369 if (pasprintf(&buf, "%s/console/vnc-port", path) == -1)
370 goto out;
372 if (pasprintf(&portstr, "%d", display) == -1)
373 goto out;
375 if (xs_write(xsh, XBT_NULL, buf, portstr, strlen(portstr)) == 0)
376 fprintf(logfile, "xs_write() vncport failed\n");
378 out:
379 free(portstr);
380 free(buf);
381 }
383 int xenstore_read_vncpasswd(int domid)
384 {
385 extern char vncpasswd[64];
386 char *buf = NULL, *path, *uuid = NULL, *passwd = NULL;
387 unsigned int i, len, rc = 0;
389 if (xsh == NULL) {
390 return -1;
391 }
393 path = xs_get_domain_path(xsh, domid);
394 if (path == NULL) {
395 fprintf(logfile, "xs_get_domain_path() error. domid %d.\n", domid);
396 return -1;
397 }
399 pasprintf(&buf, "%s/vm", path);
400 uuid = xs_read(xsh, XBT_NULL, buf, &len);
401 if (uuid == NULL) {
402 fprintf(logfile, "xs_read(): uuid get error. %s.\n", buf);
403 free(path);
404 return -1;
405 }
407 pasprintf(&buf, "%s/vncpasswd", uuid);
408 passwd = xs_read(xsh, XBT_NULL, buf, &len);
409 if (passwd == NULL) {
410 fprintf(logfile, "xs_read(): vncpasswd get error. %s.\n", buf);
411 free(uuid);
412 free(path);
413 return rc;
414 }
416 for (i=0; i<len && i<63; i++) {
417 vncpasswd[i] = passwd[i];
418 passwd[i] = '\0';
419 }
420 vncpasswd[len] = '\0';
421 pasprintf(&buf, "%s/vncpasswd", uuid);
422 if (xs_write(xsh, XBT_NULL, buf, passwd, len) == 0) {
423 fprintf(logfile, "xs_write() vncpasswd failed.\n");
424 rc = -1;
425 }
427 free(passwd);
428 free(uuid);
429 free(path);
431 return rc;
432 }
435 /*
436 * get all device instances of a certain type
437 */
438 char **xenstore_domain_get_devices(struct xs_handle *handle,
439 const char *devtype, unsigned int *num)
440 {
441 char *path;
442 char *buf = NULL;
443 char **e = NULL;
445 path = xs_get_domain_path(handle, domid);
446 if (path == NULL)
447 goto out;
449 if (pasprintf(&buf, "%s/device/%s", path,devtype) == -1)
450 goto out;
452 e = xs_directory(handle, XBT_NULL, buf, num);
454 out:
455 free(path);
456 free(buf);
457 return e;
458 }
460 /*
461 * Check whether a domain has devices of the given type
462 */
463 int xenstore_domain_has_devtype(struct xs_handle *handle, const char *devtype)
464 {
465 int rc = 0;
466 unsigned int num;
467 char **e = xenstore_domain_get_devices(handle, devtype, &num);
468 if (e)
469 rc = 1;
470 free(e);
471 return rc;
472 }
474 /*
475 * Function that creates a path to a variable of an instance of a
476 * certain device
477 */
478 static char *get_device_variable_path(const char *devtype, const char *inst,
479 const char *var)
480 {
481 char *buf = NULL;
482 if (pasprintf(&buf, "/local/domain/0/backend/%s/%d/%s/%s",
483 devtype,
484 domid,
485 inst,
486 var) == -1) {
487 free(buf);
488 buf = NULL;
489 }
490 return buf;
491 }
493 char *xenstore_backend_read_variable(struct xs_handle *handle,
494 const char *devtype, const char *inst,
495 const char *var)
496 {
497 char *value = NULL;
498 char *buf = NULL;
499 unsigned int len;
501 buf = get_device_variable_path(devtype, inst, var);
502 if (NULL == buf)
503 goto out;
505 value = xs_read(handle, XBT_NULL, buf, &len);
507 free(buf);
509 out:
510 return value;
511 }
513 /*
514 Read the hotplug status variable from the backend given the type
515 of device and its instance.
516 */
517 char *xenstore_read_hotplug_status(struct xs_handle *handle,
518 const char *devtype, const char *inst)
519 {
520 return xenstore_backend_read_variable(handle, devtype, inst,
521 "hotplug-status");
522 }
524 /*
525 Subscribe to the hotplug status of a device given the type of device and
526 its instance.
527 In case an error occurrs, a negative number is returned.
528 */
529 int xenstore_subscribe_to_hotplug_status(struct xs_handle *handle,
530 const char *devtype,
531 const char *inst,
532 const char *token)
533 {
534 int rc = 0;
535 char *path = get_device_variable_path(devtype, inst, "hotplug-status");
537 if (path == NULL)
538 return -1;
540 if (0 == xs_watch(handle, path, token))
541 rc = -2;
543 free(path);
545 return rc;
546 }
548 /*
549 * Unsubscribe from a subscription to the status of a hotplug variable of
550 * a device.
551 */
552 int xenstore_unsubscribe_from_hotplug_status(struct xs_handle *handle,
553 const char *devtype,
554 const char *inst,
555 const char *token)
556 {
557 int rc = 0;
558 char *path;
559 path = get_device_variable_path(devtype, inst, "hotplug-status");
560 if (path == NULL)
561 return -1;
563 if (0 == xs_unwatch(handle, path, token))
564 rc = -2;
566 free(path);
568 return rc;
569 }
571 char *xenstore_vm_read(int domid, char *key, int *len)
572 {
573 char *buf = NULL, *path = NULL, *value = NULL;
575 if (xsh == NULL)
576 goto out;
578 path = xs_get_domain_path(xsh, domid);
579 if (path == NULL) {
580 fprintf(logfile, "xs_get_domain_path(%d): error\n", domid);
581 goto out;
582 }
584 pasprintf(&buf, "%s/vm", path);
585 free(path);
586 path = xs_read(xsh, XBT_NULL, buf, NULL);
587 if (path == NULL) {
588 fprintf(logfile, "xs_read(%s): read error\n", buf);
589 goto out;
590 }
592 pasprintf(&buf, "%s/%s", path, key);
593 value = xs_read(xsh, XBT_NULL, buf, len);
594 if (value == NULL) {
595 fprintf(logfile, "xs_read(%s): read error\n", buf);
596 goto out;
597 }
599 out:
600 free(path);
601 free(buf);
602 return value;
603 }
605 int xenstore_vm_write(int domid, char *key, char *value)
606 {
607 char *buf = NULL, *path = NULL;
608 int rc = -1;
610 if (xsh == NULL)
611 goto out;
613 path = xs_get_domain_path(xsh, domid);
614 if (path == NULL) {
615 fprintf(logfile, "xs_get_domain_path: error\n");
616 goto out;
617 }
619 pasprintf(&buf, "%s/vm", path);
620 free(path);
621 path = xs_read(xsh, XBT_NULL, buf, NULL);
622 if (path == NULL) {
623 fprintf(logfile, "xs_read(%s): read error\n", buf);
624 goto out;
625 }
627 pasprintf(&buf, "%s/%s", path, key);
628 rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
629 if (rc) {
630 fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
631 goto out;
632 }
634 out:
635 free(path);
636 free(buf);
637 return rc;
638 }