ia64/xen-unstable

view tools/blktap/drivers/blktapctrl.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 425c3d6f7557
children b1da8762f853
line source
1 /*
2 * blktapctrl.c
3 *
4 * userspace controller for the blktap disks.
5 * As requests for new block devices arrive,
6 * the controller spawns off a separate process
7 * per-disk.
8 *
9 *
10 * Copyright (c) 2005 Julian Chesterfield and Andrew Warfield.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License version 2
14 * as published by the Free Software Foundation; or, when distributed
15 * separately from the Linux kernel or incorporated into other
16 * software packages, subject to the following license:
17 *
18 * Permission is hereby granted, free of charge, to any person obtaining a copy
19 * of this source file (the "Software"), to deal in the Software without
20 * restriction, including without limitation the rights to use, copy, modify,
21 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
22 * and to permit persons to whom the Software is furnished to do so, subject to
23 * the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be included in
26 * all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
33 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
34 * IN THE SOFTWARE.
35 */
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <sys/mman.h>
40 #include <sys/user.h>
41 #include <err.h>
42 #include <errno.h>
43 #include <sys/types.h>
44 #include <linux/types.h>
45 #include <sys/wait.h>
46 #include <signal.h>
47 #include <fcntl.h>
48 #include <sys/poll.h>
49 #include <sys/ioctl.h>
50 #include <string.h>
51 #include <unistd.h>
52 #include <xs.h>
53 #include <printf.h>
54 #include <sys/time.h>
55 #include <syslog.h>
57 #include "blktaplib.h"
58 #include "blktapctrl.h"
59 #include "tapdisk.h"
61 #define PIDFILE "/var/run/blktapctrl.pid"
63 #define NUM_POLL_FDS 2
64 #define MSG_SIZE 4096
65 #define MAX_TIMEOUT 10
66 #define MAX_RAND_VAL 0xFFFF
67 #define MAX_ATTEMPTS 10
69 int run = 1;
70 int max_timeout = MAX_TIMEOUT;
71 int ctlfd = 0;
73 int blktap_major;
75 static int open_ctrl_socket(char *devname);
76 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2);
77 static int read_msg(int fd, int msgtype, void *ptr);
78 static driver_list_entry_t *active_disks[MAX_DISK_TYPES];
80 static void init_driver_list(void)
81 {
82 int i;
84 for (i = 0; i < MAX_DISK_TYPES; i++)
85 active_disks[i] = NULL;
86 return;
87 }
89 static void init_rng(void)
90 {
91 static uint32_t seed;
92 struct timeval tv;
94 gettimeofday(&tv, NULL);
95 seed = tv.tv_usec;
96 srand48(seed);
97 return;
98 }
100 static void make_blktap_dev(char *devname, int major, int minor)
101 {
102 struct stat st;
104 if (lstat(devname, &st) != 0) {
105 /*Need to create device*/
106 if (mkdir(BLKTAP_DEV_DIR, 0755) == 0)
107 DPRINTF("Created %s directory\n",BLKTAP_DEV_DIR);
108 if (mknod(devname, S_IFCHR|0600,
109 makedev(major, minor)) == 0)
110 DPRINTF("Created %s device\n",devname);
111 } else {
112 DPRINTF("%s device already exists\n",devname);
113 /* it already exists, but is it the same major number */
114 if (((st.st_rdev>>8) & 0xff) != major) {
115 DPRINTF("%s has old major %d\n",
116 devname,
117 (unsigned int)((st.st_rdev >> 8) & 0xff));
118 /* only try again if we succed in deleting it */
119 if (!unlink(devname))
120 make_blktap_dev(devname, major, minor);
121 }
122 }
123 }
125 static int get_new_dev(int *major, int *minor, blkif_t *blkif)
126 {
127 domid_translate_t tr;
128 int ret;
129 char *devname;
131 tr.domid = blkif->domid;
132 tr.busid = (unsigned short)blkif->be_id;
133 ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF, tr );
135 if ( (ret <= 0)||(ret > MAX_TAP_DEV) ) {
136 DPRINTF("Incorrect Dev ID [%d]\n",ret);
137 return -1;
138 }
140 *minor = ret;
141 *major = ioctl(ctlfd, BLKTAP_IOCTL_MAJOR, ret );
142 if (*major < 0) {
143 DPRINTF("Incorrect Major ID [%d]\n",*major);
144 return -1;
145 }
147 if (asprintf(&devname,"%s/%s%d",BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, *minor) == -1)
148 return -1;
149 make_blktap_dev(devname,*major,*minor);
150 DPRINTF("Received device id %d and major %d, "
151 "sent domid %d and be_id %d\n",
152 *minor, *major, tr.domid, tr.busid);
153 return 0;
154 }
156 static int get_tapdisk_pid(blkif_t *blkif)
157 {
158 int ret;
160 if ((ret = write_msg(blkif->fds[WRITE], CTLMSG_PID, blkif, NULL))
161 <= 0) {
162 DPRINTF("Write_msg failed - CTLMSG_PID(%d)\n", ret);
163 return -EINVAL;
164 }
166 if ((ret = read_msg(blkif->fds[READ], CTLMSG_PID_RSP, blkif))
167 <= 0) {
168 DPRINTF("Read_msg failure - CTLMSG_PID(%d)\n", ret);
169 return -EINVAL;
170 }
171 return 1;
172 }
174 /* Look up the disk specified by path:
175 * if found, dev points to the device string in the path
176 * type is the tapdisk driver type id
177 * blkif is the existing interface if this is a shared driver
178 * and NULL otherwise.
179 * return 0 on success, -1 on error.
180 */
182 static int test_path(char *path, char **dev, int *type, blkif_t **blkif)
183 {
184 char *ptr, handle[10];
185 int i, size, found = 0;
187 size = sizeof(dtypes)/sizeof(disk_info_t *);
188 *type = MAX_DISK_TYPES + 1;
189 *blkif = NULL;
191 if ( (ptr = strstr(path, ":"))!=NULL) {
192 memcpy(handle, path, (ptr - path));
193 *dev = ptr + 1;
194 ptr = handle + (ptr - path);
195 *ptr = '\0';
196 DPRINTF("Detected handle: [%s]\n",handle);
198 for (i = 0; i < size; i++)
199 if (strncmp(handle, dtypes[i]->handle,
200 (ptr - path)) ==0) {
201 found = 1;
202 break;
203 }
205 if (found) {
206 *type = dtypes[i]->idnum;
208 if (dtypes[i]->single_handler == 1) {
209 /* Check whether tapdisk process
210 already exists */
211 if (active_disks[dtypes[i]->idnum] == NULL)
212 *blkif = NULL;
213 else
214 *blkif = active_disks[dtypes[i]
215 ->idnum]->blkif;
216 }
217 return 0;
218 }
219 }
221 /* Fall-through case, we didn't find a disk driver. */
222 DPRINTF("Unknown blktap disk type [%s]!\n",handle);
223 *dev = NULL;
224 return -1;
225 }
228 static void add_disktype(blkif_t *blkif, int type)
229 {
230 driver_list_entry_t *entry, **pprev;
232 if (type > MAX_DISK_TYPES)
233 return;
235 entry = malloc(sizeof(driver_list_entry_t));
236 entry->blkif = blkif;
237 entry->next = NULL;
239 pprev = &active_disks[type];
240 while (*pprev != NULL)
241 pprev = &(*pprev)->next;
243 *pprev = entry;
244 entry->pprev = pprev;
245 }
247 static int del_disktype(blkif_t *blkif)
248 {
249 driver_list_entry_t *entry, **pprev;
250 int type = blkif->drivertype, count = 0, close = 0;
252 if (type > MAX_DISK_TYPES)
253 return 1;
255 pprev = &active_disks[type];
256 while ((*pprev != NULL) && ((*pprev)->blkif != blkif))
257 pprev = &(*pprev)->next;
259 if ((entry = *pprev) == NULL) {
260 DPRINTF("DEL_DISKTYPE: No match\n");
261 return 1;
262 }
264 *pprev = entry->next;
265 if (entry->next)
266 entry->next->pprev = pprev;
268 DPRINTF("DEL_DISKTYPE: Freeing entry\n");
269 free(entry);
271 /* Caller should close() if no single controller, or list is empty. */
272 return (!dtypes[type]->single_handler || (active_disks[type] == NULL));
273 }
275 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2)
276 {
277 blkif_t *blkif;
278 blkif_info_t *blk;
279 msg_hdr_t *msg;
280 msg_newdev_t *msg_dev;
281 char *p, *buf, *path;
282 int msglen, len, ret;
283 fd_set writefds;
284 struct timeval timeout;
285 image_t *image, *img;
286 uint32_t seed;
288 blkif = (blkif_t *)ptr;
289 blk = blkif->info;
290 image = blkif->prv;
291 len = 0;
293 switch (msgtype)
294 {
295 case CTLMSG_PARAMS:
296 path = (char *)ptr2;
297 DPRINTF("Write_msg called: CTLMSG_PARAMS, sending [%s, %s]\n",
298 blk->params, path);
300 msglen = sizeof(msg_hdr_t) + strlen(path) + 1;
301 buf = malloc(msglen);
303 /*Assign header fields*/
304 msg = (msg_hdr_t *)buf;
305 msg->type = CTLMSG_PARAMS;
306 msg->len = msglen;
307 msg->drivertype = blkif->drivertype;
308 msg->readonly = blkif->readonly;
310 gettimeofday(&timeout, NULL);
311 msg->cookie = blkif->cookie;
312 DPRINTF("Generated cookie, %d\n",blkif->cookie);
314 /*Copy blk->params to msg*/
315 p = buf + sizeof(msg_hdr_t);
316 memcpy(p, path, strlen(path) + 1);
318 break;
320 case CTLMSG_NEWDEV:
321 DPRINTF("Write_msg called: CTLMSG_NEWDEV\n");
323 msglen = sizeof(msg_hdr_t) + sizeof(msg_newdev_t);
324 buf = malloc(msglen);
326 /*Assign header fields*/
327 msg = (msg_hdr_t *)buf;
328 msg->type = CTLMSG_NEWDEV;
329 msg->len = msglen;
330 msg->drivertype = blkif->drivertype;
331 msg->cookie = blkif->cookie;
333 msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t));
334 msg_dev->devnum = blkif->minor;
335 msg_dev->domid = blkif->domid;
337 break;
339 case CTLMSG_CLOSE:
340 DPRINTF("Write_msg called: CTLMSG_CLOSE\n");
342 msglen = sizeof(msg_hdr_t);
343 buf = malloc(msglen);
345 /*Assign header fields*/
346 msg = (msg_hdr_t *)buf;
347 msg->type = CTLMSG_CLOSE;
348 msg->len = msglen;
349 msg->drivertype = blkif->drivertype;
350 msg->cookie = blkif->cookie;
352 break;
354 case CTLMSG_PID:
355 DPRINTF("Write_msg called: CTLMSG_PID\n");
357 msglen = sizeof(msg_hdr_t);
358 buf = malloc(msglen);
360 /*Assign header fields*/
361 msg = (msg_hdr_t *)buf;
362 msg->type = CTLMSG_PID;
363 msg->len = msglen;
364 msg->drivertype = blkif->drivertype;
365 msg->cookie = blkif->cookie;
367 break;
369 default:
370 return -1;
371 }
373 /*Now send the message*/
374 ret = 0;
375 FD_ZERO(&writefds);
376 FD_SET(fd,&writefds);
377 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
378 timeout.tv_usec = 0;
379 if (select(fd+1, (fd_set *) 0, &writefds,
380 (fd_set *) 0, &timeout) > 0) {
381 len = write(fd, buf, msglen);
382 if (len == -1) DPRINTF("Write failed: (%d)\n",errno);
383 }
384 free(buf);
386 return len;
387 }
389 static int read_msg(int fd, int msgtype, void *ptr)
390 {
391 blkif_t *blkif;
392 blkif_info_t *blk;
393 msg_hdr_t *msg;
394 msg_pid_t *msg_pid;
395 char *p, *buf;
396 int msglen = MSG_SIZE, len, ret;
397 fd_set readfds;
398 struct timeval timeout;
399 image_t *image, *img;
402 blkif = (blkif_t *)ptr;
403 blk = blkif->info;
404 image = blkif->prv;
406 buf = malloc(MSG_SIZE);
408 ret = 0;
409 FD_ZERO(&readfds);
410 FD_SET(fd,&readfds);
411 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
412 timeout.tv_usec = 0;
413 if (select(fd+1, &readfds, (fd_set *) 0,
414 (fd_set *) 0, &timeout) > 0) {
415 ret = read(fd, buf, msglen);
416 }
417 if (ret > 0) {
418 msg = (msg_hdr_t *)buf;
419 switch (msg->type)
420 {
421 case CTLMSG_IMG:
422 img = (image_t *)(buf + sizeof(msg_hdr_t));
423 image->size = img->size;
424 image->secsize = img->secsize;
425 image->info = img->info;
427 DPRINTF("Received CTLMSG_IMG: %llu, %lu, %u\n",
428 image->size, image->secsize, image->info);
429 if(msgtype != CTLMSG_IMG) ret = 0;
430 break;
432 case CTLMSG_IMG_FAIL:
433 DPRINTF("Received CTLMSG_IMG_FAIL, "
434 "unable to open image\n");
435 ret = 0;
436 break;
438 case CTLMSG_NEWDEV_RSP:
439 DPRINTF("Received CTLMSG_NEWDEV_RSP\n");
440 if(msgtype != CTLMSG_NEWDEV_RSP) ret = 0;
441 break;
443 case CTLMSG_NEWDEV_FAIL:
444 DPRINTF("Received CTLMSG_NEWDEV_FAIL\n");
445 ret = 0;
446 break;
448 case CTLMSG_CLOSE_RSP:
449 DPRINTF("Received CTLMSG_CLOSE_RSP\n");
450 if (msgtype != CTLMSG_CLOSE_RSP) ret = 0;
451 break;
453 case CTLMSG_PID_RSP:
454 DPRINTF("Received CTLMSG_PID_RSP\n");
455 if (msgtype != CTLMSG_PID_RSP) ret = 0;
456 else {
457 msg_pid = (msg_pid_t *)
458 (buf + sizeof(msg_hdr_t));
459 blkif->tappid = msg_pid->pid;
460 DPRINTF("\tPID: [%d]\n",blkif->tappid);
461 }
462 break;
463 default:
464 DPRINTF("UNKNOWN MESSAGE TYPE RECEIVED\n");
465 ret = 0;
466 break;
467 }
468 }
470 free(buf);
472 return ret;
474 }
476 int launch_tapdisk(char *wrctldev, char *rdctldev)
477 {
478 char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL };
479 pid_t child;
481 if ((child = fork()) < 0)
482 return -1;
484 if (!child) {
485 int i;
486 for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++)
487 if (i != STDIN_FILENO &&
488 i != STDOUT_FILENO &&
489 i != STDERR_FILENO)
490 close(i);
492 execvp("tapdisk", argv);
493 _exit(1);
494 } else {
495 pid_t got;
496 do {
497 got = waitpid(child, NULL, 0);
498 } while (got != child);
499 }
500 return 0;
501 }
503 int blktapctrl_new_blkif(blkif_t *blkif)
504 {
505 blkif_info_t *blk;
506 int major, minor, fd_read, fd_write, type, new;
507 char *rdctldev, *wrctldev, *ptr;
508 image_t *image;
509 blkif_t *exist = NULL;
510 static uint16_t next_cookie = 0;
512 DPRINTF("Received a poll for a new vbd\n");
513 if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) {
514 if (get_new_dev(&major, &minor, blkif)<0)
515 return -1;
517 if (test_path(blk->params, &ptr, &type, &exist) != 0) {
518 DPRINTF("Error in blktap device string(%s).\n",
519 blk->params);
520 return -1;
521 }
522 blkif->drivertype = type;
523 blkif->cookie = next_cookie++;
525 if (!exist) {
526 DPRINTF("Process does not exist:\n");
527 if (asprintf(&rdctldev,
528 "%s/tapctrlread%d", BLKTAP_CTRL_DIR, minor) == -1)
529 return -1;
530 if (asprintf(&wrctldev,
531 "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, minor) == -1) {
532 free(rdctldev);
533 return -1;
534 }
535 blkif->fds[READ] = open_ctrl_socket(rdctldev);
536 blkif->fds[WRITE] = open_ctrl_socket(wrctldev);
538 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
539 goto fail;
541 /*launch the new process*/
542 DPRINTF("Launching process, CMDLINE [tapdisk %s %s]\n",wrctldev, rdctldev);
543 if (launch_tapdisk(wrctldev, rdctldev) == -1) {
544 DPRINTF("Unable to fork, cmdline: [tapdisk %s %s]\n",wrctldev, rdctldev);
545 return -1;
546 }
548 free(rdctldev);
549 free(wrctldev);
550 } else {
551 DPRINTF("Process exists!\n");
552 blkif->fds[READ] = exist->fds[READ];
553 blkif->fds[WRITE] = exist->fds[WRITE];
554 }
556 add_disktype(blkif, type);
557 blkif->major = major;
558 blkif->minor = minor;
560 image = (image_t *)malloc(sizeof(image_t));
561 blkif->prv = (void *)image;
562 blkif->ops = &tapdisk_ops;
564 /*Retrieve the PID of the new process*/
565 if (get_tapdisk_pid(blkif) <= 0) {
566 DPRINTF("Unable to contact disk process\n");
567 goto fail;
568 }
570 /* Both of the following read and write calls will block up to
571 * max_timeout val*/
572 if (write_msg(blkif->fds[WRITE], CTLMSG_PARAMS, blkif, ptr)
573 <= 0) {
574 DPRINTF("Write_msg failed - CTLMSG_PARAMS\n");
575 goto fail;
576 }
578 if (read_msg(blkif->fds[READ], CTLMSG_IMG, blkif) <= 0) {
579 DPRINTF("Read_msg failure - CTLMSG_IMG\n");
580 goto fail;
581 }
583 } else return -1;
585 return 0;
586 fail:
587 ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor);
588 return -EINVAL;
589 }
591 int map_new_blktapctrl(blkif_t *blkif)
592 {
593 DPRINTF("Received a poll for a new devmap\n");
594 if (write_msg(blkif->fds[WRITE], CTLMSG_NEWDEV, blkif, NULL) <= 0) {
595 DPRINTF("Write_msg failed - CTLMSG_NEWDEV\n");
596 return -EINVAL;
597 }
599 if (read_msg(blkif->fds[READ], CTLMSG_NEWDEV_RSP, blkif) <= 0) {
600 DPRINTF("Read_msg failed - CTLMSG_NEWDEV_RSP\n");
601 return -EINVAL;
602 }
603 DPRINTF("Exiting map_new_blktapctrl\n");
605 return blkif->minor - 1;
606 }
608 int unmap_blktapctrl(blkif_t *blkif)
609 {
610 DPRINTF("Unmapping vbd\n");
612 if (write_msg(blkif->fds[WRITE], CTLMSG_CLOSE, blkif, NULL) <= 0) {
613 DPRINTF("Write_msg failed - CTLMSG_CLOSE\n");
614 return -EINVAL;
615 }
617 if (del_disktype(blkif)) {
618 close(blkif->fds[WRITE]);
619 close(blkif->fds[READ]);
620 }
622 return 0;
623 }
625 int open_ctrl_socket(char *devname)
626 {
627 int ret;
628 int ipc_fd;
629 fd_set socks;
630 struct timeval timeout;
632 if (mkdir(BLKTAP_CTRL_DIR, 0755) == 0)
633 DPRINTF("Created %s directory\n", BLKTAP_CTRL_DIR);
634 ret = mkfifo(devname,S_IRWXU|S_IRWXG|S_IRWXO);
635 if ( (ret != 0) && (errno != EEXIST) ) {
636 DPRINTF("ERROR: pipe failed (%d)\n", errno);
637 exit(0);
638 }
640 ipc_fd = open(devname,O_RDWR|O_NONBLOCK);
642 if (ipc_fd < 0) {
643 DPRINTF("FD open failed\n");
644 return -1;
645 }
647 return ipc_fd;
648 }
650 static void print_drivers(void)
651 {
652 int i, size;
654 size = sizeof(dtypes)/sizeof(disk_info_t *);
655 DPRINTF("blktapctrl: v1.0.0\n");
656 for (i = 0; i < size; i++)
657 DPRINTF("Found driver: [%s]\n",dtypes[i]->name);
658 }
660 static void write_pidfile(long pid)
661 {
662 char buf[100];
663 int len;
664 int fd;
665 int flags;
667 fd = open(PIDFILE, O_RDWR | O_CREAT, 0600);
668 if (fd == -1) {
669 DPRINTF("Opening pid file failed (%d)\n", errno);
670 exit(1);
671 }
673 /* We exit silently if daemon already running. */
674 if (lockf(fd, F_TLOCK, 0) == -1)
675 exit(0);
677 /* Set FD_CLOEXEC, so that tapdisk doesn't get this file
678 descriptor. */
679 if ((flags = fcntl(fd, F_GETFD)) == -1) {
680 DPRINTF("F_GETFD failed (%d)\n", errno);
681 exit(1);
682 }
683 flags |= FD_CLOEXEC;
684 if (fcntl(fd, F_SETFD, flags) == -1) {
685 DPRINTF("F_SETFD failed (%d)\n", errno);
686 exit(1);
687 }
689 len = sprintf(buf, "%ld\n", pid);
690 if (write(fd, buf, len) != len) {
691 DPRINTF("Writing pid file failed (%d)\n", errno);
692 exit(1);
693 }
694 }
696 int main(int argc, char *argv[])
697 {
698 char *devname;
699 tapdev_info_t *ctlinfo;
700 int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
701 struct xs_handle *h;
702 struct pollfd pfd[NUM_POLL_FDS];
703 pid_t process;
704 char buf[128];
706 __init_blkif();
707 snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid());
708 openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON);
709 if (daemon(0,0)) {
710 DPRINTF("daemon failed (%d)\n", errno);
711 goto open_failed;
712 }
714 print_drivers();
715 init_driver_list();
716 init_rng();
718 register_new_blkif_hook(blktapctrl_new_blkif);
719 register_new_devmap_hook(map_new_blktapctrl);
720 register_new_unmap_hook(unmap_blktapctrl);
722 /* Attach to blktap0 */
723 if (asprintf(&devname,"%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME) == -1)
724 goto open_failed;
725 if ((ret = xc_find_device_number("blktap0")) < 0) {
726 DPRINTF("couldn't find device number for 'blktap0'\n");
727 goto open_failed;
728 }
729 blktap_major = major(ret);
730 make_blktap_dev(devname,blktap_major,0);
731 ctlfd = open(devname, O_RDWR);
732 if (ctlfd == -1) {
733 DPRINTF("blktap0 open failed\n");
734 goto open_failed;
735 }
738 retry:
739 /* Set up store connection and watch. */
740 h = xs_daemon_open();
741 if (h == NULL) {
742 DPRINTF("xs_daemon_open failed -- "
743 "is xenstore running?\n");
744 if (count < MAX_ATTEMPTS) {
745 count++;
746 sleep(2);
747 goto retry;
748 } else goto open_failed;
749 }
751 ret = setup_probe_watch(h);
752 if (ret != 0) {
753 DPRINTF("Failed adding device probewatch\n");
754 xs_daemon_close(h);
755 goto open_failed;
756 }
758 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
760 process = getpid();
761 write_pidfile(process);
762 ret = ioctl(ctlfd, BLKTAP_IOCTL_SENDPID, process );
764 /*Static pollhooks*/
765 pfd_count = 0;
766 tap_pfd = pfd_count++;
767 pfd[tap_pfd].fd = ctlfd;
768 pfd[tap_pfd].events = POLLIN;
770 store_pfd = pfd_count++;
771 pfd[store_pfd].fd = xs_fileno(h);
772 pfd[store_pfd].events = POLLIN;
774 while (run) {
775 timeout = 1000; /*Milliseconds*/
776 ret = poll(pfd, pfd_count, timeout);
778 if (ret > 0) {
779 if (pfd[store_pfd].revents) {
780 ret = xs_fire_next_watch(h);
781 }
782 }
783 }
785 xs_daemon_close(h);
786 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
787 close(ctlfd);
788 closelog();
790 return 0;
792 open_failed:
793 DPRINTF("Unable to start blktapctrl\n");
794 closelog();
795 return -1;
796 }
798 /*
799 * Local variables:
800 * c-file-style: "linux"
801 * indent-tabs-mode: t
802 * c-indent-level: 8
803 * c-basic-offset: 8
804 * tab-width: 8
805 * End:
806 */