ia64/xen-unstable

view tools/blktap/drivers/blktapctrl.c @ 18004:830e5d8b71da

Blktapctrl compatibility layer

I originally had just changed the NEWINTF ioctl to send over 48-bits
of information, which works on 64-bit but not on 32-bit (since the arg
is an unsigned long). Additionally, the previous changes would break
an older userland against a new kernel. For that reason, introduce a
new ioctl (NEWINTF_EXT) that fixes both of these problems. This is
the dom0 userland side.

Signed-off-by: Chris Lalancette <clalance@redhat.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Jul 09 10:41:49 2008 +0100 (2008-07-09)
parents 10e79ad54c91
children 86e3027df9d9
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 domid_translate_ext_t tr_ext;
127 int ret;
128 char *devname;
130 if (blkif->be_id >= (1<<28)) {
131 /* new-style backend-id, so use the extended structure */
132 tr_ext.domid = blkif->domid;
133 tr_ext.busid = blkif->be_id;
134 ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF_EXT, &tr_ext);
135 DPRINTF("Sent domid %d and be_id %d\n", tr_ext.domid,
136 tr_ext.busid);
137 }
138 else {
139 /* old-style backend-id; use the old structure */
140 tr.domid = blkif->domid;
141 tr.busid = (unsigned short)blkif->be_id;
142 ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF, tr);
143 DPRINTF("Sent domid %d and be_id %d\n", tr.domid, tr.busid);
144 }
146 if ( (ret <= 0)||(ret > MAX_TAP_DEV) ) {
147 DPRINTF("Incorrect Dev ID [%d]\n",ret);
148 return -1;
149 }
151 *minor = ret;
152 *major = ioctl(ctlfd, BLKTAP_IOCTL_MAJOR, ret );
153 if (*major < 0) {
154 DPRINTF("Incorrect Major ID [%d]\n",*major);
155 return -1;
156 }
158 if (asprintf(&devname,"%s/%s%d",BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, *minor) == -1)
159 return -1;
160 make_blktap_dev(devname,*major,*minor);
161 DPRINTF("Received device id %d and major %d\n",
162 *minor, *major);
163 return 0;
164 }
166 static int get_tapdisk_pid(blkif_t *blkif)
167 {
168 int ret;
170 if ((ret = write_msg(blkif->fds[WRITE], CTLMSG_PID, blkif, NULL))
171 <= 0) {
172 DPRINTF("Write_msg failed - CTLMSG_PID(%d)\n", ret);
173 return -EINVAL;
174 }
176 if ((ret = read_msg(blkif->fds[READ], CTLMSG_PID_RSP, blkif))
177 <= 0) {
178 DPRINTF("Read_msg failure - CTLMSG_PID(%d)\n", ret);
179 return -EINVAL;
180 }
181 return 1;
182 }
184 /* Look up the disk specified by path:
185 * if found, dev points to the device string in the path
186 * type is the tapdisk driver type id
187 * blkif is the existing interface if this is a shared driver
188 * and NULL otherwise.
189 * return 0 on success, -1 on error.
190 */
192 static int test_path(char *path, char **dev, int *type, blkif_t **blkif)
193 {
194 char *ptr, handle[10];
195 int i, size, found = 0;
196 size_t handle_len;
198 size = sizeof(dtypes)/sizeof(disk_info_t *);
199 *type = MAX_DISK_TYPES + 1;
200 *blkif = NULL;
202 if ( (ptr = strstr(path, ":"))!=NULL) {
203 handle_len = (ptr - path);
204 memcpy(handle, path, handle_len);
205 *dev = ptr + 1;
206 ptr = handle + handle_len;
207 *ptr = '\0';
208 DPRINTF("Detected handle: [%s]\n",handle);
210 for (i = 0; i < size; i++) {
211 if ((strlen(dtypes[i]->handle) == handle_len) &&
212 strncmp(handle, dtypes[i]->handle,
213 handle_len) == 0) {
214 found = 1;
215 }
217 if (found) {
218 *type = dtypes[i]->idnum;
220 if (dtypes[i]->single_handler == 1) {
221 /* Check whether tapdisk process
222 already exists */
223 if (active_disks[dtypes[i]->idnum] == NULL)
224 *blkif = NULL;
225 else
226 *blkif = active_disks[dtypes[i]
227 ->idnum]->blkif;
228 }
229 return 0;
230 }
231 }
232 }
234 /* Fall-through case, we didn't find a disk driver. */
235 DPRINTF("Unknown blktap disk type [%s]!\n",handle);
236 *dev = NULL;
237 return -1;
238 }
241 static void add_disktype(blkif_t *blkif, int type)
242 {
243 driver_list_entry_t *entry, **pprev;
245 if (type > MAX_DISK_TYPES)
246 return;
248 entry = malloc(sizeof(driver_list_entry_t));
249 entry->blkif = blkif;
250 entry->next = NULL;
252 pprev = &active_disks[type];
253 while (*pprev != NULL)
254 pprev = &(*pprev)->next;
256 *pprev = entry;
257 entry->pprev = pprev;
258 }
260 static int del_disktype(blkif_t *blkif)
261 {
262 driver_list_entry_t *entry, **pprev;
263 int type = blkif->drivertype, count = 0, close = 0;
265 if (type > MAX_DISK_TYPES)
266 return 1;
268 pprev = &active_disks[type];
269 while ((*pprev != NULL) && ((*pprev)->blkif != blkif))
270 pprev = &(*pprev)->next;
272 if ((entry = *pprev) == NULL) {
273 DPRINTF("DEL_DISKTYPE: No match\n");
274 return 1;
275 }
277 *pprev = entry->next;
278 if (entry->next)
279 entry->next->pprev = pprev;
281 DPRINTF("DEL_DISKTYPE: Freeing entry\n");
282 free(entry);
284 /* Caller should close() if no single controller, or list is empty. */
285 return (!dtypes[type]->single_handler || (active_disks[type] == NULL));
286 }
288 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2)
289 {
290 blkif_t *blkif;
291 blkif_info_t *blk;
292 msg_hdr_t *msg;
293 msg_newdev_t *msg_dev;
294 char *p, *buf, *path;
295 int msglen, len, ret;
296 fd_set writefds;
297 struct timeval timeout;
298 image_t *image, *img;
299 uint32_t seed;
301 blkif = (blkif_t *)ptr;
302 blk = blkif->info;
303 image = blkif->prv;
304 len = 0;
306 switch (msgtype)
307 {
308 case CTLMSG_PARAMS:
309 path = (char *)ptr2;
310 DPRINTF("Write_msg called: CTLMSG_PARAMS, sending [%s, %s]\n",
311 blk->params, path);
313 msglen = sizeof(msg_hdr_t) + strlen(path) + 1;
314 buf = malloc(msglen);
316 /*Assign header fields*/
317 msg = (msg_hdr_t *)buf;
318 msg->type = CTLMSG_PARAMS;
319 msg->len = msglen;
320 msg->drivertype = blkif->drivertype;
321 msg->readonly = blkif->readonly;
323 gettimeofday(&timeout, NULL);
324 msg->cookie = blkif->cookie;
325 DPRINTF("Generated cookie, %d\n",blkif->cookie);
327 /*Copy blk->params to msg*/
328 p = buf + sizeof(msg_hdr_t);
329 memcpy(p, path, strlen(path) + 1);
331 break;
333 case CTLMSG_NEWDEV:
334 DPRINTF("Write_msg called: CTLMSG_NEWDEV\n");
336 msglen = sizeof(msg_hdr_t) + sizeof(msg_newdev_t);
337 buf = malloc(msglen);
339 /*Assign header fields*/
340 msg = (msg_hdr_t *)buf;
341 msg->type = CTLMSG_NEWDEV;
342 msg->len = msglen;
343 msg->drivertype = blkif->drivertype;
344 msg->cookie = blkif->cookie;
346 msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t));
347 msg_dev->devnum = blkif->minor;
348 msg_dev->domid = blkif->domid;
350 break;
352 case CTLMSG_CLOSE:
353 DPRINTF("Write_msg called: CTLMSG_CLOSE\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_CLOSE;
361 msg->len = msglen;
362 msg->drivertype = blkif->drivertype;
363 msg->cookie = blkif->cookie;
365 break;
367 case CTLMSG_PID:
368 DPRINTF("Write_msg called: CTLMSG_PID\n");
370 msglen = sizeof(msg_hdr_t);
371 buf = malloc(msglen);
373 /*Assign header fields*/
374 msg = (msg_hdr_t *)buf;
375 msg->type = CTLMSG_PID;
376 msg->len = msglen;
377 msg->drivertype = blkif->drivertype;
378 msg->cookie = blkif->cookie;
380 break;
382 default:
383 return -1;
384 }
386 /*Now send the message*/
387 ret = 0;
388 FD_ZERO(&writefds);
389 FD_SET(fd,&writefds);
390 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
391 timeout.tv_usec = 0;
392 if (select(fd+1, (fd_set *) 0, &writefds,
393 (fd_set *) 0, &timeout) > 0) {
394 len = write(fd, buf, msglen);
395 if (len == -1) DPRINTF("Write failed: (%d)\n",errno);
396 }
397 free(buf);
399 return len;
400 }
402 static int read_msg(int fd, int msgtype, void *ptr)
403 {
404 blkif_t *blkif;
405 blkif_info_t *blk;
406 msg_hdr_t *msg;
407 msg_pid_t *msg_pid;
408 char *p, *buf;
409 int msglen = MSG_SIZE, len, ret;
410 fd_set readfds;
411 struct timeval timeout;
412 image_t *image, *img;
415 blkif = (blkif_t *)ptr;
416 blk = blkif->info;
417 image = blkif->prv;
419 buf = malloc(MSG_SIZE);
421 ret = 0;
422 FD_ZERO(&readfds);
423 FD_SET(fd,&readfds);
424 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
425 timeout.tv_usec = 0;
426 if (select(fd+1, &readfds, (fd_set *) 0,
427 (fd_set *) 0, &timeout) > 0) {
428 ret = read(fd, buf, msglen);
429 }
430 if (ret > 0) {
431 msg = (msg_hdr_t *)buf;
432 switch (msg->type)
433 {
434 case CTLMSG_IMG:
435 img = (image_t *)(buf + sizeof(msg_hdr_t));
436 image->size = img->size;
437 image->secsize = img->secsize;
438 image->info = img->info;
440 DPRINTF("Received CTLMSG_IMG: %llu, %lu, %u\n",
441 image->size, image->secsize, image->info);
442 if(msgtype != CTLMSG_IMG) ret = 0;
443 break;
445 case CTLMSG_IMG_FAIL:
446 DPRINTF("Received CTLMSG_IMG_FAIL, "
447 "unable to open image\n");
448 ret = 0;
449 break;
451 case CTLMSG_NEWDEV_RSP:
452 DPRINTF("Received CTLMSG_NEWDEV_RSP\n");
453 if(msgtype != CTLMSG_NEWDEV_RSP) ret = 0;
454 break;
456 case CTLMSG_NEWDEV_FAIL:
457 DPRINTF("Received CTLMSG_NEWDEV_FAIL\n");
458 ret = 0;
459 break;
461 case CTLMSG_CLOSE_RSP:
462 DPRINTF("Received CTLMSG_CLOSE_RSP\n");
463 if (msgtype != CTLMSG_CLOSE_RSP) ret = 0;
464 break;
466 case CTLMSG_PID_RSP:
467 DPRINTF("Received CTLMSG_PID_RSP\n");
468 if (msgtype != CTLMSG_PID_RSP) ret = 0;
469 else {
470 msg_pid = (msg_pid_t *)
471 (buf + sizeof(msg_hdr_t));
472 blkif->tappid = msg_pid->pid;
473 DPRINTF("\tPID: [%d]\n",blkif->tappid);
474 }
475 break;
476 default:
477 DPRINTF("UNKNOWN MESSAGE TYPE RECEIVED\n");
478 ret = 0;
479 break;
480 }
481 }
483 free(buf);
485 return ret;
487 }
489 static int launch_tapdisk_provider(char **argv)
490 {
491 pid_t child;
493 if ((child = fork()) < 0)
494 return -1;
496 if (!child) {
497 int i;
498 for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++)
499 if (i != STDIN_FILENO &&
500 i != STDOUT_FILENO &&
501 i != STDERR_FILENO)
502 close(i);
504 execvp(argv[0], argv);
505 DPRINTF("execvp failed: %d (%s)\n", errno, strerror(errno));
506 DPRINTF("PATH = %s\n", getenv("PATH"));
507 _exit(1);
508 } else {
509 pid_t got;
510 do {
511 got = waitpid(child, NULL, 0);
512 } while (got != child);
513 }
514 return child;
515 }
517 static int launch_tapdisk(char *wrctldev, char *rdctldev)
518 {
519 char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL };
521 if (launch_tapdisk_provider(argv) < 0)
522 return -1;
524 return 0;
525 }
527 static int launch_tapdisk_ioemu(void)
528 {
529 char *argv[] = { "tapdisk-ioemu", NULL };
530 return launch_tapdisk_provider(argv);
531 }
533 /*
534 * Connect to an ioemu based disk provider (qemu-dm or tapdisk-ioemu)
535 *
536 * If the domain has a device model, connect to qemu-dm through the
537 * domain specific pipe. Otherwise use a single tapdisk-ioemu instance
538 * which is represented by domid 0 and provides access for Dom0 and
539 * all DomUs without device model.
540 */
541 static int connect_qemu(blkif_t *blkif, int domid)
542 {
543 char *rdctldev, *wrctldev;
545 static int tapdisk_ioemu_pid = 0;
546 static int dom0_readfd = 0;
547 static int dom0_writefd = 0;
549 if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) < 0)
550 return -1;
552 if (asprintf(&wrctldev, BLKTAP_CTRL_DIR "/qemu-write-%d", domid) < 0) {
553 free(rdctldev);
554 return -1;
555 }
557 DPRINTF("Using qemu blktap pipe: %s\n", rdctldev);
559 if (domid == 0) {
560 /*
561 * tapdisk-ioemu exits as soon as the last image is
562 * disconnected. Check if it is still running.
563 */
564 if (tapdisk_ioemu_pid == 0 || kill(tapdisk_ioemu_pid, 0)) {
565 /* No device model and tapdisk-ioemu doesn't run yet */
566 DPRINTF("Launching tapdisk-ioemu\n");
567 tapdisk_ioemu_pid = launch_tapdisk_ioemu();
569 dom0_readfd = open_ctrl_socket(wrctldev);
570 dom0_writefd = open_ctrl_socket(rdctldev);
571 }
573 DPRINTF("Using tapdisk-ioemu connection\n");
574 blkif->fds[READ] = dom0_readfd;
575 blkif->fds[WRITE] = dom0_writefd;
576 } else if (access(rdctldev, R_OK | W_OK) == 0) {
577 /* Use existing pipe to the device model */
578 DPRINTF("Using qemu-dm connection\n");
579 blkif->fds[READ] = open_ctrl_socket(wrctldev);
580 blkif->fds[WRITE] = open_ctrl_socket(rdctldev);
581 } else {
582 /* No device model => try with tapdisk-ioemu */
583 DPRINTF("No device model\n");
584 connect_qemu(blkif, 0);
585 }
587 free(rdctldev);
588 free(wrctldev);
590 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
591 return -1;
593 DPRINTF("Attached to qemu blktap pipes\n");
594 return 0;
595 }
597 /* Launch tapdisk instance */
598 static int connect_tapdisk(blkif_t *blkif, int minor)
599 {
600 char *rdctldev = NULL, *wrctldev = NULL;
601 int ret = -1;
603 DPRINTF("tapdisk process does not exist:\n");
605 if (asprintf(&rdctldev,
606 "%s/tapctrlread%d", BLKTAP_CTRL_DIR, minor) == -1)
607 goto fail;
609 if (asprintf(&wrctldev,
610 "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, minor) == -1)
611 goto fail;
613 blkif->fds[READ] = open_ctrl_socket(rdctldev);
614 blkif->fds[WRITE] = open_ctrl_socket(wrctldev);
616 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
617 goto fail;
619 /*launch the new process*/
620 DPRINTF("Launching process, CMDLINE [tapdisk %s %s]\n",
621 wrctldev, rdctldev);
623 if (launch_tapdisk(wrctldev, rdctldev) == -1) {
624 DPRINTF("Unable to fork, cmdline: [tapdisk %s %s]\n",
625 wrctldev, rdctldev);
626 goto fail;
627 }
629 ret = 0;
631 fail:
632 if (rdctldev)
633 free(rdctldev);
635 if (wrctldev)
636 free(wrctldev);
638 return ret;
639 }
641 int blktapctrl_new_blkif(blkif_t *blkif)
642 {
643 blkif_info_t *blk;
644 int major, minor, fd_read, fd_write, type, new;
645 char *rdctldev, *wrctldev, *ptr;
646 image_t *image;
647 blkif_t *exist = NULL;
648 static uint16_t next_cookie = 0;
650 DPRINTF("Received a poll for a new vbd\n");
651 if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) {
652 if (get_new_dev(&major, &minor, blkif)<0)
653 return -1;
655 if (test_path(blk->params, &ptr, &type, &exist) != 0) {
656 DPRINTF("Error in blktap device string(%s).\n",
657 blk->params);
658 goto fail;
659 }
660 blkif->drivertype = type;
661 blkif->cookie = next_cookie++;
663 if (!exist) {
664 if (type == DISK_TYPE_IOEMU) {
665 if (connect_qemu(blkif, blkif->domid))
666 goto fail;
667 } else {
668 if (connect_tapdisk(blkif, minor))
669 goto fail;
670 }
672 } else {
673 DPRINTF("Process exists!\n");
674 blkif->fds[READ] = exist->fds[READ];
675 blkif->fds[WRITE] = exist->fds[WRITE];
676 }
678 add_disktype(blkif, type);
679 blkif->major = major;
680 blkif->minor = minor;
682 image = (image_t *)malloc(sizeof(image_t));
683 blkif->prv = (void *)image;
684 blkif->ops = &tapdisk_ops;
686 /*Retrieve the PID of the new process*/
687 if (get_tapdisk_pid(blkif) <= 0) {
688 DPRINTF("Unable to contact disk process\n");
689 goto fail;
690 }
692 /* Both of the following read and write calls will block up to
693 * max_timeout val*/
694 if (write_msg(blkif->fds[WRITE], CTLMSG_PARAMS, blkif, ptr)
695 <= 0) {
696 DPRINTF("Write_msg failed - CTLMSG_PARAMS\n");
697 goto fail;
698 }
700 if (read_msg(blkif->fds[READ], CTLMSG_IMG, blkif) <= 0) {
701 DPRINTF("Read_msg failure - CTLMSG_IMG\n");
702 goto fail;
703 }
705 } else return -1;
707 return 0;
708 fail:
709 ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor);
710 return -EINVAL;
711 }
713 int map_new_blktapctrl(blkif_t *blkif)
714 {
715 DPRINTF("Received a poll for a new devmap\n");
716 if (write_msg(blkif->fds[WRITE], CTLMSG_NEWDEV, blkif, NULL) <= 0) {
717 DPRINTF("Write_msg failed - CTLMSG_NEWDEV\n");
718 return -EINVAL;
719 }
721 if (read_msg(blkif->fds[READ], CTLMSG_NEWDEV_RSP, blkif) <= 0) {
722 DPRINTF("Read_msg failed - CTLMSG_NEWDEV_RSP\n");
723 return -EINVAL;
724 }
725 DPRINTF("Exiting map_new_blktapctrl\n");
727 return blkif->minor - 1;
728 }
730 int unmap_blktapctrl(blkif_t *blkif)
731 {
732 DPRINTF("Unmapping vbd\n");
734 if (write_msg(blkif->fds[WRITE], CTLMSG_CLOSE, blkif, NULL) <= 0) {
735 DPRINTF("Write_msg failed - CTLMSG_CLOSE\n");
736 return -EINVAL;
737 }
739 if (del_disktype(blkif)) {
740 close(blkif->fds[WRITE]);
741 close(blkif->fds[READ]);
742 }
744 return 0;
745 }
747 int open_ctrl_socket(char *devname)
748 {
749 int ret;
750 int ipc_fd;
751 fd_set socks;
752 struct timeval timeout;
754 if (mkdir(BLKTAP_CTRL_DIR, 0755) == 0)
755 DPRINTF("Created %s directory\n", BLKTAP_CTRL_DIR);
756 ret = mkfifo(devname,S_IRWXU|S_IRWXG|S_IRWXO);
757 if ( (ret != 0) && (errno != EEXIST) ) {
758 DPRINTF("ERROR: pipe failed (%d)\n", errno);
759 exit(0);
760 }
762 ipc_fd = open(devname,O_RDWR|O_NONBLOCK);
764 if (ipc_fd < 0) {
765 DPRINTF("FD open failed\n");
766 return -1;
767 }
769 return ipc_fd;
770 }
772 static void print_drivers(void)
773 {
774 int i, size;
776 size = sizeof(dtypes)/sizeof(disk_info_t *);
777 DPRINTF("blktapctrl: v1.0.0\n");
778 for (i = 0; i < size; i++)
779 DPRINTF("Found driver: [%s]\n",dtypes[i]->name);
780 }
782 static void write_pidfile(long pid)
783 {
784 char buf[100];
785 int len;
786 int fd;
787 int flags;
789 fd = open(PIDFILE, O_RDWR | O_CREAT, 0600);
790 if (fd == -1) {
791 DPRINTF("Opening pid file failed (%d)\n", errno);
792 exit(1);
793 }
795 /* We exit silently if daemon already running. */
796 if (lockf(fd, F_TLOCK, 0) == -1)
797 exit(0);
799 /* Set FD_CLOEXEC, so that tapdisk doesn't get this file
800 descriptor. */
801 if ((flags = fcntl(fd, F_GETFD)) == -1) {
802 DPRINTF("F_GETFD failed (%d)\n", errno);
803 exit(1);
804 }
805 flags |= FD_CLOEXEC;
806 if (fcntl(fd, F_SETFD, flags) == -1) {
807 DPRINTF("F_SETFD failed (%d)\n", errno);
808 exit(1);
809 }
811 len = snprintf(buf, sizeof(buf), "%ld\n", pid);
812 if (write(fd, buf, len) != len) {
813 DPRINTF("Writing pid file failed (%d)\n", errno);
814 exit(1);
815 }
816 }
818 int main(int argc, char *argv[])
819 {
820 char *devname;
821 tapdev_info_t *ctlinfo;
822 int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
823 struct xs_handle *h;
824 struct pollfd pfd[NUM_POLL_FDS];
825 pid_t process;
826 char buf[128];
828 __init_blkif();
829 snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid());
830 openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON);
831 if (daemon(0,0)) {
832 DPRINTF("daemon failed (%d)\n", errno);
833 goto open_failed;
834 }
836 print_drivers();
837 init_driver_list();
838 init_rng();
840 register_new_blkif_hook(blktapctrl_new_blkif);
841 register_new_devmap_hook(map_new_blktapctrl);
842 register_new_unmap_hook(unmap_blktapctrl);
844 /* Attach to blktap0 */
845 if (asprintf(&devname,"%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME) == -1)
846 goto open_failed;
847 if ((ret = xc_find_device_number("blktap0")) < 0) {
848 DPRINTF("couldn't find device number for 'blktap0'\n");
849 goto open_failed;
850 }
851 blktap_major = major(ret);
852 make_blktap_dev(devname,blktap_major,0);
853 ctlfd = open(devname, O_RDWR);
854 if (ctlfd == -1) {
855 DPRINTF("blktap0 open failed\n");
856 goto open_failed;
857 }
860 retry:
861 /* Set up store connection and watch. */
862 h = xs_daemon_open();
863 if (h == NULL) {
864 DPRINTF("xs_daemon_open failed -- "
865 "is xenstore running?\n");
866 if (count < MAX_ATTEMPTS) {
867 count++;
868 sleep(2);
869 goto retry;
870 } else goto open_failed;
871 }
873 ret = setup_probe_watch(h);
874 if (ret != 0) {
875 DPRINTF("Failed adding device probewatch\n");
876 xs_daemon_close(h);
877 goto open_failed;
878 }
880 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
882 process = getpid();
883 write_pidfile(process);
884 ret = ioctl(ctlfd, BLKTAP_IOCTL_SENDPID, process );
886 /*Static pollhooks*/
887 pfd_count = 0;
888 tap_pfd = pfd_count++;
889 pfd[tap_pfd].fd = ctlfd;
890 pfd[tap_pfd].events = POLLIN;
892 store_pfd = pfd_count++;
893 pfd[store_pfd].fd = xs_fileno(h);
894 pfd[store_pfd].events = POLLIN;
896 while (run) {
897 timeout = 1000; /*Milliseconds*/
898 ret = poll(pfd, pfd_count, timeout);
900 if (ret > 0) {
901 if (pfd[store_pfd].revents) {
902 ret = xs_fire_next_watch(h);
903 }
904 }
905 }
907 xs_daemon_close(h);
908 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
909 close(ctlfd);
910 closelog();
912 return 0;
914 open_failed:
915 DPRINTF("Unable to start blktapctrl\n");
916 closelog();
917 return -1;
918 }
920 /*
921 * Local variables:
922 * c-file-style: "linux"
923 * indent-tabs-mode: t
924 * c-indent-level: 8
925 * c-basic-offset: 8
926 * tab-width: 8
927 * End:
928 */