ia64/xen-unstable

annotate 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
rev   line source
jchesterfield@10736 1 /*
jchesterfield@10736 2 * blktapctrl.c
jchesterfield@10736 3 *
jchesterfield@10736 4 * userspace controller for the blktap disks.
jchesterfield@10736 5 * As requests for new block devices arrive,
jchesterfield@10736 6 * the controller spawns off a separate process
jchesterfield@10736 7 * per-disk.
jchesterfield@10736 8 *
jchesterfield@10736 9 *
jchesterfield@10736 10 * Copyright (c) 2005 Julian Chesterfield and Andrew Warfield.
jchesterfield@10736 11 *
jchesterfield@10736 12 * This program is free software; you can redistribute it and/or
jchesterfield@10736 13 * modify it under the terms of the GNU General Public License version 2
jchesterfield@10736 14 * as published by the Free Software Foundation; or, when distributed
jchesterfield@10736 15 * separately from the Linux kernel or incorporated into other
jchesterfield@10736 16 * software packages, subject to the following license:
jchesterfield@10736 17 *
jchesterfield@10736 18 * Permission is hereby granted, free of charge, to any person obtaining a copy
jchesterfield@10736 19 * of this source file (the "Software"), to deal in the Software without
jchesterfield@10736 20 * restriction, including without limitation the rights to use, copy, modify,
jchesterfield@10736 21 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
jchesterfield@10736 22 * and to permit persons to whom the Software is furnished to do so, subject to
jchesterfield@10736 23 * the following conditions:
jchesterfield@10736 24 *
jchesterfield@10736 25 * The above copyright notice and this permission notice shall be included in
jchesterfield@10736 26 * all copies or substantial portions of the Software.
jchesterfield@10736 27 *
jchesterfield@10736 28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jchesterfield@10736 29 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jchesterfield@10736 30 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jchesterfield@10736 31 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jchesterfield@10736 32 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
jchesterfield@10736 33 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
jchesterfield@10736 34 * IN THE SOFTWARE.
jchesterfield@10736 35 */
jchesterfield@10736 36
jchesterfield@10736 37 #include <stdio.h>
jchesterfield@10736 38 #include <stdlib.h>
jchesterfield@10736 39 #include <sys/mman.h>
keir@16526 40 #include <sys/stat.h>
jchesterfield@10736 41 #include <err.h>
jchesterfield@10736 42 #include <errno.h>
jchesterfield@10736 43 #include <sys/types.h>
kfraser@15684 44 #include <sys/wait.h>
jchesterfield@10736 45 #include <signal.h>
jchesterfield@10736 46 #include <fcntl.h>
jchesterfield@10736 47 #include <sys/poll.h>
jchesterfield@10736 48 #include <sys/ioctl.h>
jchesterfield@10736 49 #include <string.h>
jchesterfield@10736 50 #include <unistd.h>
jchesterfield@10736 51 #include <xs.h>
jchesterfield@10736 52 #include <sys/time.h>
jchesterfield@10736 53 #include <syslog.h>
jchesterfield@10736 54
jchesterfield@10736 55 #include "blktaplib.h"
jchesterfield@10736 56 #include "blktapctrl.h"
jchesterfield@10736 57 #include "tapdisk.h"
jchesterfield@10736 58
ewan@13007 59 #define PIDFILE "/var/run/blktapctrl.pid"
ewan@13007 60
jchesterfield@10736 61 #define NUM_POLL_FDS 2
jchesterfield@10736 62 #define MSG_SIZE 4096
jchesterfield@10736 63 #define MAX_TIMEOUT 10
jchesterfield@10736 64 #define MAX_RAND_VAL 0xFFFF
jchesterfield@10896 65 #define MAX_ATTEMPTS 10
jchesterfield@10736 66
jchesterfield@10736 67 int run = 1;
jchesterfield@10736 68 int max_timeout = MAX_TIMEOUT;
jchesterfield@10736 69 int ctlfd = 0;
jchesterfield@10736 70
andy@11671 71 int blktap_major;
andy@11671 72
jchesterfield@10736 73 static int open_ctrl_socket(char *devname);
jchesterfield@10736 74 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2);
jchesterfield@10736 75 static int read_msg(int fd, int msgtype, void *ptr);
jchesterfield@10736 76 static driver_list_entry_t *active_disks[MAX_DISK_TYPES];
jchesterfield@10736 77
jchesterfield@10736 78 static void init_driver_list(void)
jchesterfield@10736 79 {
jchesterfield@10736 80 int i;
jchesterfield@10736 81
jchesterfield@10736 82 for (i = 0; i < MAX_DISK_TYPES; i++)
jchesterfield@10736 83 active_disks[i] = NULL;
jchesterfield@10736 84 return;
jchesterfield@10736 85 }
jchesterfield@10736 86
jchesterfield@10736 87 static void init_rng(void)
jchesterfield@10736 88 {
jchesterfield@10736 89 static uint32_t seed;
jchesterfield@10736 90 struct timeval tv;
jchesterfield@10736 91
jchesterfield@10736 92 gettimeofday(&tv, NULL);
jchesterfield@10736 93 seed = tv.tv_usec;
jchesterfield@10736 94 srand48(seed);
jchesterfield@10736 95 return;
jchesterfield@10736 96 }
jchesterfield@10736 97
jchesterfield@10736 98 static void make_blktap_dev(char *devname, int major, int minor)
jchesterfield@10736 99 {
jchesterfield@10736 100 struct stat st;
jchesterfield@10736 101
jchesterfield@10736 102 if (lstat(devname, &st) != 0) {
jchesterfield@10736 103 /*Need to create device*/
jchesterfield@10736 104 if (mkdir(BLKTAP_DEV_DIR, 0755) == 0)
jchesterfield@10736 105 DPRINTF("Created %s directory\n",BLKTAP_DEV_DIR);
jchesterfield@10736 106 if (mknod(devname, S_IFCHR|0600,
jchesterfield@10736 107 makedev(major, minor)) == 0)
jchesterfield@10736 108 DPRINTF("Created %s device\n",devname);
andy@11671 109 } else {
andy@11671 110 DPRINTF("%s device already exists\n",devname);
andy@11671 111 /* it already exists, but is it the same major number */
andy@11671 112 if (((st.st_rdev>>8) & 0xff) != major) {
andy@11671 113 DPRINTF("%s has old major %d\n",
andy@11671 114 devname,
andy@11671 115 (unsigned int)((st.st_rdev >> 8) & 0xff));
andy@11671 116 /* only try again if we succed in deleting it */
andy@11671 117 if (!unlink(devname))
andy@11671 118 make_blktap_dev(devname, major, minor);
andy@11671 119 }
andy@11671 120 }
jchesterfield@10736 121 }
jchesterfield@10736 122
jchesterfield@10736 123 static int get_new_dev(int *major, int *minor, blkif_t *blkif)
jchesterfield@10736 124 {
jchesterfield@10736 125 domid_translate_t tr;
keir@18004 126 domid_translate_ext_t tr_ext;
jchesterfield@10736 127 int ret;
jchesterfield@10736 128 char *devname;
jchesterfield@10736 129
keir@18004 130 if (blkif->be_id >= (1<<28)) {
keir@18004 131 /* new-style backend-id, so use the extended structure */
keir@18004 132 tr_ext.domid = blkif->domid;
keir@18004 133 tr_ext.busid = blkif->be_id;
keir@18004 134 ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF_EXT, &tr_ext);
keir@18004 135 DPRINTF("Sent domid %d and be_id %d\n", tr_ext.domid,
keir@18004 136 tr_ext.busid);
keir@18004 137 }
keir@18004 138 else {
keir@18004 139 /* old-style backend-id; use the old structure */
keir@18004 140 tr.domid = blkif->domid;
keir@18004 141 tr.busid = (unsigned short)blkif->be_id;
keir@18004 142 ret = ioctl(ctlfd, BLKTAP_IOCTL_NEWINTF, tr);
keir@18004 143 DPRINTF("Sent domid %d and be_id %d\n", tr.domid, tr.busid);
keir@18004 144 }
jchesterfield@10736 145
jchesterfield@10736 146 if ( (ret <= 0)||(ret > MAX_TAP_DEV) ) {
jchesterfield@10736 147 DPRINTF("Incorrect Dev ID [%d]\n",ret);
jchesterfield@10736 148 return -1;
jchesterfield@10736 149 }
jchesterfield@10736 150
jchesterfield@10736 151 *minor = ret;
jchesterfield@10736 152 *major = ioctl(ctlfd, BLKTAP_IOCTL_MAJOR, ret );
jchesterfield@10736 153 if (*major < 0) {
jchesterfield@10736 154 DPRINTF("Incorrect Major ID [%d]\n",*major);
jchesterfield@10736 155 return -1;
jchesterfield@10736 156 }
jchesterfield@10736 157
kfraser@15334 158 if (asprintf(&devname,"%s/%s%d",BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, *minor) == -1)
kfraser@15334 159 return -1;
jchesterfield@10736 160 make_blktap_dev(devname,*major,*minor);
keir@18004 161 DPRINTF("Received device id %d and major %d\n",
keir@18004 162 *minor, *major);
jchesterfield@10736 163 return 0;
jchesterfield@10736 164 }
jchesterfield@10736 165
jchesterfield@10736 166 static int get_tapdisk_pid(blkif_t *blkif)
jchesterfield@10736 167 {
jchesterfield@10736 168 int ret;
jchesterfield@10736 169
jchesterfield@10736 170 if ((ret = write_msg(blkif->fds[WRITE], CTLMSG_PID, blkif, NULL))
jchesterfield@10736 171 <= 0) {
jchesterfield@10736 172 DPRINTF("Write_msg failed - CTLMSG_PID(%d)\n", ret);
jchesterfield@10736 173 return -EINVAL;
jchesterfield@10736 174 }
jchesterfield@10736 175
jchesterfield@10736 176 if ((ret = read_msg(blkif->fds[READ], CTLMSG_PID_RSP, blkif))
jchesterfield@10736 177 <= 0) {
jchesterfield@10736 178 DPRINTF("Read_msg failure - CTLMSG_PID(%d)\n", ret);
jchesterfield@10736 179 return -EINVAL;
jchesterfield@10736 180 }
jchesterfield@10736 181 return 1;
jchesterfield@10736 182 }
jchesterfield@10736 183
andy@12480 184 /* Look up the disk specified by path:
andy@12480 185 * if found, dev points to the device string in the path
andy@12480 186 * type is the tapdisk driver type id
andy@12480 187 * blkif is the existing interface if this is a shared driver
andy@12480 188 * and NULL otherwise.
andy@12480 189 * return 0 on success, -1 on error.
andy@12480 190 */
andy@12480 191
jwires@14896 192 static int test_path(char *path, char **dev, int *type, blkif_t **blkif)
jchesterfield@10736 193 {
jchesterfield@10736 194 char *ptr, handle[10];
andy@12480 195 int i, size, found = 0;
keir@17097 196 size_t handle_len;
jchesterfield@10736 197
jchesterfield@10736 198 size = sizeof(dtypes)/sizeof(disk_info_t *);
jchesterfield@10736 199 *type = MAX_DISK_TYPES + 1;
jwires@14896 200 *blkif = NULL;
jchesterfield@10736 201
jchesterfield@10736 202 if ( (ptr = strstr(path, ":"))!=NULL) {
keir@17097 203 handle_len = (ptr - path);
keir@17097 204 memcpy(handle, path, handle_len);
jchesterfield@10736 205 *dev = ptr + 1;
keir@17097 206 ptr = handle + handle_len;
jchesterfield@10736 207 *ptr = '\0';
jchesterfield@10736 208 DPRINTF("Detected handle: [%s]\n",handle);
jchesterfield@10736 209
keir@17097 210 for (i = 0; i < size; i++) {
keir@17097 211 if ((strlen(dtypes[i]->handle) == handle_len) &&
keir@17097 212 strncmp(handle, dtypes[i]->handle,
keir@17097 213 handle_len) == 0) {
andy@12480 214 found = 1;
andy@12480 215 }
jchesterfield@10736 216
keir@17097 217 if (found) {
keir@17097 218 *type = dtypes[i]->idnum;
andy@12480 219
andy@12480 220 if (dtypes[i]->single_handler == 1) {
andy@12480 221 /* Check whether tapdisk process
andy@12480 222 already exists */
andy@12480 223 if (active_disks[dtypes[i]->idnum] == NULL)
jwires@14896 224 *blkif = NULL;
andy@12480 225 else
jwires@14896 226 *blkif = active_disks[dtypes[i]
andy@12480 227 ->idnum]->blkif;
andy@12480 228 }
andy@12480 229 return 0;
andy@12480 230 }
keir@17097 231 }
andy@12480 232 }
jchesterfield@10736 233
andy@12480 234 /* Fall-through case, we didn't find a disk driver. */
andy@12480 235 DPRINTF("Unknown blktap disk type [%s]!\n",handle);
andy@12480 236 *dev = NULL;
andy@12480 237 return -1;
jchesterfield@10736 238 }
jchesterfield@10736 239
andy@12480 240
jchesterfield@10736 241 static void add_disktype(blkif_t *blkif, int type)
jchesterfield@10736 242 {
kfraser@11965 243 driver_list_entry_t *entry, **pprev;
jchesterfield@10736 244
kfraser@11965 245 if (type > MAX_DISK_TYPES)
kfraser@11965 246 return;
jchesterfield@10736 247
jchesterfield@10736 248 entry = malloc(sizeof(driver_list_entry_t));
jchesterfield@10736 249 entry->blkif = blkif;
kfraser@11965 250 entry->next = NULL;
jchesterfield@10736 251
kfraser@11965 252 pprev = &active_disks[type];
kfraser@11965 253 while (*pprev != NULL)
kfraser@11965 254 pprev = &(*pprev)->next;
jchesterfield@10736 255
kfraser@11965 256 *pprev = entry;
kfraser@11965 257 entry->pprev = pprev;
jchesterfield@10736 258 }
jchesterfield@10736 259
jchesterfield@10736 260 static int del_disktype(blkif_t *blkif)
jchesterfield@10736 261 {
kfraser@11965 262 driver_list_entry_t *entry, **pprev;
jchesterfield@10736 263 int type = blkif->drivertype, count = 0, close = 0;
jchesterfield@10736 264
kfraser@11965 265 if (type > MAX_DISK_TYPES)
kfraser@11965 266 return 1;
kfraser@11965 267
kfraser@11965 268 pprev = &active_disks[type];
kfraser@11965 269 while ((*pprev != NULL) && ((*pprev)->blkif != blkif))
kfraser@11965 270 pprev = &(*pprev)->next;
jchesterfield@10736 271
kfraser@11965 272 if ((entry = *pprev) == NULL) {
kfraser@11965 273 DPRINTF("DEL_DISKTYPE: No match\n");
kfraser@11965 274 return 1;
kfraser@11965 275 }
jchesterfield@10736 276
kfraser@11965 277 *pprev = entry->next;
kfraser@11965 278 if (entry->next)
kfraser@11965 279 entry->next->pprev = pprev;
kfraser@11965 280
kfraser@11965 281 DPRINTF("DEL_DISKTYPE: Freeing entry\n");
kfraser@11965 282 free(entry);
kfraser@11965 283
kfraser@11965 284 /* Caller should close() if no single controller, or list is empty. */
kfraser@11965 285 return (!dtypes[type]->single_handler || (active_disks[type] == NULL));
jchesterfield@10736 286 }
jchesterfield@10736 287
jchesterfield@10736 288 static int write_msg(int fd, int msgtype, void *ptr, void *ptr2)
jchesterfield@10736 289 {
jchesterfield@10736 290 blkif_t *blkif;
jchesterfield@10736 291 blkif_info_t *blk;
jchesterfield@10736 292 msg_hdr_t *msg;
jchesterfield@10736 293 msg_newdev_t *msg_dev;
jchesterfield@10736 294 char *p, *buf, *path;
jchesterfield@10736 295 int msglen, len, ret;
jchesterfield@10736 296 fd_set writefds;
jchesterfield@10736 297 struct timeval timeout;
jchesterfield@10736 298 image_t *image, *img;
jchesterfield@10736 299 uint32_t seed;
jchesterfield@10736 300
jchesterfield@10736 301 blkif = (blkif_t *)ptr;
jchesterfield@10736 302 blk = blkif->info;
jchesterfield@10736 303 image = blkif->prv;
jchesterfield@10736 304 len = 0;
jchesterfield@10736 305
jchesterfield@10736 306 switch (msgtype)
jchesterfield@10736 307 {
jchesterfield@10736 308 case CTLMSG_PARAMS:
jchesterfield@10736 309 path = (char *)ptr2;
jchesterfield@10736 310 DPRINTF("Write_msg called: CTLMSG_PARAMS, sending [%s, %s]\n",
jchesterfield@10736 311 blk->params, path);
jchesterfield@10736 312
jchesterfield@10736 313 msglen = sizeof(msg_hdr_t) + strlen(path) + 1;
jchesterfield@10736 314 buf = malloc(msglen);
jchesterfield@10736 315
jchesterfield@10736 316 /*Assign header fields*/
jchesterfield@10736 317 msg = (msg_hdr_t *)buf;
jchesterfield@10736 318 msg->type = CTLMSG_PARAMS;
jchesterfield@10736 319 msg->len = msglen;
jchesterfield@10736 320 msg->drivertype = blkif->drivertype;
jwires@14105 321 msg->readonly = blkif->readonly;
jchesterfield@10736 322
jchesterfield@10736 323 gettimeofday(&timeout, NULL);
jchesterfield@10736 324 msg->cookie = blkif->cookie;
jchesterfield@10736 325 DPRINTF("Generated cookie, %d\n",blkif->cookie);
jchesterfield@10736 326
jchesterfield@10736 327 /*Copy blk->params to msg*/
jchesterfield@10736 328 p = buf + sizeof(msg_hdr_t);
jchesterfield@10736 329 memcpy(p, path, strlen(path) + 1);
jchesterfield@10736 330
jchesterfield@10736 331 break;
jchesterfield@10736 332
jchesterfield@10736 333 case CTLMSG_NEWDEV:
jchesterfield@10736 334 DPRINTF("Write_msg called: CTLMSG_NEWDEV\n");
jchesterfield@10736 335
jchesterfield@10736 336 msglen = sizeof(msg_hdr_t) + sizeof(msg_newdev_t);
jchesterfield@10736 337 buf = malloc(msglen);
jchesterfield@10736 338
jchesterfield@10736 339 /*Assign header fields*/
jchesterfield@10736 340 msg = (msg_hdr_t *)buf;
jchesterfield@10736 341 msg->type = CTLMSG_NEWDEV;
jchesterfield@10736 342 msg->len = msglen;
jchesterfield@10736 343 msg->drivertype = blkif->drivertype;
jchesterfield@10736 344 msg->cookie = blkif->cookie;
jchesterfield@10736 345
jchesterfield@10736 346 msg_dev = (msg_newdev_t *)(buf + sizeof(msg_hdr_t));
jchesterfield@10736 347 msg_dev->devnum = blkif->minor;
jchesterfield@10736 348 msg_dev->domid = blkif->domid;
jchesterfield@10736 349
jchesterfield@10736 350 break;
jchesterfield@10736 351
jchesterfield@10736 352 case CTLMSG_CLOSE:
jchesterfield@10736 353 DPRINTF("Write_msg called: CTLMSG_CLOSE\n");
jchesterfield@10736 354
jchesterfield@10736 355 msglen = sizeof(msg_hdr_t);
jchesterfield@10736 356 buf = malloc(msglen);
jchesterfield@10736 357
jchesterfield@10736 358 /*Assign header fields*/
jchesterfield@10736 359 msg = (msg_hdr_t *)buf;
jchesterfield@10736 360 msg->type = CTLMSG_CLOSE;
jchesterfield@10736 361 msg->len = msglen;
jchesterfield@10736 362 msg->drivertype = blkif->drivertype;
jchesterfield@10736 363 msg->cookie = blkif->cookie;
jchesterfield@10736 364
jchesterfield@10736 365 break;
jchesterfield@10736 366
jchesterfield@10736 367 case CTLMSG_PID:
jchesterfield@10736 368 DPRINTF("Write_msg called: CTLMSG_PID\n");
jchesterfield@10736 369
jchesterfield@10736 370 msglen = sizeof(msg_hdr_t);
jchesterfield@10736 371 buf = malloc(msglen);
jchesterfield@10736 372
jchesterfield@10736 373 /*Assign header fields*/
jchesterfield@10736 374 msg = (msg_hdr_t *)buf;
jchesterfield@10736 375 msg->type = CTLMSG_PID;
jchesterfield@10736 376 msg->len = msglen;
jchesterfield@10736 377 msg->drivertype = blkif->drivertype;
jchesterfield@10736 378 msg->cookie = blkif->cookie;
jchesterfield@10736 379
jchesterfield@10736 380 break;
jchesterfield@10736 381
jchesterfield@10736 382 default:
jchesterfield@10736 383 return -1;
jchesterfield@10736 384 }
jchesterfield@10736 385
jchesterfield@10736 386 /*Now send the message*/
jchesterfield@10736 387 ret = 0;
jchesterfield@10736 388 FD_ZERO(&writefds);
jchesterfield@10736 389 FD_SET(fd,&writefds);
jchesterfield@10736 390 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
jchesterfield@10736 391 timeout.tv_usec = 0;
jchesterfield@10736 392 if (select(fd+1, (fd_set *) 0, &writefds,
jchesterfield@10736 393 (fd_set *) 0, &timeout) > 0) {
jchesterfield@10736 394 len = write(fd, buf, msglen);
jchesterfield@10736 395 if (len == -1) DPRINTF("Write failed: (%d)\n",errno);
jchesterfield@10736 396 }
jchesterfield@10736 397 free(buf);
jchesterfield@10736 398
jchesterfield@10736 399 return len;
jchesterfield@10736 400 }
jchesterfield@10736 401
jchesterfield@10736 402 static int read_msg(int fd, int msgtype, void *ptr)
jchesterfield@10736 403 {
jchesterfield@10736 404 blkif_t *blkif;
jchesterfield@10736 405 blkif_info_t *blk;
jchesterfield@10736 406 msg_hdr_t *msg;
jchesterfield@10736 407 msg_pid_t *msg_pid;
jchesterfield@10736 408 char *p, *buf;
jchesterfield@10736 409 int msglen = MSG_SIZE, len, ret;
jchesterfield@10736 410 fd_set readfds;
jchesterfield@10736 411 struct timeval timeout;
jchesterfield@10736 412 image_t *image, *img;
jchesterfield@10736 413
jchesterfield@10736 414
jchesterfield@10736 415 blkif = (blkif_t *)ptr;
jchesterfield@10736 416 blk = blkif->info;
jchesterfield@10736 417 image = blkif->prv;
jchesterfield@10736 418
jchesterfield@10736 419 buf = malloc(MSG_SIZE);
jchesterfield@10736 420
jchesterfield@10736 421 ret = 0;
jchesterfield@10736 422 FD_ZERO(&readfds);
jchesterfield@10736 423 FD_SET(fd,&readfds);
jchesterfield@10736 424 timeout.tv_sec = max_timeout; /*Wait for up to max_timeout seconds*/
jchesterfield@10736 425 timeout.tv_usec = 0;
jchesterfield@10736 426 if (select(fd+1, &readfds, (fd_set *) 0,
jchesterfield@10736 427 (fd_set *) 0, &timeout) > 0) {
jchesterfield@10736 428 ret = read(fd, buf, msglen);
jchesterfield@10736 429 }
jchesterfield@10736 430 if (ret > 0) {
jchesterfield@10736 431 msg = (msg_hdr_t *)buf;
jchesterfield@10736 432 switch (msg->type)
jchesterfield@10736 433 {
jchesterfield@10736 434 case CTLMSG_IMG:
jchesterfield@10736 435 img = (image_t *)(buf + sizeof(msg_hdr_t));
jchesterfield@10736 436 image->size = img->size;
jchesterfield@10736 437 image->secsize = img->secsize;
jchesterfield@10736 438 image->info = img->info;
jchesterfield@10736 439
kfraser@12619 440 DPRINTF("Received CTLMSG_IMG: %llu, %lu, %u\n",
jchesterfield@10736 441 image->size, image->secsize, image->info);
jchesterfield@10736 442 if(msgtype != CTLMSG_IMG) ret = 0;
jchesterfield@10736 443 break;
jchesterfield@10736 444
jchesterfield@10736 445 case CTLMSG_IMG_FAIL:
jchesterfield@10736 446 DPRINTF("Received CTLMSG_IMG_FAIL, "
jchesterfield@10736 447 "unable to open image\n");
jchesterfield@10736 448 ret = 0;
jchesterfield@10736 449 break;
jchesterfield@10736 450
jchesterfield@10736 451 case CTLMSG_NEWDEV_RSP:
jchesterfield@10736 452 DPRINTF("Received CTLMSG_NEWDEV_RSP\n");
jchesterfield@10736 453 if(msgtype != CTLMSG_NEWDEV_RSP) ret = 0;
jchesterfield@10736 454 break;
jchesterfield@10736 455
jchesterfield@10736 456 case CTLMSG_NEWDEV_FAIL:
jchesterfield@10736 457 DPRINTF("Received CTLMSG_NEWDEV_FAIL\n");
jchesterfield@10736 458 ret = 0;
jchesterfield@10736 459 break;
jchesterfield@10736 460
jchesterfield@10736 461 case CTLMSG_CLOSE_RSP:
jchesterfield@10736 462 DPRINTF("Received CTLMSG_CLOSE_RSP\n");
jchesterfield@10736 463 if (msgtype != CTLMSG_CLOSE_RSP) ret = 0;
jchesterfield@10736 464 break;
jchesterfield@10736 465
jchesterfield@10736 466 case CTLMSG_PID_RSP:
jchesterfield@10736 467 DPRINTF("Received CTLMSG_PID_RSP\n");
jchesterfield@10736 468 if (msgtype != CTLMSG_PID_RSP) ret = 0;
jchesterfield@10736 469 else {
jchesterfield@10736 470 msg_pid = (msg_pid_t *)
jchesterfield@10736 471 (buf + sizeof(msg_hdr_t));
jchesterfield@10736 472 blkif->tappid = msg_pid->pid;
jchesterfield@10736 473 DPRINTF("\tPID: [%d]\n",blkif->tappid);
jchesterfield@10736 474 }
jchesterfield@10736 475 break;
jchesterfield@10736 476 default:
jchesterfield@10736 477 DPRINTF("UNKNOWN MESSAGE TYPE RECEIVED\n");
jchesterfield@10736 478 ret = 0;
jchesterfield@10736 479 break;
jchesterfield@10736 480 }
jchesterfield@10736 481 }
jchesterfield@10736 482
jchesterfield@10736 483 free(buf);
jchesterfield@10736 484
jchesterfield@10736 485 return ret;
jchesterfield@10736 486
jchesterfield@10736 487 }
jchesterfield@10736 488
keir@17517 489 static int launch_tapdisk_provider(char **argv)
kfraser@15684 490 {
kfraser@15684 491 pid_t child;
kfraser@15684 492
kfraser@15684 493 if ((child = fork()) < 0)
kfraser@15684 494 return -1;
kfraser@15684 495
kfraser@15684 496 if (!child) {
kfraser@15684 497 int i;
kfraser@15684 498 for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++)
kfraser@15684 499 if (i != STDIN_FILENO &&
kfraser@15684 500 i != STDOUT_FILENO &&
kfraser@15684 501 i != STDERR_FILENO)
kfraser@15684 502 close(i);
kfraser@15684 503
keir@17517 504 execvp(argv[0], argv);
keir@17517 505 DPRINTF("execvp failed: %d (%s)\n", errno, strerror(errno));
keir@17517 506 DPRINTF("PATH = %s\n", getenv("PATH"));
kfraser@15684 507 _exit(1);
kfraser@15684 508 } else {
kfraser@15684 509 pid_t got;
kfraser@15684 510 do {
kfraser@15684 511 got = waitpid(child, NULL, 0);
kfraser@15684 512 } while (got != child);
kfraser@15684 513 }
keir@17517 514 return child;
keir@17517 515 }
keir@17517 516
keir@17517 517 static int launch_tapdisk(char *wrctldev, char *rdctldev)
keir@17517 518 {
keir@17517 519 char *argv[] = { "tapdisk", wrctldev, rdctldev, NULL };
keir@17517 520
keir@17517 521 if (launch_tapdisk_provider(argv) < 0)
keir@17517 522 return -1;
keir@17517 523
kfraser@15684 524 return 0;
kfraser@15684 525 }
kfraser@15684 526
keir@17517 527 static int launch_tapdisk_ioemu(void)
keir@17517 528 {
keir@17517 529 char *argv[] = { "tapdisk-ioemu", NULL };
keir@17517 530 return launch_tapdisk_provider(argv);
keir@17517 531 }
keir@17517 532
keir@17517 533 /*
keir@17517 534 * Connect to an ioemu based disk provider (qemu-dm or tapdisk-ioemu)
keir@17517 535 *
keir@17517 536 * If the domain has a device model, connect to qemu-dm through the
keir@17517 537 * domain specific pipe. Otherwise use a single tapdisk-ioemu instance
keir@17517 538 * which is represented by domid 0 and provides access for Dom0 and
keir@17517 539 * all DomUs without device model.
keir@17517 540 */
keir@17517 541 static int connect_qemu(blkif_t *blkif, int domid)
keir@17223 542 {
keir@17223 543 char *rdctldev, *wrctldev;
keir@17517 544
keir@17517 545 static int tapdisk_ioemu_pid = 0;
keir@17517 546 static int dom0_readfd = 0;
keir@17517 547 static int dom0_writefd = 0;
keir@17223 548
keir@17517 549 if (asprintf(&rdctldev, BLKTAP_CTRL_DIR "/qemu-read-%d", domid) < 0)
keir@17223 550 return -1;
keir@17223 551
keir@17517 552 if (asprintf(&wrctldev, BLKTAP_CTRL_DIR "/qemu-write-%d", domid) < 0) {
keir@17223 553 free(rdctldev);
keir@17223 554 return -1;
keir@17223 555 }
keir@17223 556
keir@17223 557 DPRINTF("Using qemu blktap pipe: %s\n", rdctldev);
keir@17223 558
keir@17517 559 if (domid == 0) {
keir@17517 560 /*
keir@17517 561 * tapdisk-ioemu exits as soon as the last image is
keir@17517 562 * disconnected. Check if it is still running.
keir@17517 563 */
keir@17517 564 if (tapdisk_ioemu_pid == 0 || kill(tapdisk_ioemu_pid, 0)) {
keir@17517 565 /* No device model and tapdisk-ioemu doesn't run yet */
keir@17517 566 DPRINTF("Launching tapdisk-ioemu\n");
keir@17517 567 tapdisk_ioemu_pid = launch_tapdisk_ioemu();
keir@17517 568
keir@17517 569 dom0_readfd = open_ctrl_socket(wrctldev);
keir@17517 570 dom0_writefd = open_ctrl_socket(rdctldev);
keir@17517 571 }
keir@17517 572
keir@17517 573 DPRINTF("Using tapdisk-ioemu connection\n");
keir@17517 574 blkif->fds[READ] = dom0_readfd;
keir@17517 575 blkif->fds[WRITE] = dom0_writefd;
keir@17517 576 } else if (access(rdctldev, R_OK | W_OK) == 0) {
keir@17517 577 /* Use existing pipe to the device model */
keir@17517 578 DPRINTF("Using qemu-dm connection\n");
keir@17517 579 blkif->fds[READ] = open_ctrl_socket(wrctldev);
keir@17517 580 blkif->fds[WRITE] = open_ctrl_socket(rdctldev);
keir@17517 581 } else {
keir@17517 582 /* No device model => try with tapdisk-ioemu */
keir@17517 583 DPRINTF("No device model\n");
keir@17517 584 connect_qemu(blkif, 0);
keir@17517 585 }
keir@17223 586
keir@17223 587 free(rdctldev);
keir@17223 588 free(wrctldev);
keir@17223 589
keir@17223 590 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
keir@17223 591 return -1;
keir@17223 592
keir@17223 593 DPRINTF("Attached to qemu blktap pipes\n");
keir@17223 594 return 0;
keir@17223 595 }
keir@17223 596
keir@17223 597 /* Launch tapdisk instance */
keir@17223 598 static int connect_tapdisk(blkif_t *blkif, int minor)
keir@17223 599 {
keir@17223 600 char *rdctldev = NULL, *wrctldev = NULL;
keir@17223 601 int ret = -1;
keir@17223 602
keir@17223 603 DPRINTF("tapdisk process does not exist:\n");
keir@17223 604
keir@17223 605 if (asprintf(&rdctldev,
keir@17223 606 "%s/tapctrlread%d", BLKTAP_CTRL_DIR, minor) == -1)
keir@17223 607 goto fail;
keir@17223 608
keir@17223 609 if (asprintf(&wrctldev,
keir@17223 610 "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, minor) == -1)
keir@17223 611 goto fail;
keir@17223 612
keir@17223 613 blkif->fds[READ] = open_ctrl_socket(rdctldev);
keir@17223 614 blkif->fds[WRITE] = open_ctrl_socket(wrctldev);
keir@17223 615
keir@17223 616 if (blkif->fds[READ] == -1 || blkif->fds[WRITE] == -1)
keir@17223 617 goto fail;
keir@17223 618
keir@17223 619 /*launch the new process*/
keir@17223 620 DPRINTF("Launching process, CMDLINE [tapdisk %s %s]\n",
keir@17223 621 wrctldev, rdctldev);
keir@17223 622
keir@17223 623 if (launch_tapdisk(wrctldev, rdctldev) == -1) {
keir@17223 624 DPRINTF("Unable to fork, cmdline: [tapdisk %s %s]\n",
keir@17223 625 wrctldev, rdctldev);
keir@17223 626 goto fail;
keir@17223 627 }
keir@17223 628
keir@17223 629 ret = 0;
keir@17223 630
keir@17223 631 fail:
keir@17223 632 if (rdctldev)
keir@17223 633 free(rdctldev);
keir@17223 634
keir@17223 635 if (wrctldev)
keir@17223 636 free(wrctldev);
keir@17223 637
keir@17223 638 return ret;
keir@17223 639 }
keir@17223 640
jchesterfield@10736 641 int blktapctrl_new_blkif(blkif_t *blkif)
jchesterfield@10736 642 {
jchesterfield@10736 643 blkif_info_t *blk;
jchesterfield@10736 644 int major, minor, fd_read, fd_write, type, new;
kfraser@15684 645 char *rdctldev, *wrctldev, *ptr;
jchesterfield@10736 646 image_t *image;
jchesterfield@10736 647 blkif_t *exist = NULL;
jwires@14896 648 static uint16_t next_cookie = 0;
jchesterfield@10736 649
jchesterfield@10736 650 DPRINTF("Received a poll for a new vbd\n");
jchesterfield@10736 651 if ( ((blk=blkif->info) != NULL) && (blk->params != NULL) ) {
jchesterfield@10736 652 if (get_new_dev(&major, &minor, blkif)<0)
jchesterfield@10736 653 return -1;
jchesterfield@10736 654
jwires@14896 655 if (test_path(blk->params, &ptr, &type, &exist) != 0) {
andy@12480 656 DPRINTF("Error in blktap device string(%s).\n",
andy@12480 657 blk->params);
keir@17172 658 goto fail;
andy@12480 659 }
jchesterfield@10736 660 blkif->drivertype = type;
jwires@14896 661 blkif->cookie = next_cookie++;
jchesterfield@10736 662
jchesterfield@10736 663 if (!exist) {
keir@17223 664 if (type == DISK_TYPE_IOEMU) {
keir@17517 665 if (connect_qemu(blkif, blkif->domid))
keir@17223 666 goto fail;
keir@17223 667 } else {
keir@17223 668 if (connect_tapdisk(blkif, minor))
keir@17223 669 goto fail;
jchesterfield@10736 670 }
jchesterfield@10736 671
jchesterfield@10736 672 } else {
jchesterfield@10736 673 DPRINTF("Process exists!\n");
jchesterfield@10736 674 blkif->fds[READ] = exist->fds[READ];
jchesterfield@10736 675 blkif->fds[WRITE] = exist->fds[WRITE];
jchesterfield@10736 676 }
jchesterfield@10736 677
jchesterfield@10736 678 add_disktype(blkif, type);
jchesterfield@10736 679 blkif->major = major;
jchesterfield@10736 680 blkif->minor = minor;
jchesterfield@10736 681
jchesterfield@10736 682 image = (image_t *)malloc(sizeof(image_t));
jchesterfield@10736 683 blkif->prv = (void *)image;
jchesterfield@10736 684 blkif->ops = &tapdisk_ops;
jchesterfield@10736 685
jchesterfield@10736 686 /*Retrieve the PID of the new process*/
jchesterfield@10736 687 if (get_tapdisk_pid(blkif) <= 0) {
jchesterfield@10736 688 DPRINTF("Unable to contact disk process\n");
jchesterfield@10736 689 goto fail;
jchesterfield@10736 690 }
jchesterfield@10736 691
jchesterfield@10736 692 /* Both of the following read and write calls will block up to
jchesterfield@10736 693 * max_timeout val*/
jchesterfield@10736 694 if (write_msg(blkif->fds[WRITE], CTLMSG_PARAMS, blkif, ptr)
jchesterfield@10736 695 <= 0) {
jchesterfield@10736 696 DPRINTF("Write_msg failed - CTLMSG_PARAMS\n");
jchesterfield@10736 697 goto fail;
jchesterfield@10736 698 }
jchesterfield@10736 699
jchesterfield@10736 700 if (read_msg(blkif->fds[READ], CTLMSG_IMG, blkif) <= 0) {
jchesterfield@10736 701 DPRINTF("Read_msg failure - CTLMSG_IMG\n");
jchesterfield@10736 702 goto fail;
jchesterfield@10736 703 }
jchesterfield@10736 704
jchesterfield@10736 705 } else return -1;
jchesterfield@10736 706
jchesterfield@10736 707 return 0;
jchesterfield@10736 708 fail:
jchesterfield@10736 709 ioctl(ctlfd, BLKTAP_IOCTL_FREEINTF, minor);
jchesterfield@10736 710 return -EINVAL;
jchesterfield@10736 711 }
jchesterfield@10736 712
jchesterfield@10736 713 int map_new_blktapctrl(blkif_t *blkif)
jchesterfield@10736 714 {
jchesterfield@10736 715 DPRINTF("Received a poll for a new devmap\n");
jchesterfield@10736 716 if (write_msg(blkif->fds[WRITE], CTLMSG_NEWDEV, blkif, NULL) <= 0) {
jchesterfield@10736 717 DPRINTF("Write_msg failed - CTLMSG_NEWDEV\n");
jchesterfield@10736 718 return -EINVAL;
jchesterfield@10736 719 }
jchesterfield@10736 720
jchesterfield@10736 721 if (read_msg(blkif->fds[READ], CTLMSG_NEWDEV_RSP, blkif) <= 0) {
jchesterfield@10736 722 DPRINTF("Read_msg failed - CTLMSG_NEWDEV_RSP\n");
jchesterfield@10736 723 return -EINVAL;
jchesterfield@10736 724 }
jchesterfield@10736 725 DPRINTF("Exiting map_new_blktapctrl\n");
jchesterfield@10736 726
jchesterfield@10736 727 return blkif->minor - 1;
jchesterfield@10736 728 }
jchesterfield@10736 729
jchesterfield@10736 730 int unmap_blktapctrl(blkif_t *blkif)
jchesterfield@10736 731 {
jchesterfield@10736 732 DPRINTF("Unmapping vbd\n");
jchesterfield@10736 733
jchesterfield@10736 734 if (write_msg(blkif->fds[WRITE], CTLMSG_CLOSE, blkif, NULL) <= 0) {
jchesterfield@10736 735 DPRINTF("Write_msg failed - CTLMSG_CLOSE\n");
jchesterfield@10736 736 return -EINVAL;
jchesterfield@10736 737 }
jchesterfield@10736 738
jchesterfield@10736 739 if (del_disktype(blkif)) {
jchesterfield@10736 740 close(blkif->fds[WRITE]);
jchesterfield@10736 741 close(blkif->fds[READ]);
kfraser@11965 742 }
jchesterfield@10736 743
jchesterfield@10736 744 return 0;
jchesterfield@10736 745 }
jchesterfield@10736 746
jchesterfield@10736 747 int open_ctrl_socket(char *devname)
jchesterfield@10736 748 {
jchesterfield@10736 749 int ret;
jchesterfield@10736 750 int ipc_fd;
jchesterfield@10736 751 fd_set socks;
jchesterfield@10736 752 struct timeval timeout;
jchesterfield@10736 753
brendan@15003 754 if (mkdir(BLKTAP_CTRL_DIR, 0755) == 0)
brendan@15003 755 DPRINTF("Created %s directory\n", BLKTAP_CTRL_DIR);
jchesterfield@10736 756 ret = mkfifo(devname,S_IRWXU|S_IRWXG|S_IRWXO);
jchesterfield@10736 757 if ( (ret != 0) && (errno != EEXIST) ) {
jchesterfield@10736 758 DPRINTF("ERROR: pipe failed (%d)\n", errno);
jchesterfield@10736 759 exit(0);
jchesterfield@10736 760 }
jchesterfield@10736 761
jchesterfield@10736 762 ipc_fd = open(devname,O_RDWR|O_NONBLOCK);
jchesterfield@10736 763
jchesterfield@10736 764 if (ipc_fd < 0) {
jchesterfield@10736 765 DPRINTF("FD open failed\n");
jchesterfield@10736 766 return -1;
jchesterfield@10736 767 }
jchesterfield@10736 768
jchesterfield@10736 769 return ipc_fd;
jchesterfield@10736 770 }
jchesterfield@10736 771
jchesterfield@10736 772 static void print_drivers(void)
jchesterfield@10736 773 {
jchesterfield@10736 774 int i, size;
jchesterfield@10736 775
jchesterfield@10736 776 size = sizeof(dtypes)/sizeof(disk_info_t *);
jchesterfield@10736 777 DPRINTF("blktapctrl: v1.0.0\n");
jchesterfield@10736 778 for (i = 0; i < size; i++)
jchesterfield@10736 779 DPRINTF("Found driver: [%s]\n",dtypes[i]->name);
jchesterfield@10736 780 }
jchesterfield@10736 781
ewan@13007 782 static void write_pidfile(long pid)
ewan@13007 783 {
ewan@13007 784 char buf[100];
ewan@13007 785 int len;
ewan@13007 786 int fd;
ewan@13017 787 int flags;
ewan@13007 788
ewan@13007 789 fd = open(PIDFILE, O_RDWR | O_CREAT, 0600);
ewan@13007 790 if (fd == -1) {
ewan@13007 791 DPRINTF("Opening pid file failed (%d)\n", errno);
ewan@13007 792 exit(1);
ewan@13007 793 }
ewan@13007 794
ewan@13007 795 /* We exit silently if daemon already running. */
ewan@13007 796 if (lockf(fd, F_TLOCK, 0) == -1)
ewan@13007 797 exit(0);
ewan@13007 798
ewan@13017 799 /* Set FD_CLOEXEC, so that tapdisk doesn't get this file
ewan@13017 800 descriptor. */
ewan@13017 801 if ((flags = fcntl(fd, F_GETFD)) == -1) {
ewan@13017 802 DPRINTF("F_GETFD failed (%d)\n", errno);
ewan@13017 803 exit(1);
ewan@13017 804 }
ewan@13017 805 flags |= FD_CLOEXEC;
ewan@13017 806 if (fcntl(fd, F_SETFD, flags) == -1) {
ewan@13017 807 DPRINTF("F_SETFD failed (%d)\n", errno);
ewan@13017 808 exit(1);
ewan@13017 809 }
ewan@13017 810
keir@16526 811 len = snprintf(buf, sizeof(buf), "%ld\n", pid);
ewan@13007 812 if (write(fd, buf, len) != len) {
ewan@13007 813 DPRINTF("Writing pid file failed (%d)\n", errno);
ewan@13007 814 exit(1);
ewan@13007 815 }
ewan@13007 816 }
ewan@13007 817
jchesterfield@10736 818 int main(int argc, char *argv[])
jchesterfield@10736 819 {
jchesterfield@10736 820 char *devname;
jchesterfield@10736 821 tapdev_info_t *ctlinfo;
jchesterfield@10896 822 int tap_pfd, store_pfd, xs_fd, ret, timeout, pfd_count, count=0;
jchesterfield@10736 823 struct xs_handle *h;
jchesterfield@10736 824 struct pollfd pfd[NUM_POLL_FDS];
jchesterfield@10736 825 pid_t process;
kfraser@12283 826 char buf[128];
jchesterfield@10736 827
jchesterfield@10736 828 __init_blkif();
kfraser@12283 829 snprintf(buf, sizeof(buf), "BLKTAPCTRL[%d]", getpid());
kfraser@12283 830 openlog(buf, LOG_CONS|LOG_ODELAY, LOG_DAEMON);
kfraser@15209 831 if (daemon(0,0)) {
kfraser@15209 832 DPRINTF("daemon failed (%d)\n", errno);
kfraser@15209 833 goto open_failed;
kfraser@15209 834 }
jchesterfield@10736 835
jchesterfield@10736 836 print_drivers();
jchesterfield@10736 837 init_driver_list();
jchesterfield@10736 838 init_rng();
jchesterfield@10736 839
jchesterfield@10736 840 register_new_blkif_hook(blktapctrl_new_blkif);
jchesterfield@10736 841 register_new_devmap_hook(map_new_blktapctrl);
jchesterfield@10736 842 register_new_unmap_hook(unmap_blktapctrl);
jchesterfield@10736 843
kfraser@11692 844 /* Attach to blktap0 */
kfraser@15334 845 if (asprintf(&devname,"%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME) == -1)
kfraser@15334 846 goto open_failed;
kfraser@15196 847 if ((ret = xc_find_device_number("blktap0")) < 0) {
kfraser@15196 848 DPRINTF("couldn't find device number for 'blktap0'\n");
andy@11671 849 goto open_failed;
kfraser@15196 850 }
kfraser@11692 851 blktap_major = major(ret);
andy@11671 852 make_blktap_dev(devname,blktap_major,0);
jchesterfield@10736 853 ctlfd = open(devname, O_RDWR);
jchesterfield@10736 854 if (ctlfd == -1) {
jchesterfield@10736 855 DPRINTF("blktap0 open failed\n");
jchesterfield@10736 856 goto open_failed;
jchesterfield@10736 857 }
jchesterfield@10736 858
jchesterfield@11748 859
jchesterfield@10896 860 retry:
jchesterfield@10736 861 /* Set up store connection and watch. */
jchesterfield@10736 862 h = xs_daemon_open();
jchesterfield@10736 863 if (h == NULL) {
jchesterfield@10736 864 DPRINTF("xs_daemon_open failed -- "
jchesterfield@10736 865 "is xenstore running?\n");
jchesterfield@10896 866 if (count < MAX_ATTEMPTS) {
jchesterfield@10896 867 count++;
jchesterfield@10896 868 sleep(2);
jchesterfield@10896 869 goto retry;
jchesterfield@10896 870 } else goto open_failed;
jchesterfield@10736 871 }
jchesterfield@10736 872
jchesterfield@11748 873 ret = setup_probe_watch(h);
kfraser@11768 874 if (ret != 0) {
jchesterfield@10896 875 DPRINTF("Failed adding device probewatch\n");
jchesterfield@11748 876 xs_daemon_close(h);
jchesterfield@11748 877 goto open_failed;
jchesterfield@10736 878 }
jchesterfield@10736 879
jchesterfield@10736 880 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE );
jchesterfield@10736 881
jchesterfield@10736 882 process = getpid();
ewan@13007 883 write_pidfile(process);
jchesterfield@10736 884 ret = ioctl(ctlfd, BLKTAP_IOCTL_SENDPID, process );
jchesterfield@10736 885
jchesterfield@10736 886 /*Static pollhooks*/
jchesterfield@10736 887 pfd_count = 0;
jchesterfield@10736 888 tap_pfd = pfd_count++;
jchesterfield@10736 889 pfd[tap_pfd].fd = ctlfd;
jchesterfield@10736 890 pfd[tap_pfd].events = POLLIN;
jchesterfield@10736 891
jchesterfield@10736 892 store_pfd = pfd_count++;
jchesterfield@10736 893 pfd[store_pfd].fd = xs_fileno(h);
jchesterfield@10736 894 pfd[store_pfd].events = POLLIN;
jchesterfield@10736 895
jchesterfield@10736 896 while (run) {
jchesterfield@10736 897 timeout = 1000; /*Milliseconds*/
jchesterfield@10736 898 ret = poll(pfd, pfd_count, timeout);
jchesterfield@10736 899
jchesterfield@10736 900 if (ret > 0) {
jchesterfield@10736 901 if (pfd[store_pfd].revents) {
jchesterfield@10736 902 ret = xs_fire_next_watch(h);
jchesterfield@10736 903 }
jchesterfield@10736 904 }
jchesterfield@10736 905 }
jchesterfield@10736 906
jchesterfield@10896 907 xs_daemon_close(h);
jchesterfield@10736 908 ioctl(ctlfd, BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH );
jchesterfield@10736 909 close(ctlfd);
jchesterfield@10736 910 closelog();
jchesterfield@10736 911
jchesterfield@10736 912 return 0;
jchesterfield@10736 913
jchesterfield@10736 914 open_failed:
jchesterfield@10736 915 DPRINTF("Unable to start blktapctrl\n");
jchesterfield@10736 916 closelog();
jchesterfield@10736 917 return -1;
jchesterfield@10736 918 }
ewan@13007 919
ewan@13007 920 /*
ewan@13007 921 * Local variables:
ewan@13007 922 * c-file-style: "linux"
ewan@13007 923 * indent-tabs-mode: t
ewan@13007 924 * c-indent-level: 8
ewan@13007 925 * c-basic-offset: 8
ewan@13007 926 * tab-width: 8
ewan@13007 927 * End:
ewan@13007 928 */