debuggers.hg

view tools/blktap/drivers/blktapctrl.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 221b2680ffe5
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/stat.h>
41 #include <err.h>
42 #include <errno.h>
43 #include <sys/types.h>
44 #include <sys/wait.h>
45 #include <signal.h>
46 #include <fcntl.h>
47 #include <sys/poll.h>
48 #include <sys/ioctl.h>
49 #include <string.h>
50 #include <unistd.h>
51 #include <xs.h>
52 #include <sys/time.h>
53 #include <syslog.h>
55 #include "blktaplib.h"
56 #include "blktapctrl.h"
57 #include "tapdisk.h"
59 #define PIDFILE "/var/run/blktapctrl.pid"
61 #define NUM_POLL_FDS 2
62 #define MSG_SIZE 4096
63 #define MAX_TIMEOUT 10
64 #define MAX_RAND_VAL 0xFFFF
65 #define MAX_ATTEMPTS 10
67 int run = 1;
68 int max_timeout = MAX_TIMEOUT;
69 int ctlfd = 0;
71 int blktap_major;
73 static int open_ctrl_socket(char *devname);
74 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2);
75 static int read_msg(int fd, int msgtype, void *ptr);
76 static driver_list_entry_t *active_disks[MAX_DISK_TYPES];
78 static void init_driver_list(void)
79 {
80 int i;
82 for (i = 0; i < MAX_DISK_TYPES; i++)
83 active_disks[i] = NULL;
84 return;
85 }
87 static void init_rng(void)
88 {
89 static uint32_t seed;
90 struct timeval tv;
92 gettimeofday(&tv, NULL);
93 seed = tv.tv_usec;
94 srand48(seed);
95 return;
96 }
98 static void make_blktap_dev(char *devname, int major, int minor)
99 {
100 struct stat st;
102 if (lstat(devname, &st) != 0) {
103 /*Need to create device*/
104 if (mkdir(BLKTAP_DEV_DIR, 0755) == 0)
105 DPRINTF("Created %s directory\n",BLKTAP_DEV_DIR);
106 if (mknod(devname, S_IFCHR|0600,
107 makedev(major, minor)) == 0)
108 DPRINTF("Created %s device\n",devname);
109 } else {
110 DPRINTF("%s device already exists\n",devname);
111 /* it already exists, but is it the same major number */
112 if (((st.st_rdev>>8) & 0xff) != major) {
113 DPRINTF("%s has old major %d\n",
114 devname,
115 (unsigned int)((st.st_rdev >> 8) & 0xff));
116 /* only try again if we succed in deleting it */
117 if (!unlink(devname))
118 make_blktap_dev(devname, major, minor);
119 }
120 }
121 }
123 static int get_new_dev(int *major, int *minor, blkif_t *blkif)
124 {
125 domid_translate_t tr;
126 int ret;
127 char *devname;
129 tr.domid = blkif->domid;
130 tr.busid = (unsigned short)blkif->be_id;
131 ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF, tr );
133 if ( (ret <= 0)||(ret > MAX_TAP_DEV) ) {
134 DPRINTF("Incorrect Dev ID [%d]\n",ret);
135 return -1;
136 }
138 *minor = ret;
139 *major = ioctl(ctlfd, BLKTAP_IOCTL_MAJOR, ret );
140 if (*major < 0) {
141 DPRINTF("Incorrect Major ID [%d]\n",*major);
142 return -1;
143 }
145 if (asprintf(&devname,"%s/%s%d",BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, *minor) == -1)
146 return -1;
147 make_blktap_dev(devname,*major,*minor);
148 DPRINTF("Received device id %d and major %d, "
149 "sent domid %d and be_id %d\n",
150 *minor, *major, tr.domid, tr.busid);
151 return 0;
152 }
154 static int get_tapdisk_pid(blkif_t *blkif)
155 {
156 int ret;
158 if ((ret = write_msg(blkif->fds[WRITE], CTLMSG_PID, blkif, NULL))
159 <= 0) {
160 DPRINTF("Write_msg failed - CTLMSG_PID(%d)\n", ret);
161 return -EINVAL;
162 }
164 if ((ret = read_msg(blkif->fds[READ], CTLMSG_PID_RSP, blkif))
165 <= 0) {
166 DPRINTF("Read_msg failure - CTLMSG_PID(%d)\n", ret);
167 return -EINVAL;
168 }
169 return 1;
170 }
172 /* Look up the disk specified by path:
173 * if found, dev points to the device string in the path
174 * type is the tapdisk driver type id
175 * blkif is the existing interface if this is a shared driver
176 * and NULL otherwise.
177 * return 0 on success, -1 on error.
178 */
180 static int test_path(char *path, char **dev, int *type, blkif_t **blkif)
181 {
182 char *ptr, handle[10];
183 int i, size, found = 0;
185 size = sizeof(dtypes)/sizeof(disk_info_t *);
186 *type = MAX_DISK_TYPES + 1;
187 *blkif = NULL;
189 if ( (ptr = strstr(path, ":"))!=NULL) {
190 memcpy(handle, path, (ptr - path));
191 *dev = ptr + 1;
192 ptr = handle + (ptr - path);
193 *ptr = '\0';
194 DPRINTF("Detected handle: [%s]\n",handle);
196 for (i = 0; i < size; i++)
197 if (strncmp(handle, dtypes[i]->handle,
198 (ptr - path)) ==0) {
199 found = 1;
200 break;
201 }
203 if (found) {
204 *type = dtypes[i]->idnum;
206 if (dtypes[i]->single_handler == 1) {
207 /* Check whether tapdisk process
208 already exists */
209 if (active_disks[dtypes[i]->idnum] == NULL)
210 *blkif = NULL;
211 else
212 *blkif = active_disks[dtypes[i]
213 ->idnum]->blkif;
214 }
215 return 0;
216 }
217 }
219 /* Fall-through case, we didn't find a disk driver. */
220 DPRINTF("Unknown blktap disk type [%s]!\n",handle);
221 *dev = NULL;
222 return -1;
223 }
226 static void add_disktype(blkif_t *blkif, int type)
227 {
228 driver_list_entry_t *entry, **pprev;
230 if (type > MAX_DISK_TYPES)
231 return;
233 entry = malloc(sizeof(driver_list_entry_t));
234 entry->blkif = blkif;
235 entry->next = NULL;
237 pprev = &active_disks[type];
238 while (*pprev != NULL)
239 pprev = &(*pprev)->next;
241 *pprev = entry;
242 entry->pprev = pprev;
243 }
245 static int del_disktype(blkif_t *blkif)
246 {
247 driver_list_entry_t *entry, **pprev;
248 int type = blkif->drivertype, count = 0, close = 0;
250 if (type > MAX_DISK_TYPES)
251 return 1;
253 pprev = &active_disks[type];
254 while ((*pprev != NULL) && ((*pprev)->blkif != blkif))
255 pprev = &(*pprev)->next;
257 if ((entry = *pprev) == NULL) {
258 DPRINTF("DEL_DISKTYPE: No match\n");
259 return 1;
260 }
262 *pprev = entry->next;
263 if (entry->next)
264 entry->next->pprev = pprev;
266 DPRINTF("DEL_DISKTYPE: Freeing entry\n");
267 free(entry);
269 /* Caller should close() if no single controller, or list is empty. */
270 return (!dtypes[type]->single_handler || (active_disks[type] == NULL));
271 }
273 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2)
274 {
275 blkif_t *blkif;
276 blkif_info_t *blk;
277 msg_hdr_t *msg;
278 msg_newdev_t *msg_dev;
279 char *p, *buf, *path;
280 int msglen, len, ret;
281 fd_set writefds;
282 struct timeval timeout;
283 image_t *image, *img;
284 uint32_t seed;
286 blkif = (blkif_t *)ptr;
287 blk = blkif->info;
288 image = blkif->prv;
289 len = 0;
291 switch (msgtype)
292 {
293 case CTLMSG_PARAMS:
294 path = (char *)ptr2;
295 DPRINTF("Write_msg called: CTLMSG_PARAMS, sending [%s, %s]\n",
296 blk->params, path);
298 msglen = sizeof(msg_hdr_t) + strlen(path) + 1;
299 buf = malloc(msglen);
301 /*Assign header fields*/
302 msg = (msg_hdr_t *)buf;
303 msg->type = CTLMSG_PARAMS;
304 msg->len = msglen;
305 msg->drivertype = blkif->drivertype;
306 msg->readonly = blkif->readonly;
308 gettimeofday(&timeout, NULL);
309 msg->cookie = blkif->cookie;
310 DPRINTF("Generated cookie, %d\n",blkif->cookie);
312 /*Copy blk->params to msg*/
313 p = buf + sizeof(msg_hdr_t);
314 memcpy(p, path, strlen(path) + 1);
316 break;
318 case CTLMSG_NEWDEV:
319 DPRINTF("Write_msg called: CTLMSG_NEWDEV\n");
321 msglen = sizeof(msg_hdr_t) + sizeof(msg_newdev_t);
322 buf = malloc(msglen);
324 /*Assign header fields*/
325 msg = (msg_hdr_t *)buf;
326 msg->type = CTLMSG_NEWDEV;
327 msg->len = msglen;
328 msg->drivertype = blkif->drivertype;
329 msg->cookie = blkif->cookie;
331 msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t));
332 msg_dev->devnum = blkif->minor;
333 msg_dev->domid = blkif->domid;
335 break;
337 case CTLMSG_CLOSE:
338 DPRINTF("Write_msg called: CTLMSG_CLOSE\n");
340 msglen = sizeof(msg_hdr_t);
341 buf = malloc(msglen);
343 /*Assign header fields*/
344 msg = (msg_hdr_t *)buf;
345 msg->type = CTLMSG_CLOSE;
346 msg->len = msglen;
347 msg->drivertype = blkif->drivertype;
348 msg->cookie = blkif->cookie;
350 break;
352 case CTLMSG_PID:
353 DPRINTF("Write_msg called: CTLMSG_PID\n");
355 msglen = sizeof(msg_hdr_t);
356 buf = malloc(msglen);
358 /*Assign header fields*/
359 msg = (msg_hdr_t *)buf;
360 msg->type = CTLMSG_PID;
361 msg->len = msglen;
362 msg->drivertype = blkif->drivertype;
363 msg->cookie = blkif->cookie;
365 break;
367 default:
368 return -1;
369 }
371 /*Now send the message*/
372 ret = 0;
373 FD_ZERO(&writefds);
374 FD_SET(fd,&writefds);
375 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
376 timeout.tv_usec = 0;
377 if (select(fd+1, (fd_set *) 0, &writefds,
378 (fd_set *) 0, &timeout) > 0) {
379 len = write(fd, buf, msglen);
380 if (len == -1) DPRINTF("Write failed: (%d)\n",errno);
381 }
382 free(buf);
384 return len;
385 }
387 static int read_msg(int fd, int msgtype, void *ptr)
388 {
389 blkif_t *blkif;
390 blkif_info_t *blk;
391 msg_hdr_t *msg;
392 msg_pid_t *msg_pid;
393 char *p, *buf;
394 int msglen = MSG_SIZE, len, ret;
395 fd_set readfds;
396 struct timeval timeout;
397 image_t *image, *img;
400 blkif = (blkif_t *)ptr;
401 blk = blkif->info;
402 image = blkif->prv;
404 buf = malloc(MSG_SIZE);
406 ret = 0;
407 FD_ZERO(&readfds);
408 FD_SET(fd,&readfds);
409 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
410 timeout.tv_usec = 0;
411 if (select(fd+1, &readfds, (fd_set *) 0,
412 (fd_set *) 0, &timeout) > 0) {
413 ret = read(fd, buf, msglen);
414 }
415 if (ret > 0) {
416 msg = (msg_hdr_t *)buf;
417 switch (msg->type)
418 {
419 case CTLMSG_IMG:
420 img = (image_t *)(buf + sizeof(msg_hdr_t));
421 image->size = img->size;
422 image->secsize = img->secsize;
423 image->info = img->info;
425 DPRINTF("Received CTLMSG_IMG: %llu, %lu, %u\n",
426 image->size, image->secsize, image->info);
427 if(msgtype != CTLMSG_IMG) ret = 0;
428 break;
430 case CTLMSG_IMG_FAIL:
431 DPRINTF("Received CTLMSG_IMG_FAIL, "
432 "unable to open image\n");
433 ret = 0;
434 break;
436 case CTLMSG_NEWDEV_RSP:
437 DPRINTF("Received CTLMSG_NEWDEV_RSP\n");
438 if(msgtype != CTLMSG_NEWDEV_RSP) ret = 0;
439 break;
441 case CTLMSG_NEWDEV_FAIL:
442 DPRINTF("Received CTLMSG_NEWDEV_FAIL\n");
443 ret = 0;
444 break;
446 case CTLMSG_CLOSE_RSP:
447 DPRINTF("Received CTLMSG_CLOSE_RSP\n");
448 if (msgtype != CTLMSG_CLOSE_RSP) ret = 0;
449 break;
451 case CTLMSG_PID_RSP:
452 DPRINTF("Received CTLMSG_PID_RSP\n");
453 if (msgtype != CTLMSG_PID_RSP) ret = 0;
454 else {
455 msg_pid = (msg_pid_t *)
456 (buf + sizeof(msg_hdr_t));
457 blkif->tappid = msg_pid->pid;
458 DPRINTF("\tPID: [%d]\n",blkif->tappid);
459 }
460 break;
461 default:
462 DPRINTF("UNKNOWN MESSAGE TYPE RECEIVED\n");
463 ret = 0;
464 break;
465 }
466 }
468 free(buf);
470 return ret;
472 }
474 int launch_tapdisk(char *wrctldev, char *rdctldev)
475 {
476 char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL };
477 pid_t child;
479 if ((child = fork()) < 0)
480 return -1;
482 if (!child) {
483 int i;
484 for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++)
485 if (i != STDIN_FILENO &&
486 i != STDOUT_FILENO &&
487 i != STDERR_FILENO)
488 close(i);
490 execvp("tapdisk", argv);
491 _exit(1);
492 } else {
493 pid_t got;
494 do {
495 got = waitpid(child, NULL, 0);
496 } while (got != child);
497 }
498 return 0;
499 }
501 int blktapctrl_new_blkif(blkif_t *blkif)
502 {
503 blkif_info_t *blk;
504 int major, minor, fd_read, fd_write, type, new;
505 char *rdctldev, *wrctldev, *ptr;
506 image_t *image;
507 blkif_t *exist = NULL;
508 static uint16_t next_cookie = 0;
510 DPRINTF("Received a poll for a new vbd\n");
511 if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) {
512 if (get_new_dev(&major, &minor, blkif)<0)
513 return -1;
515 if (test_path(blk->params, &ptr, &type, &exist) != 0) {
516 DPRINTF("Error in blktap device string(%s).\n",
517 blk->params);
518 return -1;
519 }
520 blkif->drivertype = type;
521 blkif->cookie = next_cookie++;
523 if (!exist) {
524 DPRINTF("Process does not exist:\n");
525 if (asprintf(&rdctldev,
526 "%s/tapctrlread%d", BLKTAP_CTRL_DIR, minor) == -1)
527 return -1;
528 if (asprintf(&wrctldev,
529 "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, minor) == -1) {
530 free(rdctldev);
531 return -1;
532 }
533 blkif->fds[READ] = open_ctrl_socket(rdctldev);
534 blkif->fds[WRITE] = open_ctrl_socket(wrctldev);
536 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
537 goto fail;
539 /*launch the new process*/
540 DPRINTF("Launching process, CMDLINE [tapdisk %s %s]\n",wrctldev, rdctldev);
541 if (launch_tapdisk(wrctldev, rdctldev) == -1) {
542 DPRINTF("Unable to fork, cmdline: [tapdisk %s %s]\n",wrctldev, rdctldev);
543 return -1;
544 }
546 free(rdctldev);
547 free(wrctldev);
548 } else {
549 DPRINTF("Process exists!\n");
550 blkif->fds[READ] = exist->fds[READ];
551 blkif->fds[WRITE] = exist->fds[WRITE];
552 }
554 add_disktype(blkif, type);
555 blkif->major = major;
556 blkif->minor = minor;
558 image = (image_t *)malloc(sizeof(image_t));
559 blkif->prv = (void *)image;
560 blkif->ops = &tapdisk_ops;
562 /*Retrieve the PID of the new process*/
563 if (get_tapdisk_pid(blkif) <= 0) {
564 DPRINTF("Unable to contact disk process\n");
565 goto fail;
566 }
568 /* Both of the following read and write calls will block up to
569 * max_timeout val*/
570 if (write_msg(blkif->fds[WRITE], CTLMSG_PARAMS, blkif, ptr)
571 <= 0) {
572 DPRINTF("Write_msg failed - CTLMSG_PARAMS\n");
573 goto fail;
574 }
576 if (read_msg(blkif->fds[READ], CTLMSG_IMG, blkif) <= 0) {
577 DPRINTF("Read_msg failure - CTLMSG_IMG\n");
578 goto fail;
579 }
581 } else return -1;
583 return 0;
584 fail:
585 ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor);
586 return -EINVAL;
587 }
589 int map_new_blktapctrl(blkif_t *blkif)
590 {
591 DPRINTF("Received a poll for a new devmap\n");
592 if (write_msg(blkif->fds[WRITE], CTLMSG_NEWDEV, blkif, NULL) <= 0) {
593 DPRINTF("Write_msg failed - CTLMSG_NEWDEV\n");
594 return -EINVAL;
595 }
597 if (read_msg(blkif->fds[READ], CTLMSG_NEWDEV_RSP, blkif) <= 0) {
598 DPRINTF("Read_msg failed - CTLMSG_NEWDEV_RSP\n");
599 return -EINVAL;
600 }
601 DPRINTF("Exiting map_new_blktapctrl\n");
603 return blkif->minor - 1;
604 }
606 int unmap_blktapctrl(blkif_t *blkif)
607 {
608 DPRINTF("Unmapping vbd\n");
610 if (write_msg(blkif->fds[WRITE], CTLMSG_CLOSE, blkif, NULL) <= 0) {
611 DPRINTF("Write_msg failed - CTLMSG_CLOSE\n");
612 return -EINVAL;
613 }
615 if (del_disktype(blkif)) {
616 close(blkif->fds[WRITE]);
617 close(blkif->fds[READ]);
618 }
620 return 0;
621 }
623 int open_ctrl_socket(char *devname)
624 {
625 int ret;
626 int ipc_fd;
627 fd_set socks;
628 struct timeval timeout;
630 if (mkdir(BLKTAP_CTRL_DIR, 0755) == 0)
631 DPRINTF("Created %s directory\n", BLKTAP_CTRL_DIR);
632 ret = mkfifo(devname,S_IRWXU|S_IRWXG|S_IRWXO);
633 if ( (ret != 0) && (errno != EEXIST) ) {
634 DPRINTF("ERROR: pipe failed (%d)\n", errno);
635 exit(0);
636 }
638 ipc_fd = open(devname,O_RDWR|O_NONBLOCK);
640 if (ipc_fd < 0) {
641 DPRINTF("FD open failed\n");
642 return -1;
643 }
645 return ipc_fd;
646 }
648 static void print_drivers(void)
649 {
650 int i, size;
652 size = sizeof(dtypes)/sizeof(disk_info_t *);
653 DPRINTF("blktapctrl: v1.0.0\n");
654 for (i = 0; i < size; i++)
655 DPRINTF("Found driver: [%s]\n",dtypes[i]->name);
656 }
658 static void write_pidfile(long pid)
659 {
660 char buf[100];
661 int len;
662 int fd;
663 int flags;
665 fd = open(PIDFILE, O_RDWR | O_CREAT, 0600);
666 if (fd == -1) {
667 DPRINTF("Opening pid file failed (%d)\n", errno);
668 exit(1);
669 }
671 /* We exit silently if daemon already running. */
672 if (lockf(fd, F_TLOCK, 0) == -1)
673 exit(0);
675 /* Set FD_CLOEXEC, so that tapdisk doesn't get this file
676 descriptor. */
677 if ((flags = fcntl(fd, F_GETFD)) == -1) {
678 DPRINTF("F_GETFD failed (%d)\n", errno);
679 exit(1);
680 }
681 flags |= FD_CLOEXEC;
682 if (fcntl(fd, F_SETFD, flags) == -1) {
683 DPRINTF("F_SETFD failed (%d)\n", errno);
684 exit(1);
685 }
687 len = snprintf(buf, sizeof(buf), "%ld\n", pid);
688 if (write(fd, buf, len) != len) {
689 DPRINTF("Writing pid file failed (%d)\n", errno);
690 exit(1);
691 }
692 }
694 int main(int argc, char *argv[])
695 {
696 char *devname;
697 tapdev_info_t *ctlinfo;
698 int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
699 struct xs_handle *h;
700 struct pollfd pfd[NUM_POLL_FDS];
701 pid_t process;
702 char buf[128];
704 __init_blkif();
705 snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid());
706 openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON);
707 if (daemon(0,0)) {
708 DPRINTF("daemon failed (%d)\n", errno);
709 goto open_failed;
710 }
712 print_drivers();
713 init_driver_list();
714 init_rng();
716 register_new_blkif_hook(blktapctrl_new_blkif);
717 register_new_devmap_hook(map_new_blktapctrl);
718 register_new_unmap_hook(unmap_blktapctrl);
720 /* Attach to blktap0 */
721 if (asprintf(&devname,"%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME) == -1)
722 goto open_failed;
723 if ((ret = xc_find_device_number("blktap0")) < 0) {
724 DPRINTF("couldn't find device number for 'blktap0'\n");
725 goto open_failed;
726 }
727 blktap_major = major(ret);
728 make_blktap_dev(devname,blktap_major,0);
729 ctlfd = open(devname, O_RDWR);
730 if (ctlfd == -1) {
731 DPRINTF("blktap0 open failed\n");
732 goto open_failed;
733 }
736 retry:
737 /* Set up store connection and watch. */
738 h = xs_daemon_open();
739 if (h == NULL) {
740 DPRINTF("xs_daemon_open failed -- "
741 "is xenstore running?\n");
742 if (count < MAX_ATTEMPTS) {
743 count++;
744 sleep(2);
745 goto retry;
746 } else goto open_failed;
747 }
749 ret = setup_probe_watch(h);
750 if (ret != 0) {
751 DPRINTF("Failed adding device probewatch\n");
752 xs_daemon_close(h);
753 goto open_failed;
754 }
756 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
758 process = getpid();
759 write_pidfile(process);
760 ret = ioctl(ctlfd, BLKTAP_IOCTL_SENDPID, process );
762 /*Static pollhooks*/
763 pfd_count = 0;
764 tap_pfd = pfd_count++;
765 pfd[tap_pfd].fd = ctlfd;
766 pfd[tap_pfd].events = POLLIN;
768 store_pfd = pfd_count++;
769 pfd[store_pfd].fd = xs_fileno(h);
770 pfd[store_pfd].events = POLLIN;
772 while (run) {
773 timeout = 1000; /*Milliseconds*/
774 ret = poll(pfd, pfd_count, timeout);
776 if (ret > 0) {
777 if (pfd[store_pfd].revents) {
778 ret = xs_fire_next_watch(h);
779 }
780 }
781 }
783 xs_daemon_close(h);
784 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
785 close(ctlfd);
786 closelog();
788 return 0;
790 open_failed:
791 DPRINTF("Unable to start blktapctrl\n");
792 closelog();
793 return -1;
794 }
796 /*
797 * Local variables:
798 * c-file-style: "linux"
799 * indent-tabs-mode: t
800 * c-indent-level: 8
801 * c-basic-offset: 8
802 * tab-width: 8
803 * End:
804 */