ia64/xen-unstable

view tools/blktap/drivers/blktapctrl.c @ 17916:10e79ad54c91

blktap: Extend userland busid to 32 bits

Signed-off-by: Chris Lalancette <clalance@redhat.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 27 16:08:56 2008 +0100 (2008-06-27)
parents 2bc699de2297
children 830e5d8b71da
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 = 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;
184 size_t handle_len;
186 size = sizeof(dtypes)/sizeof(disk_info_t *);
187 *type = MAX_DISK_TYPES + 1;
188 *blkif = NULL;
190 if ( (ptr = strstr(path, ":"))!=NULL) {
191 handle_len = (ptr - path);
192 memcpy(handle, path, handle_len);
193 *dev = ptr + 1;
194 ptr = handle + handle_len;
195 *ptr = '\0';
196 DPRINTF("Detected handle: [%s]\n",handle);
198 for (i = 0; i < size; i++) {
199 if ((strlen(dtypes[i]->handle) == handle_len) &&
200 strncmp(handle, dtypes[i]->handle,
201 handle_len) == 0) {
202 found = 1;
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 }
220 }
222 /* Fall-through case, we didn't find a disk driver. */
223 DPRINTF("Unknown blktap disk type [%s]!\n",handle);
224 *dev = NULL;
225 return -1;
226 }
229 static void add_disktype(blkif_t *blkif, int type)
230 {
231 driver_list_entry_t *entry, **pprev;
233 if (type > MAX_DISK_TYPES)
234 return;
236 entry = malloc(sizeof(driver_list_entry_t));
237 entry->blkif = blkif;
238 entry->next = NULL;
240 pprev = &active_disks[type];
241 while (*pprev != NULL)
242 pprev = &(*pprev)->next;
244 *pprev = entry;
245 entry->pprev = pprev;
246 }
248 static int del_disktype(blkif_t *blkif)
249 {
250 driver_list_entry_t *entry, **pprev;
251 int type = blkif->drivertype, count = 0, close = 0;
253 if (type > MAX_DISK_TYPES)
254 return 1;
256 pprev = &active_disks[type];
257 while ((*pprev != NULL) && ((*pprev)->blkif != blkif))
258 pprev = &(*pprev)->next;
260 if ((entry = *pprev) == NULL) {
261 DPRINTF("DEL_DISKTYPE: No match\n");
262 return 1;
263 }
265 *pprev = entry->next;
266 if (entry->next)
267 entry->next->pprev = pprev;
269 DPRINTF("DEL_DISKTYPE: Freeing entry\n");
270 free(entry);
272 /* Caller should close() if no single controller, or list is empty. */
273 return (!dtypes[type]->single_handler || (active_disks[type] == NULL));
274 }
276 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2)
277 {
278 blkif_t *blkif;
279 blkif_info_t *blk;
280 msg_hdr_t *msg;
281 msg_newdev_t *msg_dev;
282 char *p, *buf, *path;
283 int msglen, len, ret;
284 fd_set writefds;
285 struct timeval timeout;
286 image_t *image, *img;
287 uint32_t seed;
289 blkif = (blkif_t *)ptr;
290 blk = blkif->info;
291 image = blkif->prv;
292 len = 0;
294 switch (msgtype)
295 {
296 case CTLMSG_PARAMS:
297 path = (char *)ptr2;
298 DPRINTF("Write_msg called: CTLMSG_PARAMS, sending [%s, %s]\n",
299 blk->params, path);
301 msglen = sizeof(msg_hdr_t) + strlen(path) + 1;
302 buf = malloc(msglen);
304 /*Assign header fields*/
305 msg = (msg_hdr_t *)buf;
306 msg->type = CTLMSG_PARAMS;
307 msg->len = msglen;
308 msg->drivertype = blkif->drivertype;
309 msg->readonly = blkif->readonly;
311 gettimeofday(&timeout, NULL);
312 msg->cookie = blkif->cookie;
313 DPRINTF("Generated cookie, %d\n",blkif->cookie);
315 /*Copy blk->params to msg*/
316 p = buf + sizeof(msg_hdr_t);
317 memcpy(p, path, strlen(path) + 1);
319 break;
321 case CTLMSG_NEWDEV:
322 DPRINTF("Write_msg called: CTLMSG_NEWDEV\n");
324 msglen = sizeof(msg_hdr_t) + sizeof(msg_newdev_t);
325 buf = malloc(msglen);
327 /*Assign header fields*/
328 msg = (msg_hdr_t *)buf;
329 msg->type = CTLMSG_NEWDEV;
330 msg->len = msglen;
331 msg->drivertype = blkif->drivertype;
332 msg->cookie = blkif->cookie;
334 msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t));
335 msg_dev->devnum = blkif->minor;
336 msg_dev->domid = blkif->domid;
338 break;
340 case CTLMSG_CLOSE:
341 DPRINTF("Write_msg called: CTLMSG_CLOSE\n");
343 msglen = sizeof(msg_hdr_t);
344 buf = malloc(msglen);
346 /*Assign header fields*/
347 msg = (msg_hdr_t *)buf;
348 msg->type = CTLMSG_CLOSE;
349 msg->len = msglen;
350 msg->drivertype = blkif->drivertype;
351 msg->cookie = blkif->cookie;
353 break;
355 case CTLMSG_PID:
356 DPRINTF("Write_msg called: CTLMSG_PID\n");
358 msglen = sizeof(msg_hdr_t);
359 buf = malloc(msglen);
361 /*Assign header fields*/
362 msg = (msg_hdr_t *)buf;
363 msg->type = CTLMSG_PID;
364 msg->len = msglen;
365 msg->drivertype = blkif->drivertype;
366 msg->cookie = blkif->cookie;
368 break;
370 default:
371 return -1;
372 }
374 /*Now send the message*/
375 ret = 0;
376 FD_ZERO(&writefds);
377 FD_SET(fd,&writefds);
378 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
379 timeout.tv_usec = 0;
380 if (select(fd+1, (fd_set *) 0, &writefds,
381 (fd_set *) 0, &timeout) > 0) {
382 len = write(fd, buf, msglen);
383 if (len == -1) DPRINTF("Write failed: (%d)\n",errno);
384 }
385 free(buf);
387 return len;
388 }
390 static int read_msg(int fd, int msgtype, void *ptr)
391 {
392 blkif_t *blkif;
393 blkif_info_t *blk;
394 msg_hdr_t *msg;
395 msg_pid_t *msg_pid;
396 char *p, *buf;
397 int msglen = MSG_SIZE, len, ret;
398 fd_set readfds;
399 struct timeval timeout;
400 image_t *image, *img;
403 blkif = (blkif_t *)ptr;
404 blk = blkif->info;
405 image = blkif->prv;
407 buf = malloc(MSG_SIZE);
409 ret = 0;
410 FD_ZERO(&readfds);
411 FD_SET(fd,&readfds);
412 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
413 timeout.tv_usec = 0;
414 if (select(fd+1, &readfds, (fd_set *) 0,
415 (fd_set *) 0, &timeout) > 0) {
416 ret = read(fd, buf, msglen);
417 }
418 if (ret > 0) {
419 msg = (msg_hdr_t *)buf;
420 switch (msg->type)
421 {
422 case CTLMSG_IMG:
423 img = (image_t *)(buf + sizeof(msg_hdr_t));
424 image->size = img->size;
425 image->secsize = img->secsize;
426 image->info = img->info;
428 DPRINTF("Received CTLMSG_IMG: %llu, %lu, %u\n",
429 image->size, image->secsize, image->info);
430 if(msgtype != CTLMSG_IMG) ret = 0;
431 break;
433 case CTLMSG_IMG_FAIL:
434 DPRINTF("Received CTLMSG_IMG_FAIL, "
435 "unable to open image\n");
436 ret = 0;
437 break;
439 case CTLMSG_NEWDEV_RSP:
440 DPRINTF("Received CTLMSG_NEWDEV_RSP\n");
441 if(msgtype != CTLMSG_NEWDEV_RSP) ret = 0;
442 break;
444 case CTLMSG_NEWDEV_FAIL:
445 DPRINTF("Received CTLMSG_NEWDEV_FAIL\n");
446 ret = 0;
447 break;
449 case CTLMSG_CLOSE_RSP:
450 DPRINTF("Received CTLMSG_CLOSE_RSP\n");
451 if (msgtype != CTLMSG_CLOSE_RSP) ret = 0;
452 break;
454 case CTLMSG_PID_RSP:
455 DPRINTF("Received CTLMSG_PID_RSP\n");
456 if (msgtype != CTLMSG_PID_RSP) ret = 0;
457 else {
458 msg_pid = (msg_pid_t *)
459 (buf + sizeof(msg_hdr_t));
460 blkif->tappid = msg_pid->pid;
461 DPRINTF("\tPID: [%d]\n",blkif->tappid);
462 }
463 break;
464 default:
465 DPRINTF("UNKNOWN MESSAGE TYPE RECEIVED\n");
466 ret = 0;
467 break;
468 }
469 }
471 free(buf);
473 return ret;
475 }
477 static int launch_tapdisk_provider(char **argv)
478 {
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(argv[0], argv);
493 DPRINTF("execvp failed: %d (%s)\n", errno, strerror(errno));
494 DPRINTF("PATH = %s\n", getenv("PATH"));
495 _exit(1);
496 } else {
497 pid_t got;
498 do {
499 got = waitpid(child, NULL, 0);
500 } while (got != child);
501 }
502 return child;
503 }
505 static int launch_tapdisk(char *wrctldev, char *rdctldev)
506 {
507 char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL };
509 if (launch_tapdisk_provider(argv) < 0)
510 return -1;
512 return 0;
513 }
515 static int launch_tapdisk_ioemu(void)
516 {
517 char *argv[] = { "tapdisk-ioemu", NULL };
518 return launch_tapdisk_provider(argv);
519 }
521 /*
522 * Connect to an ioemu based disk provider (qemu-dm or tapdisk-ioemu)
523 *
524 * If the domain has a device model, connect to qemu-dm through the
525 * domain specific pipe. Otherwise use a single tapdisk-ioemu instance
526 * which is represented by domid 0 and provides access for Dom0 and
527 * all DomUs without device model.
528 */
529 static int connect_qemu(blkif_t *blkif, int domid)
530 {
531 char *rdctldev, *wrctldev;
533 static int tapdisk_ioemu_pid = 0;
534 static int dom0_readfd = 0;
535 static int dom0_writefd = 0;
537 if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) < 0)
538 return -1;
540 if (asprintf(&wrctldev, BLKTAP_CTRL_DIR "/qemu-write-%d", domid) < 0) {
541 free(rdctldev);
542 return -1;
543 }
545 DPRINTF("Using qemu blktap pipe: %s\n", rdctldev);
547 if (domid == 0) {
548 /*
549 * tapdisk-ioemu exits as soon as the last image is
550 * disconnected. Check if it is still running.
551 */
552 if (tapdisk_ioemu_pid == 0 || kill(tapdisk_ioemu_pid, 0)) {
553 /* No device model and tapdisk-ioemu doesn't run yet */
554 DPRINTF("Launching tapdisk-ioemu\n");
555 tapdisk_ioemu_pid = launch_tapdisk_ioemu();
557 dom0_readfd = open_ctrl_socket(wrctldev);
558 dom0_writefd = open_ctrl_socket(rdctldev);
559 }
561 DPRINTF("Using tapdisk-ioemu connection\n");
562 blkif->fds[READ] = dom0_readfd;
563 blkif->fds[WRITE] = dom0_writefd;
564 } else if (access(rdctldev, R_OK | W_OK) == 0) {
565 /* Use existing pipe to the device model */
566 DPRINTF("Using qemu-dm connection\n");
567 blkif->fds[READ] = open_ctrl_socket(wrctldev);
568 blkif->fds[WRITE] = open_ctrl_socket(rdctldev);
569 } else {
570 /* No device model => try with tapdisk-ioemu */
571 DPRINTF("No device model\n");
572 connect_qemu(blkif, 0);
573 }
575 free(rdctldev);
576 free(wrctldev);
578 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
579 return -1;
581 DPRINTF("Attached to qemu blktap pipes\n");
582 return 0;
583 }
585 /* Launch tapdisk instance */
586 static int connect_tapdisk(blkif_t *blkif, int minor)
587 {
588 char *rdctldev = NULL, *wrctldev = NULL;
589 int ret = -1;
591 DPRINTF("tapdisk process does not exist:\n");
593 if (asprintf(&rdctldev,
594 "%s/tapctrlread%d", BLKTAP_CTRL_DIR, minor) == -1)
595 goto fail;
597 if (asprintf(&wrctldev,
598 "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, minor) == -1)
599 goto fail;
601 blkif->fds[READ] = open_ctrl_socket(rdctldev);
602 blkif->fds[WRITE] = open_ctrl_socket(wrctldev);
604 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
605 goto fail;
607 /*launch the new process*/
608 DPRINTF("Launching process, CMDLINE [tapdisk %s %s]\n",
609 wrctldev, rdctldev);
611 if (launch_tapdisk(wrctldev, rdctldev) == -1) {
612 DPRINTF("Unable to fork, cmdline: [tapdisk %s %s]\n",
613 wrctldev, rdctldev);
614 goto fail;
615 }
617 ret = 0;
619 fail:
620 if (rdctldev)
621 free(rdctldev);
623 if (wrctldev)
624 free(wrctldev);
626 return ret;
627 }
629 int blktapctrl_new_blkif(blkif_t *blkif)
630 {
631 blkif_info_t *blk;
632 int major, minor, fd_read, fd_write, type, new;
633 char *rdctldev, *wrctldev, *ptr;
634 image_t *image;
635 blkif_t *exist = NULL;
636 static uint16_t next_cookie = 0;
638 DPRINTF("Received a poll for a new vbd\n");
639 if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) {
640 if (get_new_dev(&major, &minor, blkif)<0)
641 return -1;
643 if (test_path(blk->params, &ptr, &type, &exist) != 0) {
644 DPRINTF("Error in blktap device string(%s).\n",
645 blk->params);
646 goto fail;
647 }
648 blkif->drivertype = type;
649 blkif->cookie = next_cookie++;
651 if (!exist) {
652 if (type == DISK_TYPE_IOEMU) {
653 if (connect_qemu(blkif, blkif->domid))
654 goto fail;
655 } else {
656 if (connect_tapdisk(blkif, minor))
657 goto fail;
658 }
660 } else {
661 DPRINTF("Process exists!\n");
662 blkif->fds[READ] = exist->fds[READ];
663 blkif->fds[WRITE] = exist->fds[WRITE];
664 }
666 add_disktype(blkif, type);
667 blkif->major = major;
668 blkif->minor = minor;
670 image = (image_t *)malloc(sizeof(image_t));
671 blkif->prv = (void *)image;
672 blkif->ops = &tapdisk_ops;
674 /*Retrieve the PID of the new process*/
675 if (get_tapdisk_pid(blkif) <= 0) {
676 DPRINTF("Unable to contact disk process\n");
677 goto fail;
678 }
680 /* Both of the following read and write calls will block up to
681 * max_timeout val*/
682 if (write_msg(blkif->fds[WRITE], CTLMSG_PARAMS, blkif, ptr)
683 <= 0) {
684 DPRINTF("Write_msg failed - CTLMSG_PARAMS\n");
685 goto fail;
686 }
688 if (read_msg(blkif->fds[READ], CTLMSG_IMG, blkif) <= 0) {
689 DPRINTF("Read_msg failure - CTLMSG_IMG\n");
690 goto fail;
691 }
693 } else return -1;
695 return 0;
696 fail:
697 ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor);
698 return -EINVAL;
699 }
701 int map_new_blktapctrl(blkif_t *blkif)
702 {
703 DPRINTF("Received a poll for a new devmap\n");
704 if (write_msg(blkif->fds[WRITE], CTLMSG_NEWDEV, blkif, NULL) <= 0) {
705 DPRINTF("Write_msg failed - CTLMSG_NEWDEV\n");
706 return -EINVAL;
707 }
709 if (read_msg(blkif->fds[READ], CTLMSG_NEWDEV_RSP, blkif) <= 0) {
710 DPRINTF("Read_msg failed - CTLMSG_NEWDEV_RSP\n");
711 return -EINVAL;
712 }
713 DPRINTF("Exiting map_new_blktapctrl\n");
715 return blkif->minor - 1;
716 }
718 int unmap_blktapctrl(blkif_t *blkif)
719 {
720 DPRINTF("Unmapping vbd\n");
722 if (write_msg(blkif->fds[WRITE], CTLMSG_CLOSE, blkif, NULL) <= 0) {
723 DPRINTF("Write_msg failed - CTLMSG_CLOSE\n");
724 return -EINVAL;
725 }
727 if (del_disktype(blkif)) {
728 close(blkif->fds[WRITE]);
729 close(blkif->fds[READ]);
730 }
732 return 0;
733 }
735 int open_ctrl_socket(char *devname)
736 {
737 int ret;
738 int ipc_fd;
739 fd_set socks;
740 struct timeval timeout;
742 if (mkdir(BLKTAP_CTRL_DIR, 0755) == 0)
743 DPRINTF("Created %s directory\n", BLKTAP_CTRL_DIR);
744 ret = mkfifo(devname,S_IRWXU|S_IRWXG|S_IRWXO);
745 if ( (ret != 0) && (errno != EEXIST) ) {
746 DPRINTF("ERROR: pipe failed (%d)\n", errno);
747 exit(0);
748 }
750 ipc_fd = open(devname,O_RDWR|O_NONBLOCK);
752 if (ipc_fd < 0) {
753 DPRINTF("FD open failed\n");
754 return -1;
755 }
757 return ipc_fd;
758 }
760 static void print_drivers(void)
761 {
762 int i, size;
764 size = sizeof(dtypes)/sizeof(disk_info_t *);
765 DPRINTF("blktapctrl: v1.0.0\n");
766 for (i = 0; i < size; i++)
767 DPRINTF("Found driver: [%s]\n",dtypes[i]->name);
768 }
770 static void write_pidfile(long pid)
771 {
772 char buf[100];
773 int len;
774 int fd;
775 int flags;
777 fd = open(PIDFILE, O_RDWR | O_CREAT, 0600);
778 if (fd == -1) {
779 DPRINTF("Opening pid file failed (%d)\n", errno);
780 exit(1);
781 }
783 /* We exit silently if daemon already running. */
784 if (lockf(fd, F_TLOCK, 0) == -1)
785 exit(0);
787 /* Set FD_CLOEXEC, so that tapdisk doesn't get this file
788 descriptor. */
789 if ((flags = fcntl(fd, F_GETFD)) == -1) {
790 DPRINTF("F_GETFD failed (%d)\n", errno);
791 exit(1);
792 }
793 flags |= FD_CLOEXEC;
794 if (fcntl(fd, F_SETFD, flags) == -1) {
795 DPRINTF("F_SETFD failed (%d)\n", errno);
796 exit(1);
797 }
799 len = snprintf(buf, sizeof(buf), "%ld\n", pid);
800 if (write(fd, buf, len) != len) {
801 DPRINTF("Writing pid file failed (%d)\n", errno);
802 exit(1);
803 }
804 }
806 int main(int argc, char *argv[])
807 {
808 char *devname;
809 tapdev_info_t *ctlinfo;
810 int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
811 struct xs_handle *h;
812 struct pollfd pfd[NUM_POLL_FDS];
813 pid_t process;
814 char buf[128];
816 __init_blkif();
817 snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid());
818 openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON);
819 if (daemon(0,0)) {
820 DPRINTF("daemon failed (%d)\n", errno);
821 goto open_failed;
822 }
824 print_drivers();
825 init_driver_list();
826 init_rng();
828 register_new_blkif_hook(blktapctrl_new_blkif);
829 register_new_devmap_hook(map_new_blktapctrl);
830 register_new_unmap_hook(unmap_blktapctrl);
832 /* Attach to blktap0 */
833 if (asprintf(&devname,"%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME) == -1)
834 goto open_failed;
835 if ((ret = xc_find_device_number("blktap0")) < 0) {
836 DPRINTF("couldn't find device number for 'blktap0'\n");
837 goto open_failed;
838 }
839 blktap_major = major(ret);
840 make_blktap_dev(devname,blktap_major,0);
841 ctlfd = open(devname, O_RDWR);
842 if (ctlfd == -1) {
843 DPRINTF("blktap0 open failed\n");
844 goto open_failed;
845 }
848 retry:
849 /* Set up store connection and watch. */
850 h = xs_daemon_open();
851 if (h == NULL) {
852 DPRINTF("xs_daemon_open failed -- "
853 "is xenstore running?\n");
854 if (count < MAX_ATTEMPTS) {
855 count++;
856 sleep(2);
857 goto retry;
858 } else goto open_failed;
859 }
861 ret = setup_probe_watch(h);
862 if (ret != 0) {
863 DPRINTF("Failed adding device probewatch\n");
864 xs_daemon_close(h);
865 goto open_failed;
866 }
868 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
870 process = getpid();
871 write_pidfile(process);
872 ret = ioctl(ctlfd, BLKTAP_IOCTL_SENDPID, process );
874 /*Static pollhooks*/
875 pfd_count = 0;
876 tap_pfd = pfd_count++;
877 pfd[tap_pfd].fd = ctlfd;
878 pfd[tap_pfd].events = POLLIN;
880 store_pfd = pfd_count++;
881 pfd[store_pfd].fd = xs_fileno(h);
882 pfd[store_pfd].events = POLLIN;
884 while (run) {
885 timeout = 1000; /*Milliseconds*/
886 ret = poll(pfd, pfd_count, timeout);
888 if (ret > 0) {
889 if (pfd[store_pfd].revents) {
890 ret = xs_fire_next_watch(h);
891 }
892 }
893 }
895 xs_daemon_close(h);
896 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
897 close(ctlfd);
898 closelog();
900 return 0;
902 open_failed:
903 DPRINTF("Unable to start blktapctrl\n");
904 closelog();
905 return -1;
906 }
908 /*
909 * Local variables:
910 * c-file-style: "linux"
911 * indent-tabs-mode: t
912 * c-indent-level: 8
913 * c-basic-offset: 8
914 * tab-width: 8
915 * End:
916 */