ia64/xen-unstable

view tools/blktap/drivers/blktapctrl.c @ 18041:86e3027df9d9

blktap: cleanup

Make functions w/o a prototype static and remove redundant
declaration of xs_fire_next_watch().

Signed-off-by: Christoph Egger <Christoph.Egger@amd.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jul 11 15:36:40 2008 +0100 (2008-07-11)
parents 830e5d8b71da
children b01303f59872
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"
58 #include "list.h"
59 #include "xs_api.h" /* for xs_fire_next_watch() */
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 domid_translate_ext_t tr_ext;
129 int ret;
130 char *devname;
132 if (blkif->be_id >= (1<<28)) {
133 /* new-style backend-id, so use the extended structure */
134 tr_ext.domid = blkif->domid;
135 tr_ext.busid = blkif->be_id;
136 ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF_EXT, &tr_ext);
137 DPRINTF("Sent domid %d and be_id %d\n", tr_ext.domid,
138 tr_ext.busid);
139 }
140 else {
141 /* old-style backend-id; use the old structure */
142 tr.domid = blkif->domid;
143 tr.busid = (unsigned short)blkif->be_id;
144 ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF, tr);
145 DPRINTF("Sent domid %d and be_id %d\n", tr.domid, tr.busid);
146 }
148 if ( (ret <= 0)||(ret > MAX_TAP_DEV) ) {
149 DPRINTF("Incorrect Dev ID [%d]\n",ret);
150 return -1;
151 }
153 *minor = ret;
154 *major = ioctl(ctlfd, BLKTAP_IOCTL_MAJOR, ret );
155 if (*major < 0) {
156 DPRINTF("Incorrect Major ID [%d]\n",*major);
157 return -1;
158 }
160 if (asprintf(&devname,"%s/%s%d",BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, *minor) == -1)
161 return -1;
162 make_blktap_dev(devname,*major,*minor);
163 DPRINTF("Received device id %d and major %d\n",
164 *minor, *major);
165 return 0;
166 }
168 static int get_tapdisk_pid(blkif_t *blkif)
169 {
170 int ret;
172 if ((ret = write_msg(blkif->fds[WRITE], CTLMSG_PID, blkif, NULL))
173 <= 0) {
174 DPRINTF("Write_msg failed - CTLMSG_PID(%d)\n", ret);
175 return -EINVAL;
176 }
178 if ((ret = read_msg(blkif->fds[READ], CTLMSG_PID_RSP, blkif))
179 <= 0) {
180 DPRINTF("Read_msg failure - CTLMSG_PID(%d)\n", ret);
181 return -EINVAL;
182 }
183 return 1;
184 }
186 /* Look up the disk specified by path:
187 * if found, dev points to the device string in the path
188 * type is the tapdisk driver type id
189 * blkif is the existing interface if this is a shared driver
190 * and NULL otherwise.
191 * return 0 on success, -1 on error.
192 */
194 static int test_path(char *path, char **dev, int *type, blkif_t **blkif)
195 {
196 char *ptr, handle[10];
197 int i, size, found = 0;
198 size_t handle_len;
200 size = sizeof(dtypes)/sizeof(disk_info_t *);
201 *type = MAX_DISK_TYPES + 1;
202 *blkif = NULL;
204 if ( (ptr = strstr(path, ":"))!=NULL) {
205 handle_len = (ptr - path);
206 memcpy(handle, path, handle_len);
207 *dev = ptr + 1;
208 ptr = handle + handle_len;
209 *ptr = '\0';
210 DPRINTF("Detected handle: [%s]\n",handle);
212 for (i = 0; i < size; i++) {
213 if ((strlen(dtypes[i]->handle) == handle_len) &&
214 strncmp(handle, dtypes[i]->handle,
215 handle_len) == 0) {
216 found = 1;
217 }
219 if (found) {
220 *type = dtypes[i]->idnum;
222 if (dtypes[i]->single_handler == 1) {
223 /* Check whether tapdisk process
224 already exists */
225 if (active_disks[dtypes[i]->idnum] == NULL)
226 *blkif = NULL;
227 else
228 *blkif = active_disks[dtypes[i]
229 ->idnum]->blkif;
230 }
231 return 0;
232 }
233 }
234 }
236 /* Fall-through case, we didn't find a disk driver. */
237 DPRINTF("Unknown blktap disk type [%s]!\n",handle);
238 *dev = NULL;
239 return -1;
240 }
243 static void add_disktype(blkif_t *blkif, int type)
244 {
245 driver_list_entry_t *entry, **pprev;
247 if (type > MAX_DISK_TYPES)
248 return;
250 entry = malloc(sizeof(driver_list_entry_t));
251 entry->blkif = blkif;
252 entry->next = NULL;
254 pprev = &active_disks[type];
255 while (*pprev != NULL)
256 pprev = &(*pprev)->next;
258 *pprev = entry;
259 entry->pprev = pprev;
260 }
262 static int del_disktype(blkif_t *blkif)
263 {
264 driver_list_entry_t *entry, **pprev;
265 int type = blkif->drivertype, count = 0, close = 0;
267 if (type > MAX_DISK_TYPES)
268 return 1;
270 pprev = &active_disks[type];
271 while ((*pprev != NULL) && ((*pprev)->blkif != blkif))
272 pprev = &(*pprev)->next;
274 if ((entry = *pprev) == NULL) {
275 DPRINTF("DEL_DISKTYPE: No match\n");
276 return 1;
277 }
279 *pprev = entry->next;
280 if (entry->next)
281 entry->next->pprev = pprev;
283 DPRINTF("DEL_DISKTYPE: Freeing entry\n");
284 free(entry);
286 /* Caller should close() if no single controller, or list is empty. */
287 return (!dtypes[type]->single_handler || (active_disks[type] == NULL));
288 }
290 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2)
291 {
292 blkif_t *blkif;
293 blkif_info_t *blk;
294 msg_hdr_t *msg;
295 msg_newdev_t *msg_dev;
296 char *p, *buf, *path;
297 int msglen, len, ret;
298 fd_set writefds;
299 struct timeval timeout;
300 image_t *image, *img;
301 uint32_t seed;
303 blkif = (blkif_t *)ptr;
304 blk = blkif->info;
305 image = blkif->prv;
306 len = 0;
308 switch (msgtype)
309 {
310 case CTLMSG_PARAMS:
311 path = (char *)ptr2;
312 DPRINTF("Write_msg called: CTLMSG_PARAMS, sending [%s, %s]\n",
313 blk->params, path);
315 msglen = sizeof(msg_hdr_t) + strlen(path) + 1;
316 buf = malloc(msglen);
318 /*Assign header fields*/
319 msg = (msg_hdr_t *)buf;
320 msg->type = CTLMSG_PARAMS;
321 msg->len = msglen;
322 msg->drivertype = blkif->drivertype;
323 msg->readonly = blkif->readonly;
325 gettimeofday(&timeout, NULL);
326 msg->cookie = blkif->cookie;
327 DPRINTF("Generated cookie, %d\n",blkif->cookie);
329 /*Copy blk->params to msg*/
330 p = buf + sizeof(msg_hdr_t);
331 memcpy(p, path, strlen(path) + 1);
333 break;
335 case CTLMSG_NEWDEV:
336 DPRINTF("Write_msg called: CTLMSG_NEWDEV\n");
338 msglen = sizeof(msg_hdr_t) + sizeof(msg_newdev_t);
339 buf = malloc(msglen);
341 /*Assign header fields*/
342 msg = (msg_hdr_t *)buf;
343 msg->type = CTLMSG_NEWDEV;
344 msg->len = msglen;
345 msg->drivertype = blkif->drivertype;
346 msg->cookie = blkif->cookie;
348 msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t));
349 msg_dev->devnum = blkif->minor;
350 msg_dev->domid = blkif->domid;
352 break;
354 case CTLMSG_CLOSE:
355 DPRINTF("Write_msg called: CTLMSG_CLOSE\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_CLOSE;
363 msg->len = msglen;
364 msg->drivertype = blkif->drivertype;
365 msg->cookie = blkif->cookie;
367 break;
369 case CTLMSG_PID:
370 DPRINTF("Write_msg called: CTLMSG_PID\n");
372 msglen = sizeof(msg_hdr_t);
373 buf = malloc(msglen);
375 /*Assign header fields*/
376 msg = (msg_hdr_t *)buf;
377 msg->type = CTLMSG_PID;
378 msg->len = msglen;
379 msg->drivertype = blkif->drivertype;
380 msg->cookie = blkif->cookie;
382 break;
384 default:
385 return -1;
386 }
388 /*Now send the message*/
389 ret = 0;
390 FD_ZERO(&writefds);
391 FD_SET(fd,&writefds);
392 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
393 timeout.tv_usec = 0;
394 if (select(fd+1, (fd_set *) 0, &writefds,
395 (fd_set *) 0, &timeout) > 0) {
396 len = write(fd, buf, msglen);
397 if (len == -1) DPRINTF("Write failed: (%d)\n",errno);
398 }
399 free(buf);
401 return len;
402 }
404 static int read_msg(int fd, int msgtype, void *ptr)
405 {
406 blkif_t *blkif;
407 blkif_info_t *blk;
408 msg_hdr_t *msg;
409 msg_pid_t *msg_pid;
410 char *p, *buf;
411 int msglen = MSG_SIZE, len, ret;
412 fd_set readfds;
413 struct timeval timeout;
414 image_t *image, *img;
417 blkif = (blkif_t *)ptr;
418 blk = blkif->info;
419 image = blkif->prv;
421 buf = malloc(MSG_SIZE);
423 ret = 0;
424 FD_ZERO(&readfds);
425 FD_SET(fd,&readfds);
426 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
427 timeout.tv_usec = 0;
428 if (select(fd+1, &readfds, (fd_set *) 0,
429 (fd_set *) 0, &timeout) > 0) {
430 ret = read(fd, buf, msglen);
431 }
432 if (ret > 0) {
433 msg = (msg_hdr_t *)buf;
434 switch (msg->type)
435 {
436 case CTLMSG_IMG:
437 img = (image_t *)(buf + sizeof(msg_hdr_t));
438 image->size = img->size;
439 image->secsize = img->secsize;
440 image->info = img->info;
442 DPRINTF("Received CTLMSG_IMG: %llu, %lu, %u\n",
443 image->size, image->secsize, image->info);
444 if(msgtype != CTLMSG_IMG) ret = 0;
445 break;
447 case CTLMSG_IMG_FAIL:
448 DPRINTF("Received CTLMSG_IMG_FAIL, "
449 "unable to open image\n");
450 ret = 0;
451 break;
453 case CTLMSG_NEWDEV_RSP:
454 DPRINTF("Received CTLMSG_NEWDEV_RSP\n");
455 if(msgtype != CTLMSG_NEWDEV_RSP) ret = 0;
456 break;
458 case CTLMSG_NEWDEV_FAIL:
459 DPRINTF("Received CTLMSG_NEWDEV_FAIL\n");
460 ret = 0;
461 break;
463 case CTLMSG_CLOSE_RSP:
464 DPRINTF("Received CTLMSG_CLOSE_RSP\n");
465 if (msgtype != CTLMSG_CLOSE_RSP) ret = 0;
466 break;
468 case CTLMSG_PID_RSP:
469 DPRINTF("Received CTLMSG_PID_RSP\n");
470 if (msgtype != CTLMSG_PID_RSP) ret = 0;
471 else {
472 msg_pid = (msg_pid_t *)
473 (buf + sizeof(msg_hdr_t));
474 blkif->tappid = msg_pid->pid;
475 DPRINTF("\tPID: [%d]\n",blkif->tappid);
476 }
477 break;
478 default:
479 DPRINTF("UNKNOWN MESSAGE TYPE RECEIVED\n");
480 ret = 0;
481 break;
482 }
483 }
485 free(buf);
487 return ret;
489 }
491 static int launch_tapdisk_provider(char **argv)
492 {
493 pid_t child;
495 if ((child = fork()) < 0)
496 return -1;
498 if (!child) {
499 int i;
500 for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++)
501 if (i != STDIN_FILENO &&
502 i != STDOUT_FILENO &&
503 i != STDERR_FILENO)
504 close(i);
506 execvp(argv[0], argv);
507 DPRINTF("execvp failed: %d (%s)\n", errno, strerror(errno));
508 DPRINTF("PATH = %s\n", getenv("PATH"));
509 _exit(1);
510 } else {
511 pid_t got;
512 do {
513 got = waitpid(child, NULL, 0);
514 } while (got != child);
515 }
516 return child;
517 }
519 static int launch_tapdisk(char *wrctldev, char *rdctldev)
520 {
521 char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL };
523 if (launch_tapdisk_provider(argv) < 0)
524 return -1;
526 return 0;
527 }
529 static int launch_tapdisk_ioemu(void)
530 {
531 char *argv[] = { "tapdisk-ioemu", NULL };
532 return launch_tapdisk_provider(argv);
533 }
535 /*
536 * Connect to an ioemu based disk provider (qemu-dm or tapdisk-ioemu)
537 *
538 * If the domain has a device model, connect to qemu-dm through the
539 * domain specific pipe. Otherwise use a single tapdisk-ioemu instance
540 * which is represented by domid 0 and provides access for Dom0 and
541 * all DomUs without device model.
542 */
543 static int connect_qemu(blkif_t *blkif, int domid)
544 {
545 char *rdctldev, *wrctldev;
547 static int tapdisk_ioemu_pid = 0;
548 static int dom0_readfd = 0;
549 static int dom0_writefd = 0;
551 if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) < 0)
552 return -1;
554 if (asprintf(&wrctldev, BLKTAP_CTRL_DIR "/qemu-write-%d", domid) < 0) {
555 free(rdctldev);
556 return -1;
557 }
559 DPRINTF("Using qemu blktap pipe: %s\n", rdctldev);
561 if (domid == 0) {
562 /*
563 * tapdisk-ioemu exits as soon as the last image is
564 * disconnected. Check if it is still running.
565 */
566 if (tapdisk_ioemu_pid == 0 || kill(tapdisk_ioemu_pid, 0)) {
567 /* No device model and tapdisk-ioemu doesn't run yet */
568 DPRINTF("Launching tapdisk-ioemu\n");
569 tapdisk_ioemu_pid = launch_tapdisk_ioemu();
571 dom0_readfd = open_ctrl_socket(wrctldev);
572 dom0_writefd = open_ctrl_socket(rdctldev);
573 }
575 DPRINTF("Using tapdisk-ioemu connection\n");
576 blkif->fds[READ] = dom0_readfd;
577 blkif->fds[WRITE] = dom0_writefd;
578 } else if (access(rdctldev, R_OK | W_OK) == 0) {
579 /* Use existing pipe to the device model */
580 DPRINTF("Using qemu-dm connection\n");
581 blkif->fds[READ] = open_ctrl_socket(wrctldev);
582 blkif->fds[WRITE] = open_ctrl_socket(rdctldev);
583 } else {
584 /* No device model => try with tapdisk-ioemu */
585 DPRINTF("No device model\n");
586 connect_qemu(blkif, 0);
587 }
589 free(rdctldev);
590 free(wrctldev);
592 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
593 return -1;
595 DPRINTF("Attached to qemu blktap pipes\n");
596 return 0;
597 }
599 /* Launch tapdisk instance */
600 static int connect_tapdisk(blkif_t *blkif, int minor)
601 {
602 char *rdctldev = NULL, *wrctldev = NULL;
603 int ret = -1;
605 DPRINTF("tapdisk process does not exist:\n");
607 if (asprintf(&rdctldev,
608 "%s/tapctrlread%d", BLKTAP_CTRL_DIR, minor) == -1)
609 goto fail;
611 if (asprintf(&wrctldev,
612 "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, minor) == -1)
613 goto fail;
615 blkif->fds[READ] = open_ctrl_socket(rdctldev);
616 blkif->fds[WRITE] = open_ctrl_socket(wrctldev);
618 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
619 goto fail;
621 /*launch the new process*/
622 DPRINTF("Launching process, CMDLINE [tapdisk %s %s]\n",
623 wrctldev, rdctldev);
625 if (launch_tapdisk(wrctldev, rdctldev) == -1) {
626 DPRINTF("Unable to fork, cmdline: [tapdisk %s %s]\n",
627 wrctldev, rdctldev);
628 goto fail;
629 }
631 ret = 0;
633 fail:
634 if (rdctldev)
635 free(rdctldev);
637 if (wrctldev)
638 free(wrctldev);
640 return ret;
641 }
643 static int blktapctrl_new_blkif(blkif_t *blkif)
644 {
645 blkif_info_t *blk;
646 int major, minor, fd_read, fd_write, type, new;
647 char *rdctldev, *wrctldev, *ptr;
648 image_t *image;
649 blkif_t *exist = NULL;
650 static uint16_t next_cookie = 0;
652 DPRINTF("Received a poll for a new vbd\n");
653 if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) {
654 if (get_new_dev(&major, &minor, blkif)<0)
655 return -1;
657 if (test_path(blk->params, &ptr, &type, &exist) != 0) {
658 DPRINTF("Error in blktap device string(%s).\n",
659 blk->params);
660 goto fail;
661 }
662 blkif->drivertype = type;
663 blkif->cookie = next_cookie++;
665 if (!exist) {
666 if (type == DISK_TYPE_IOEMU) {
667 if (connect_qemu(blkif, blkif->domid))
668 goto fail;
669 } else {
670 if (connect_tapdisk(blkif, minor))
671 goto fail;
672 }
674 } else {
675 DPRINTF("Process exists!\n");
676 blkif->fds[READ] = exist->fds[READ];
677 blkif->fds[WRITE] = exist->fds[WRITE];
678 }
680 add_disktype(blkif, type);
681 blkif->major = major;
682 blkif->minor = minor;
684 image = (image_t *)malloc(sizeof(image_t));
685 blkif->prv = (void *)image;
686 blkif->ops = &tapdisk_ops;
688 /*Retrieve the PID of the new process*/
689 if (get_tapdisk_pid(blkif) <= 0) {
690 DPRINTF("Unable to contact disk process\n");
691 goto fail;
692 }
694 /* Both of the following read and write calls will block up to
695 * max_timeout val*/
696 if (write_msg(blkif->fds[WRITE], CTLMSG_PARAMS, blkif, ptr)
697 <= 0) {
698 DPRINTF("Write_msg failed - CTLMSG_PARAMS\n");
699 goto fail;
700 }
702 if (read_msg(blkif->fds[READ], CTLMSG_IMG, blkif) <= 0) {
703 DPRINTF("Read_msg failure - CTLMSG_IMG\n");
704 goto fail;
705 }
707 } else return -1;
709 return 0;
710 fail:
711 ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor);
712 return -EINVAL;
713 }
715 static int map_new_blktapctrl(blkif_t *blkif)
716 {
717 DPRINTF("Received a poll for a new devmap\n");
718 if (write_msg(blkif->fds[WRITE], CTLMSG_NEWDEV, blkif, NULL) <= 0) {
719 DPRINTF("Write_msg failed - CTLMSG_NEWDEV\n");
720 return -EINVAL;
721 }
723 if (read_msg(blkif->fds[READ], CTLMSG_NEWDEV_RSP, blkif) <= 0) {
724 DPRINTF("Read_msg failed - CTLMSG_NEWDEV_RSP\n");
725 return -EINVAL;
726 }
727 DPRINTF("Exiting map_new_blktapctrl\n");
729 return blkif->minor - 1;
730 }
732 static int unmap_blktapctrl(blkif_t *blkif)
733 {
734 DPRINTF("Unmapping vbd\n");
736 if (write_msg(blkif->fds[WRITE], CTLMSG_CLOSE, blkif, NULL) <= 0) {
737 DPRINTF("Write_msg failed - CTLMSG_CLOSE\n");
738 return -EINVAL;
739 }
741 if (del_disktype(blkif)) {
742 close(blkif->fds[WRITE]);
743 close(blkif->fds[READ]);
744 }
746 return 0;
747 }
749 int open_ctrl_socket(char *devname)
750 {
751 int ret;
752 int ipc_fd;
753 fd_set socks;
754 struct timeval timeout;
756 if (mkdir(BLKTAP_CTRL_DIR, 0755) == 0)
757 DPRINTF("Created %s directory\n", BLKTAP_CTRL_DIR);
758 ret = mkfifo(devname,S_IRWXU|S_IRWXG|S_IRWXO);
759 if ( (ret != 0) && (errno != EEXIST) ) {
760 DPRINTF("ERROR: pipe failed (%d)\n", errno);
761 exit(0);
762 }
764 ipc_fd = open(devname,O_RDWR|O_NONBLOCK);
766 if (ipc_fd < 0) {
767 DPRINTF("FD open failed\n");
768 return -1;
769 }
771 return ipc_fd;
772 }
774 static void print_drivers(void)
775 {
776 int i, size;
778 size = sizeof(dtypes)/sizeof(disk_info_t *);
779 DPRINTF("blktapctrl: v1.0.0\n");
780 for (i = 0; i < size; i++)
781 DPRINTF("Found driver: [%s]\n",dtypes[i]->name);
782 }
784 static void write_pidfile(long pid)
785 {
786 char buf[100];
787 int len;
788 int fd;
789 int flags;
791 fd = open(PIDFILE, O_RDWR | O_CREAT, 0600);
792 if (fd == -1) {
793 DPRINTF("Opening pid file failed (%d)\n", errno);
794 exit(1);
795 }
797 /* We exit silently if daemon already running. */
798 if (lockf(fd, F_TLOCK, 0) == -1)
799 exit(0);
801 /* Set FD_CLOEXEC, so that tapdisk doesn't get this file
802 descriptor. */
803 if ((flags = fcntl(fd, F_GETFD)) == -1) {
804 DPRINTF("F_GETFD failed (%d)\n", errno);
805 exit(1);
806 }
807 flags |= FD_CLOEXEC;
808 if (fcntl(fd, F_SETFD, flags) == -1) {
809 DPRINTF("F_SETFD failed (%d)\n", errno);
810 exit(1);
811 }
813 len = snprintf(buf, sizeof(buf), "%ld\n", pid);
814 if (write(fd, buf, len) != len) {
815 DPRINTF("Writing pid file failed (%d)\n", errno);
816 exit(1);
817 }
818 }
820 int main(int argc, char *argv[])
821 {
822 char *devname;
823 tapdev_info_t *ctlinfo;
824 int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
825 struct xs_handle *h;
826 struct pollfd pfd[NUM_POLL_FDS];
827 pid_t process;
828 char buf[128];
830 __init_blkif();
831 snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid());
832 openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON);
833 if (daemon(0,0)) {
834 DPRINTF("daemon failed (%d)\n", errno);
835 goto open_failed;
836 }
838 print_drivers();
839 init_driver_list();
840 init_rng();
842 register_new_blkif_hook(blktapctrl_new_blkif);
843 register_new_devmap_hook(map_new_blktapctrl);
844 register_new_unmap_hook(unmap_blktapctrl);
846 /* Attach to blktap0 */
847 if (asprintf(&devname,"%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME) == -1)
848 goto open_failed;
849 if ((ret = xc_find_device_number("blktap0")) < 0) {
850 DPRINTF("couldn't find device number for 'blktap0'\n");
851 goto open_failed;
852 }
853 blktap_major = major(ret);
854 make_blktap_dev(devname,blktap_major,0);
855 ctlfd = open(devname, O_RDWR);
856 if (ctlfd == -1) {
857 DPRINTF("blktap0 open failed\n");
858 goto open_failed;
859 }
862 retry:
863 /* Set up store connection and watch. */
864 h = xs_daemon_open();
865 if (h == NULL) {
866 DPRINTF("xs_daemon_open failed -- "
867 "is xenstore running?\n");
868 if (count < MAX_ATTEMPTS) {
869 count++;
870 sleep(2);
871 goto retry;
872 } else goto open_failed;
873 }
875 ret = setup_probe_watch(h);
876 if (ret != 0) {
877 DPRINTF("Failed adding device probewatch\n");
878 xs_daemon_close(h);
879 goto open_failed;
880 }
882 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
884 process = getpid();
885 write_pidfile(process);
886 ret = ioctl(ctlfd, BLKTAP_IOCTL_SENDPID, process );
888 /*Static pollhooks*/
889 pfd_count = 0;
890 tap_pfd = pfd_count++;
891 pfd[tap_pfd].fd = ctlfd;
892 pfd[tap_pfd].events = POLLIN;
894 store_pfd = pfd_count++;
895 pfd[store_pfd].fd = xs_fileno(h);
896 pfd[store_pfd].events = POLLIN;
898 while (run) {
899 timeout = 1000; /*Milliseconds*/
900 ret = poll(pfd, pfd_count, timeout);
902 if (ret > 0) {
903 if (pfd[store_pfd].revents) {
904 ret = xs_fire_next_watch(h);
905 }
906 }
907 }
909 xs_daemon_close(h);
910 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
911 close(ctlfd);
912 closelog();
914 return 0;
916 open_failed:
917 DPRINTF("Unable to start blktapctrl\n");
918 closelog();
919 return -1;
920 }
922 /*
923 * Local variables:
924 * c-file-style: "linux"
925 * indent-tabs-mode: t
926 * c-indent-level: 8
927 * c-basic-offset: 8
928 * tab-width: 8
929 * End:
930 */