CFLAGS += -Wno-unused
CFLAGS += -I../include -I../drivers
CFLAGS += -D_GNU_SOURCE
+CFLAGS += -DTAPCTL
# Get gcc to generate the dependencies for us.
CFLAGS += -Wp,-MD,.$(@F).d
CTL_OBJS += tap-ctl-pause.o
CTL_OBJS += tap-ctl-unpause.o
CTL_OBJS += tap-ctl-major.o
+CTL_OBJS += tap-ctl-check.o
OBJS = $(CTL_OBJS)
LIBS = libblktapctl.a
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/ioctl.h>
+#include <linux/major.h>
#include "tap-ctl.h"
#include "blktap2.h"
-static void
-usage(void)
-{
- printf("usage: allocate [-d device name]>\n");
-}
-
static int
tap_ctl_prepare_directory(const char *dir)
{
err = mkdir(name, 0755);
if (err && errno != EEXIST) {
+ PERROR("mkdir %s", name);
err = errno;
- fprintf(stderr, "failed to create directory %s: %d\n",
- name, err);
break;
}
if (!access(devname, F_OK))
if (unlink(devname)) {
- fprintf(stderr, "error unlinking %s: %d\n",
- devname, errno);
+ PERROR("unlink %s", devname);
return errno;
}
err = mknod(devname, perm, makedev(major, minor));
if (err) {
- fprintf(stderr, "mknod %s failed: %d\n", devname, errno);
+ PERROR("mknod %s", devname);
return errno;
}
f = fopen("/proc/misc", "r");
if (!f) {
- fprintf(stderr, "failed to open /proc/misc: %d\n", errno);
+ EPRINTF("failed to open /proc/misc: %d\n", errno);
return errno;
}
while (fscanf(f, "%d %256s", &minor, name) == 2)
if (!strcmp(name, BLKTAP2_CONTROL_NAME)) {
err = tap_ctl_make_device(BLKTAP2_CONTROL_DEVICE,
- MISC_MAJOR_NUMBER,
+ MISC_MAJOR,
minor, S_IFCHR | 0600);
goto out;
}
err = ENOSYS;
- fprintf(stderr, "didn't find %s in /proc/misc\n", BLKTAP2_CONTROL_NAME);
+ EPRINTF("didn't find %s in /proc/misc\n", BLKTAP2_CONTROL_NAME);
out:
fclose(f);
fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
if (fd == -1) {
- fprintf(stderr, "failed to open control device: %d\n", errno);
+ EPRINTF("failed to open control device: %d\n", errno);
return errno;
}
err = ioctl(fd, BLKTAP2_IOCTL_ALLOC_TAP, &handle);
close(fd);
if (err == -1) {
- fprintf(stderr, "failed to allocate new device: %d\n", errno);
+ EPRINTF("failed to allocate new device: %d\n", errno);
return errno;
}
- if (*devname)
- name = *devname;
- else {
- err = asprintf(&name, "%s%d",
- BLKTAP2_RING_DEVICE, handle.minor);
- if (err == -1) {
- err = ENOMEM;
- goto fail;
- }
- *devname = name;
+ err = asprintf(&name, "%s%d", BLKTAP2_RING_DEVICE, handle.minor);
+ if (err == -1) {
+ err = ENOMEM;
+ goto fail;
}
err = tap_ctl_make_device(name, handle.ring,
handle.minor, S_IFCHR | 0600);
+ free(name);
if (err) {
- fprintf(stderr, "creating ring device for %d failed: %d\n",
+ EPRINTF("creating ring device for %d failed: %d\n",
handle.minor, err);
goto fail;
}
- err = asprintf(&name, "%s%d", BLKTAP2_IO_DEVICE, handle.minor);
- if (err == -1) {
- err = ENOMEM;
- goto fail;
+ if (*devname)
+ name = *devname;
+ else {
+ err = asprintf(&name, "%s%d",
+ BLKTAP2_IO_DEVICE, handle.minor);
+ if (err == -1) {
+ err = ENOMEM;
+ goto fail;
+ }
+ *devname = name;
}
err = tap_ctl_make_device(name, handle.device,
handle.minor, S_IFBLK | 0600);
- free(name);
if (err) {
- fprintf(stderr, "creating IO device for %d failed: %d\n",
+ EPRINTF("creating IO device for %d failed: %d\n",
handle.minor, err);
goto fail;
}
return 0;
fail:
- _tap_ctl_free(handle.minor);
+ tap_ctl_free(handle.minor);
return err;
}
int
-_tap_ctl_allocate(int *minor, char **devname)
+tap_ctl_allocate(int *minor, char **devname)
{
int err;
return 0;
}
-
-int
-tap_ctl_allocate(int argc, char **argv)
-{
- char *devname;
- int c, id, err;
-
- devname = NULL;
-
- optind = 0;
- while ((c = getopt(argc, argv, "d:h")) != -1) {
- switch (c) {
- case 'd':
- devname = optarg;
- break;
- case 'h':
- usage();
- return 0;
- }
- }
-
- err = _tap_ctl_allocate(&id, &devname);
- if (!err)
- printf("%s\n", devname);
-
- return err;
-}
#include "tap-ctl.h"
-static void
-usage(void)
-{
- printf("usage: attach <-i id> <-m minor>\n");
-}
-
int
-_tap_ctl_attach(const int id, const int minor)
+tap_ctl_attach(const int id, const int minor)
{
int err;
tapdisk_message_t message;
if (message.type == TAPDISK_MESSAGE_ATTACH_RSP) {
err = message.u.response.error;
if (err)
- printf("attach failed: %d\n", err);
+ EPRINTF("attach failed: %d\n", err);
} else {
- printf("got unexpected result '%s' from %d\n",
- tapdisk_message_name(message.type), id);
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
err = EINVAL;
}
return err;
}
-
-int
-tap_ctl_attach(int argc, char **argv)
-{
- int c, id, minor;
-
- id = -1;
- minor = -1;
-
- optind = 0;
- while ((c = getopt(argc, argv, "i:m:h")) != -1) {
- switch (c) {
- case 'i':
- id = atoi(optarg);
- break;
- case 'm':
- minor = atoi(optarg);
- break;
- case 'h':
- usage();
- return 0;
- }
- }
-
- if (id == -1 || minor == -1) {
- usage();
- return EINVAL;
- }
-
- return _tap_ctl_attach(id, minor);
-}
--- /dev/null
+/*
+ * Copyright (c) 2008, XenSource Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of XenSource Inc. nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "tap-ctl.h"
+#include "blktap2.h"
+
+int
+tap_ctl_check_blktap(const char **msg)
+{
+ FILE *f;
+ int err = 0, minor;
+ char name[32];
+
+ memset(name, 0, sizeof(name));
+
+ f = fopen("/proc/misc", "r");
+ if (!f) {
+ *msg = "failed to open /proc/misc";
+ return -errno;
+ }
+
+ while (fscanf(f, "%d %32s", &minor, name) == 2) {
+ if (!strcmp(name, BLKTAP2_CONTROL_NAME))
+ goto out;
+ }
+
+ err = -ENOSYS;
+ *msg = "blktap kernel module not installed";
+
+out:
+ fclose(f);
+ return err;
+}
+
+int
+tap_ctl_check(const char **msg)
+{
+ int err;
+ uid_t uid;
+
+ err = tap_ctl_check_blktap(msg);
+ if (err)
+ goto out;
+
+ err = 0;
+ *msg = "ok";
+
+out:
+ return err;
+}
#include "tap-ctl.h"
-static void
-usage(void)
-{
- printf("usage: close <-i id> <-m minor> [-f force]\n");
-}
-
static int
__tap_ctl_close(const int id, const int minor, const int force)
{
if (message.type == TAPDISK_MESSAGE_CLOSE_RSP) {
err = message.u.response.error;
if (err)
- printf("close failed: %d\n", err);
+ EPRINTF("close failed: %d\n", err);
} else {
- printf("got unexpected result '%s' from %d\n",
- tapdisk_message_name(message.type), id);
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
err = EINVAL;
}
}
int
-_tap_ctl_close(const int id, const int minor, const int force)
+tap_ctl_close(const int id, const int minor, const int force)
{
int i, err;
err = (err < 0 ? -err : err);
if (err != EAGAIN) {
- printf("close failed: %d\n", err);
+ EPRINTF("close failed: %d\n", err);
return err;
}
usleep(1000);
}
- printf("close timed out\n");
+ EPRINTF("close timed out\n");
return EIO;
}
-
-int
-tap_ctl_close(int argc, char **argv)
-{
- int c, id, minor, force;
-
- id = -1;
- minor = -1;
- force = 0;
-
- optind = 0;
- while ((c = getopt(argc, argv, "i:m:fh")) != -1) {
- switch (c) {
- case 'i':
- id = atoi(optarg);
- break;
- case 'm':
- minor = atoi(optarg);
- break;
- case 'f':
- force = -1;
- break;
- case 'h':
- usage();
- return 0;
- }
- }
-
- if (id == -1 || minor == -1) {
- usage();
- return EINVAL;
- }
-
- return _tap_ctl_close(id, minor, force);
-}
#include "tap-ctl.h"
#include "blktap2.h"
-static void
-usage(void)
-{
- printf("usage: create <-a args> [-d device name]\n");
-}
-
int
-_tap_ctl_create(const char *params, char **devname)
+tap_ctl_create(const char *params, char **devname)
{
- int err, id;
+ int err, id, minor;
- err = _tap_ctl_allocate(&id, devname);
+ err = tap_ctl_allocate(&minor, devname);
if (err)
return err;
- err = _tap_ctl_spawn(id);
- if (err < 0)
+ id = tap_ctl_spawn();
+ if (id < 0)
goto destroy;
- err = _tap_ctl_attach(id, id);
+ err = tap_ctl_attach(id, minor);
if (err)
goto destroy;
- err = tap_ctl_open(id, id, params);
+ err = tap_ctl_open(id, minor, params);
if (err)
goto detach;
return 0;
detach:
- _tap_ctl_detach(id, id);
+ tap_ctl_detach(id, minor);
destroy:
- _tap_ctl_free(id);
- return err;
-}
-
-int
-tap_ctl_create(int argc, char **argv)
-{
- int c, err, type;
- char *args, *devname;
-
- args = NULL;
- devname = NULL;
-
- optind = 0;
- while ((c = getopt(argc, argv, "a:d:h")) != -1) {
- switch (c) {
- case 'a':
- args = optarg;
- break;
- case 'd':
- devname = optarg;
- break;
- case 'h':
- usage();
- return 0;
- }
- }
-
- if (!args) {
- usage();
- return EINVAL;
- }
-
- err = _tap_ctl_create(args, &devname);
- if (!err)
- printf("%s\n", devname);
-
+ tap_ctl_free(minor);
return err;
}
#include "tap-ctl.h"
#include "blktap2.h"
-static void
-usage(void)
-{
- printf("usage: destroy <-i id> <-m minor>\n");
-}
-
int
-_tap_ctl_destroy(const int id, const int minor)
+tap_ctl_destroy(const int id, const int minor)
{
int err;
- err = _tap_ctl_close(id, minor, 0);
+ err = tap_ctl_close(id, minor, 0);
if (err)
return err;
- err = _tap_ctl_detach(id, minor);
+ err = tap_ctl_detach(id, minor);
if (err)
return err;
- err = _tap_ctl_free(minor);
+ err = tap_ctl_free(minor);
if (err)
return err;
return 0;
}
-
-int
-tap_ctl_destroy(int argc, char **argv)
-{
- int c, id, minor;
-
- id = -1;
- minor = -1;
-
- optind = 0;
- while ((c = getopt(argc, argv, "i:m:h")) != -1) {
- switch (c) {
- case 'i':
- id = atoi(optarg);
- break;
- case 'm':
- minor = atoi(optarg);
- break;
- case 'h':
- usage();
- return 0;
- }
- }
-
- if (id == -1 || minor == -1) {
- usage();
- return EINVAL;
- }
-
- return _tap_ctl_destroy(id, minor);
-}
#include "tap-ctl.h"
-static void
-usage(void)
-{
- printf("usage: detach <-i id> <-m minor>\n");
-}
-
int
-_tap_ctl_detach(const int id, const int minor)
+tap_ctl_detach(const int id, const int minor)
{
int err;
tapdisk_message_t message;
return err;
}
-
-int
-tap_ctl_detach(int argc, char **argv)
-{
- int c, id, minor;
-
- id = -1;
- minor = -1;
-
- optind = 0;
- while ((c = getopt(argc, argv, "i:m:h")) != -1) {
- switch (c) {
- case 'i':
- id = atoi(optarg);
- break;
- case 'm':
- minor = atoi(optarg);
- break;
- case 'h':
- usage();
- return 0;
- }
- }
-
- if (id == -1 || minor == -1) {
- usage();
- return EINVAL;
- }
-
- return _tap_ctl_detach(id, minor);
-}
#include "tap-ctl.h"
#include "blktap2.h"
-static void
-usage(void)
-{
- printf("usage: free <-m minor>\n");
-}
-
int
-_tap_ctl_free(const int minor)
+tap_ctl_free(const int minor)
{
int fd, err;
fd = open(BLKTAP2_CONTROL_DEVICE, O_RDONLY);
if (fd == -1) {
- printf("failed to open control device: %d\n", errno);
+ EPRINTF("failed to open control device: %d\n", errno);
return errno;
}
return err;
}
-
-int
-tap_ctl_free(int argc, char **argv)
-{
- int c, minor;
-
- minor = -1;
-
- optind = 0;
- while ((c = getopt(argc, argv, "m:h")) != -1) {
- switch (c) {
- case 'm':
- minor = atoi(optarg);
- break;
- case 'h':
- usage();
- return 0;
- }
- }
-
- if (minor == -1) {
- usage();
- return EINVAL;
- }
-
- return _tap_ctl_free(minor);
-}
}
if (offset != len) {
- printf("failure reading message\n");
+ EPRINTF("failure reading message\n");
return -EIO;
}
}
if (offset != len) {
- printf("failure writing message\n");
+ EPRINTF("failure writing message\n");
return -EIO;
}
err = tap_ctl_write_message(sfd, message, timeout);
if (err) {
- printf("failed to send '%s' message\n",
- tapdisk_message_name(message->type));
+ EPRINTF("failed to send '%s' message\n",
+ tapdisk_message_name(message->type));
return err;
}
err = tap_ctl_read_message(sfd, message, timeout);
if (err) {
- printf("failed to receive '%s' message\n",
- tapdisk_message_name(message->type));
+ EPRINTF("failed to receive '%s' message\n",
+ tapdisk_message_name(message->type));
return err;
}
fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd == -1) {
- fprintf(stderr, "couldn't create socket for %s: %d\n", name, errno);
+ EPRINTF("couldn't create socket for %s: %d\n", name, errno);
return -errno;
}
err = connect(fd, (const struct sockaddr *)&saddr, sizeof(saddr));
if (err) {
- //if (errno != ECONNREFUSED)
- fprintf(stderr, "couldn't connect to %s: %d\n", name, errno);
+ EPRINTF("couldn't connect to %s: %d\n", name, errno);
close(fd);
return -errno;
}
*sfd = -1;
if (id < 0) {
- printf("invalid id %d\n", id);
+ EPRINTF("invalid id %d\n", id);
return -EINVAL;
}
name = tap_ctl_socket_name(id);
if (!name) {
- printf("couldn't name socket for %d\n", id);
+ EPRINTF("couldn't name socket for %d\n", id);
return -ENOMEM;
}
#include "tap-ctl.h"
#include "blktap2.h"
#include "list.h"
-#include "tapdisk-disktype.h"
static void
free_list(tap_list_t *entry)
case GLOB_ABORTED:
case GLOB_NOSPACE:
err = -errno;
- fprintf(stderr, "%s: glob failed, err %d", pattern, err);
+ EPRINTF("%s: glob failed, err %d", pattern, err);
goto fail;
}
case GLOB_ABORTED:
case GLOB_NOSPACE:
err = -errno;
- fprintf(stderr, "%s: glob failed, err %d", pattern, err);
+ EPRINTF("%s: glob failed, err %d", pattern, err);
goto fail;
}
if (err != 1)
continue;
- tap->pid = _tap_ctl_get_pid(tap->id);
+ tap->pid = tap_ctl_get_pid(tap->id);
if (tap->pid < 0)
continue;
- INIT_LIST_HEAD(&tap->list);
-
n_taps++;
}
qsort(tapv, n_taps, sizeof(struct tapdisk), _tap_tapdisk_cmp);
+ for (i = 0; i < n_taps; ++i)
+ INIT_LIST_HEAD(&tapv[i].list);
+
done:
*_tapv = tapv;
err = 0;
#include "blktaplib.h"
int
-tap_ctl_open(const int id, const int minor, const char *args)
+tap_ctl_open(const int id, const int minor, const char *params)
{
int err;
tapdisk_message_t message;
message.u.params.devnum = minor;
err = snprintf(message.u.params.path,
- sizeof(message.u.params.path) - 1, "%s", args);
+ sizeof(message.u.params.path) - 1, "%s", params);
if (err >= sizeof(message.u.params.path)) {
- printf("name too long\n");
+ EPRINTF("name too long\n");
return ENAMETOOLONG;
}
break;
case TAPDISK_MESSAGE_ERROR:
err = -message.u.response.error;
- fprintf(stderr, "open failed, err %d\n", err);
+ EPRINTF("open failed, err %d\n", err);
break;
default:
- printf("got unexpected result '%s' from %d\n",
- tapdisk_message_name(message.type), id);
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
err = EINVAL;
}
#include "tap-ctl.h"
-static void
-usage(void)
-{
- printf("usage: pause <-i id> <-m minor>\n");
-}
-
int
tap_ctl_pause(const int id, const int minor)
{
err = message.u.response.error;
else {
err = EINVAL;
- printf("got unexpected result '%s' from %d\n",
- tapdisk_message_name(message.type), id);
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
}
return err;
#include "tap-ctl.h"
#include "blktap2.h"
-static void
-usage(void)
-{
- printf("usage: spawn <-i id>\n");
-}
-
static pid_t
-__tap_ctl_spawn(const int id)
+__tap_ctl_spawn(int *readfd)
{
- int err, child;
- char uuid[12], *control, *tapdisk;
+ int err, child, channel[2];
+ char *tapdisk;
+
+ if (pipe(channel)) {
+ EPRINTF("pipe failed: %d\n", errno);
+ return -errno;
+ }
if ((child = fork()) == -1) {
- printf("fork failed: %d\n", errno);
+ EPRINTF("fork failed: %d\n", errno);
return -errno;
}
- if (child)
+ if (child) {
+ close(channel[1]);
+ *readfd = channel[0];
return child;
+ }
- err = asprintf(&control, "%s/%s%d",
- BLKTAP2_CONTROL_DIR,
- BLKTAP2_CONTROL_SOCKET, id);
- if (err == -1) {
- printf("fork failed: %d\n", ENOMEM);
- exit(ENOMEM);
+ if (dup2(channel[1], STDOUT_FILENO) == -1) {
+ EPRINTF("dup2 failed: %d\n", errno);
+ exit(errno);
}
+ if (dup2(channel[1], STDERR_FILENO) == -1) {
+ EPRINTF("dup2 failed: %d\n", errno);
+ exit(errno);
+ }
+
+ close(channel[0]);
+ close(channel[1]);
+
tapdisk = getenv("TAPDISK2");
if (!tapdisk)
tapdisk = "tapdisk2";
- snprintf(uuid, sizeof(uuid) - 1, "%d", id);
+ execlp(tapdisk, tapdisk, NULL);
- execlp(tapdisk, tapdisk, "-u", uuid, "-c", control, NULL);
-
- printf("exec failed\n");
+ EPRINTF("exec failed\n");
exit(1);
}
pid_t
-_tap_ctl_get_pid(const int id)
+tap_ctl_get_pid(const int id)
{
int err;
tapdisk_message_t message;
}
static int
-_tap_ctl_wait(pid_t child)
+tap_ctl_wait(pid_t child)
{
pid_t pid;
int status;
pid = waitpid(child, &status, 0);
if (pid < 0) {
- fprintf(stderr, "wait(%d) failed, err %d\n", child, errno);
+ EPRINTF("wait(%d) failed, err %d\n", child, errno);
return -errno;
}
if (WIFEXITED(status)) {
int code = WEXITSTATUS(status);
if (code)
- fprintf(stderr, "tapdisk2[%d] failed, status %d\n", child, code);
+ EPRINTF("tapdisk2[%d] failed, status %d\n", child, code);
return -code;
}
if (WIFSIGNALED(status)) {
int signo = WTERMSIG(status);
- fprintf(stderr, "tapdisk2[%d] killed by signal %d\n", child, signo);
+ EPRINTF("tapdisk2[%d] killed by signal %d\n", child, signo);
return -EINTR;
}
- fprintf(stderr, "tapdisk2[%d]: unexpected status %#x\n", child, status);
+ EPRINTF("tapdisk2[%d]: unexpected status %#x\n", child, status);
return -EAGAIN;
}
-
-int
-_tap_ctl_spawn(const int id)
+static int
+tap_ctl_get_child_id(int readfd)
{
- pid_t child, task;
- int err;
+ int id;
+ FILE *f;
- child = __tap_ctl_spawn(id);
- if (child < 0)
- return child;
-
- err = _tap_ctl_wait(child);
- if (err)
- return err;
+ f = fdopen(readfd, "r");
+ if (!f) {
+ EPRINTF("fdopen failed: %d\n", errno);
+ return -1;
+ }
- task = _tap_ctl_get_pid(id);
- if (task < 0)
- fprintf(stderr, "get_pid(%d) failed, err %d\n", child, errno);
+ errno = 0;
+ if (fscanf(f, BLKTAP2_CONTROL_DIR"/"
+ BLKTAP2_CONTROL_SOCKET"%d", &id) != 1) {
+ errno = (errno ? : EINVAL);
+ EPRINTF("parsing id failed: %d\n", errno);
+ id = -1;
+ }
- return task;
+ fclose(f);
+ return id;
}
int
-tap_ctl_spawn(int argc, char **argv)
+tap_ctl_spawn(void)
{
- int c, id;
- pid_t task;
-
- id = -1;
-
- optind = 0;
- while ((c = getopt(argc, argv, "i:h")) != -1) {
- switch (c) {
- case 'i':
- id = atoi(optarg);
- break;
- case 'h':
- usage();
- return 0;
- }
- }
+ pid_t child;
+ int err, id, readfd;
- if (id == -1) {
- usage();
- return EINVAL;
- }
+ readfd = -1;
+
+ child = __tap_ctl_spawn(&readfd);
+ if (child < 0)
+ return child;
+
+ err = tap_ctl_wait(child);
+ if (err)
+ return err;
- task = _tap_ctl_spawn(id);
+ id = tap_ctl_get_child_id(readfd);
+ if (id < 0)
+ EPRINTF("get_id failed, child %d err %d\n", child, errno);
- return task < 0 ? task : 0;
+ return id;
}
err = message.u.response.error;
else {
err = EINVAL;
- printf("got unexpected result '%s' from %d\n",
- tapdisk_message_name(message.type), id);
+ EPRINTF("got unexpected result '%s' from %d\n",
+ tapdisk_message_name(message.type), id);
}
return err;
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#include <stdio.h>
-#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <getopt.h>
#include "tap-ctl.h"
tap_cli_list_usage(FILE *stream)
{
fprintf(stream,
- "usage: list [-h] [-m minor] [-i id] [-p pid] [-t type] [-f file]\n");
+ "usage: list [-h] [-p pid] [-m minor] [-t type] [-f file]\n");
+}
+
+static void
+tap_ctl_list_row(tap_list_t *entry)
+{
+ char minor_str[10] = "-";
+ char state_str[10] = "-";
+ char pid_str[10] = "-";
+
+ if (entry->pid != -1)
+ sprintf(pid_str, "%d", entry->pid);
+
+ if (entry->minor != -1)
+ sprintf(minor_str, "%d", entry->minor);
+
+ if (entry->state != -1)
+ sprintf(state_str, "%x", entry->state);
+
+ printf("%8s %2s %4s %10s %s\n",
+ pid_str, minor_str, state_str,
+ entry->type ? : "-", entry->path ? : "-");
+}
+
+static void
+tap_ctl_list_dict(tap_list_t *entry)
+{
+ int d = 0;
+
+ if (entry->pid != -1) {
+ if (d) putc(' ', stdout);
+ d = printf("pid=%d", entry->pid);
+ }
+
+ if (entry->minor != -1) {
+ if (d) putc(' ', stdout);
+ d = printf("minor=%d", entry->minor);
+ }
+
+ if (entry->state != -1) {
+ if (d) putc(' ', stdout);
+ d = printf("state=%d", entry->state);
+ }
+
+ if (entry->type && entry->path) {
+ if (d) putc(' ', stdout);
+ d = printf("args=%s:%s", entry->type, entry->path);
+ }
+
+ putc('\n', stdout);
}
int
tap_cli_list(int argc, char **argv)
{
tap_list_t **list, **_entry;
- int c, id, minor, err;
+ int c, minor, tty, err;
const char *type, *file;
pid_t pid;
if (err)
return -err;
- id = -1;
- minor = -1;
- pid = -1;
- type = NULL;
- file = NULL;
+ pid = -1;
+ minor = -1;
+ type = NULL;
+ file = NULL;
- while ((c = getopt(argc, argv, "m:i:p:t:f:h")) != -1) {
+ while ((c = getopt(argc, argv, "m:p:t:f:h")) != -1) {
switch (c) {
- case 'i':
- id = atoi(optarg);
- break;
case 'm':
minor = atoi(optarg);
break;
case 'f':
file = optarg;
break;
+ case '?':
+ goto usage;
case 'h':
tap_cli_list_usage(stdout);
return 0;
}
}
+ tty = isatty(STDOUT_FILENO);
+
for (_entry = list; *_entry != NULL; ++_entry) {
tap_list_t *entry = *_entry;
- char id_str[10] = "-";
- char minor_str[10] = "-";
- char state_str[10] = "-";
- char pid_str[10] = "-";
-
- if (id >= 0 && entry->id != id)
- continue;
if (minor >= 0 && entry->minor != minor)
continue;
if (file && entry->path && strcmp(entry->path, file))
continue;
- if (entry->id != -1)
- sprintf(id_str, "%d", entry->id);
+ if (tty)
+ tap_ctl_list_row(entry);
+ else
+ tap_ctl_list_dict(entry);
+ }
- if (entry->pid != -1)
- sprintf(pid_str, "%d", entry->pid);
+ tap_ctl_free_list(list);
- if (entry->minor != -1)
- sprintf(minor_str, "%d", entry->minor);
+ return 0;
- if (entry->state != -1)
- sprintf(state_str, "%x", entry->state);
+usage:
+ tap_cli_list_usage(stderr);
+ return EINVAL;
+}
- printf("%-3s %2s %8s %4s %10s %s\n",
- minor_str, id_str, pid_str, state_str,
- entry->type ? : "-", entry->path ? : "-");
+static void
+tap_cli_allocate_usage(FILE *stream)
+{
+ fprintf(stream, "usage: allocate [-d device name]>\n");
+}
+
+static int
+tap_cli_allocate(int argc, char **argv)
+{
+ char *devname;
+ int c, minor, err;
+
+ devname = NULL;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "d:h")) != -1) {
+ switch (c) {
+ case 'd':
+ devname = optarg;
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_allocate_usage(stdout);
+ return 0;
+ }
}
- tap_ctl_free_list(list);
+ err = tap_ctl_allocate(&minor, &devname);
+ if (!err)
+ printf("%s\n", devname);
+
+ return err;
+
+usage:
+ tap_cli_allocate_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_free_usage(FILE *stream)
+{
+ fprintf(stream, "usage: free <-m minor>\n");
+}
+
+static int
+tap_cli_free(int argc, char **argv)
+{
+ int c, minor;
+
+ minor = -1;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "m:h")) != -1) {
+ switch (c) {
+ case 'm':
+ minor = atoi(optarg);
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_free_usage(stdout);
+ return 0;
+ }
+ }
+
+ if (minor == -1)
+ goto usage;
+
+ return tap_ctl_free(minor);
+
+usage:
+ tap_cli_free_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_create_usage(FILE *stream)
+{
+ fprintf(stream, "usage: create <-a args> [-d device name]\n");
+}
+
+static int
+tap_cli_create(int argc, char **argv)
+{
+ int c, err;
+ char *args, *devname;
+
+ args = NULL;
+ devname = NULL;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "a:d:h")) != -1) {
+ switch (c) {
+ case 'a':
+ args = optarg;
+ break;
+ case 'd':
+ devname = optarg;
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_create_usage(stdout);
+ return 0;
+ }
+ }
+
+ if (!args)
+ goto usage;
+
+ err = tap_ctl_create(args, &devname);
+ if (!err)
+ printf("%s\n", devname);
+
+ return err;
+
+usage:
+ tap_cli_create_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_destroy_usage(FILE *stream)
+{
+ fprintf(stream, "usage: destroy <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_destroy(int argc, char **argv)
+{
+ int c, pid, minor;
+
+ pid = -1;
+ minor = -1;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+ switch (c) {
+ case 'p':
+ pid = atoi(optarg);
+ break;
+ case 'm':
+ minor = atoi(optarg);
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_destroy_usage(stdout);
+ return 0;
+ }
+ }
+
+ if (pid == -1 || minor == -1)
+ goto usage;
+
+ return tap_ctl_destroy(pid, minor);
+
+usage:
+ tap_cli_destroy_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_spawn_usage(FILE *stream)
+{
+ fprintf(stream, "usage: spawn\n");
+}
+
+static int
+tap_cli_spawn(int argc, char **argv)
+{
+ int c;
+ pid_t task;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "h")) != -1) {
+ switch (c) {
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_spawn_usage(stdout);
+ return 0;
+ }
+ }
+ task = tap_ctl_spawn();
+ if (task < 0) {
+ printf("spawn failed: %d\n", errno);
+ return task;
+ }
+
+ printf("tapdisk spawned with pid %d\n", task);
return 0;
usage:
- tap_cli_list_usage(stderr);
+ tap_cli_spawn_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_attach_usage(FILE *stream)
+{
+ fprintf(stream, "usage: attach <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_attach(int argc, char **argv)
+{
+ int c, pid, minor;
+
+ pid = -1;
+ minor = -1;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+ switch (c) {
+ case 'p':
+ pid = atoi(optarg);
+ break;
+ case 'm':
+ minor = atoi(optarg);
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_attach_usage(stderr);
+ return 0;
+ }
+ }
+
+ if (pid == -1 || minor == -1)
+ goto usage;
+
+ return tap_ctl_attach(pid, minor);
+
+usage:
+ tap_cli_attach_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_detach_usage(FILE *stream)
+{
+ fprintf(stream, "usage: detach <-p pid> <-m minor>\n");
+}
+
+static int
+tap_cli_detach(int argc, char **argv)
+{
+ int c, pid, minor;
+
+ pid = -1;
+ minor = -1;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "p:m:h")) != -1) {
+ switch (c) {
+ case 'p':
+ pid = atoi(optarg);
+ break;
+ case 'm':
+ minor = atoi(optarg);
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_detach_usage(stdout);
+ return 0;
+ }
+ }
+
+ if (pid == -1 || minor == -1)
+ goto usage;
+
+ return tap_ctl_detach(pid, minor);
+
+usage:
+ tap_cli_detach_usage(stderr);
+ return EINVAL;
+}
+
+static void
+tap_cli_close_usage(FILE *stream)
+{
+ fprintf(stream, "usage: close <-p pid> <-m minor> [-f force]\n");
+}
+
+static int
+tap_cli_close(int argc, char **argv)
+{
+ int c, pid, minor, force;
+
+ pid = -1;
+ minor = -1;
+ force = 0;
+
+ optind = 0;
+ while ((c = getopt(argc, argv, "p:m:fh")) != -1) {
+ switch (c) {
+ case 'p':
+ pid = atoi(optarg);
+ break;
+ case 'm':
+ minor = atoi(optarg);
+ break;
+ case 'f':
+ force = -1;
+ break;
+ case '?':
+ goto usage;
+ case 'h':
+ tap_cli_close_usage(stdout);
+ return 0;
+ }
+ }
+
+ if (pid == -1 || minor == -1)
+ goto usage;
+
+ return tap_ctl_close(pid, minor, force);
+
+usage:
+ tap_cli_close_usage(stderr);
return EINVAL;
}
static void
tap_cli_pause_usage(FILE *stream)
{
- fprintf(stream, "usage: pause <-i id> <-m minor>\n");
+ fprintf(stream, "usage: pause <-p pid> <-m minor>\n");
}
static int
tap_cli_pause(int argc, char **argv)
{
- int c, id, minor;
+ int c, pid, minor;
- id = -1;
+ pid = -1;
minor = -1;
optind = 0;
- while ((c = getopt(argc, argv, "i:m:h")) != -1) {
+ while ((c = getopt(argc, argv, "p:m:h")) != -1) {
switch (c) {
- case 'i':
- id = atoi(optarg);
+ case 'p':
+ pid = atoi(optarg);
break;
case 'm':
minor = atoi(optarg);
break;
+ case '?':
+ goto usage;
case 'h':
tap_cli_pause_usage(stdout);
return 0;
}
}
- if (id == -1 || minor == -1) {
- tap_cli_pause_usage(stderr);
- return EINVAL;
- }
+ if (pid == -1 || minor == -1)
+ goto usage;
- return tap_ctl_pause(id, minor);
+ return tap_ctl_pause(pid, minor);
+
+usage:
+ tap_cli_pause_usage(stderr);
+ return EINVAL;
}
static void
int
tap_cli_unpause(int argc, char **argv)
{
- char *args;
- int c, id, minor, type;
+ const char *args;
+ int c, pid, minor;
- id = -1;
+ pid = -1;
minor = -1;
args = NULL;
optind = 0;
- while ((c = getopt(argc, argv, "i:m:a:h")) != -1) {
+ while ((c = getopt(argc, argv, "p:m:a:h")) != -1) {
switch (c) {
- case 'i':
- id = atoi(optarg);
+ case 'p':
+ pid = atoi(optarg);
break;
case 'm':
minor = atoi(optarg);
case 'a':
args = optarg;
break;
+ case '?':
+ goto usage;
case 'h':
tap_cli_unpause_usage(stdout);
return 0;
}
}
- if (id == -1 || minor == -1)
+ if (pid == -1 || minor == -1)
goto usage;
- return tap_ctl_unpause(id, minor, args);
+ return tap_ctl_unpause(pid, minor, args);
usage:
tap_cli_unpause_usage(stderr);
static void
tap_cli_major_usage(FILE *stream)
{
- fprintf(stream, "usage: unpause <-i id> <-m minor> <-t type> <-f file>\n");
+ fprintf(stream, "usage: major [-h]\n");
}
static int
case 'c':
chr = 1;
break;
+ case '?':
+ goto usage;
case 'h':
tap_cli_major_usage(stdout);
return 0;
static void
tap_cli_open_usage(FILE *stream)
{
- fprintf(stream, "usage: open <-i id> <-m minor> <-a args>\n");
+ fprintf(stream, "usage: open <-p pid> <-m minor> <-a args>\n");
}
static int
tap_cli_open(int argc, char **argv)
{
const char *args;
- int c, id, minor;
+ int c, pid, minor;
- id = -1;
+ pid = -1;
minor = -1;
args = NULL;
optind = 0;
- while ((c = getopt(argc, argv, "i:m:a:h")) != -1) {
+ while ((c = getopt(argc, argv, "a:m:p:h")) != -1) {
switch (c) {
- case 'i':
- id = atoi(optarg);
+ case 'p':
+ pid = atoi(optarg);
break;
case 'm':
minor = atoi(optarg);
case 'a':
args = optarg;
break;
+ case '?':
+ goto usage;
case 'h':
tap_cli_open_usage(stdout);
return 0;
}
}
- if (id == -1 || minor == -1 || !args)
+ if (pid == -1 || minor == -1 || !args)
goto usage;
- return tap_ctl_open(id, minor, args);
+ return tap_ctl_open(pid, minor, args);
usage:
tap_cli_open_usage(stderr);
return EINVAL;
}
+static void
+tap_cli_check_usage(FILE *stream)
+{
+ fprintf(stream, "usage: check\n"
+ "(checks whether environment is suitable for tapdisk2)\n");
+}
+
+static int
+tap_cli_check(int argc, char **argv)
+{
+ int err;
+ const char *msg;
+
+ if (argc != 1)
+ goto usage;
+
+ err = tap_ctl_check(&msg);
+ printf("%s\n", msg);
+
+ return err;
+
+usage:
+ tap_cli_check_usage(stderr);
+ return EINVAL;
+}
+
struct command commands[] = {
{ .name = "list", .func = tap_cli_list },
- { .name = "allocate", .func = tap_ctl_allocate },
- { .name = "free", .func = tap_ctl_free },
- { .name = "create", .func = tap_ctl_create },
- { .name = "destroy", .func = tap_ctl_destroy },
- { .name = "spawn", .func = tap_ctl_spawn },
- { .name = "attach", .func = tap_ctl_attach },
- { .name = "detach", .func = tap_ctl_detach },
+ { .name = "allocate", .func = tap_cli_allocate },
+ { .name = "free", .func = tap_cli_free },
+ { .name = "create", .func = tap_cli_create },
+ { .name = "destroy", .func = tap_cli_destroy },
+ { .name = "spawn", .func = tap_cli_spawn },
+ { .name = "attach", .func = tap_cli_attach },
+ { .name = "detach", .func = tap_cli_detach },
{ .name = "open", .func = tap_cli_open },
- { .name = "close", .func = tap_ctl_close },
+ { .name = "close", .func = tap_cli_close },
{ .name = "pause", .func = tap_cli_pause },
{ .name = "unpause", .func = tap_cli_unpause },
{ .name = "major", .func = tap_cli_major },
+ { .name = "check", .func = tap_cli_check },
};
#define print_commands() \
main(int argc, char *argv[])
{
char **cargv;
+ const char *msg;
struct command *cmd;
int cargc, i, cnt, ret;
rlim.rlim_cur = RLIM_INFINITY;
rlim.rlim_max = RLIM_INFINITY;
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
- fprintf(stderr, "setrlimit failed: %d\n", errno);
+ PERROR("setrlimit failed");
#endif
ret = 0;
cargc = argc - 1;
cmd = get_command(argv[1]);
if (!cmd) {
- fprintf(stderr, "invalid COMMAND %s\n", argv[1]);
+ EPRINTF("invalid COMMAND %s", argv[1]);
help();
}
+ ret = tap_ctl_check(&msg);
+ if (ret) {
+ printf("%s\n", msg);
+ return ret;
+ }
+
cargv = malloc(sizeof(char *) * cargc);
if (!cargv)
exit(ENOMEM);
#define __TAP_CTL_H__
#include <syslog.h>
+#include <errno.h>
#include "tapdisk-message.h"
extern int tap_ctl_debug;
+#ifdef TAPCTL
#define DBG(_f, _a...) \
do { \
if (tap_ctl_debug) \
#define DPRINTF(_f, _a...) syslog(LOG_INFO, _f, ##_a)
#define EPRINTF(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a)
+#define PERROR(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f ": %s", __func__, ##_a, \
+ strerror(errno))
+#endif
+
+void tap_ctl_version(int *major, int *minor);
+int tap_ctl_kernel_version(int *major, int *minor);
+int tap_ctl_check_blktap(const char **message);
+int tap_ctl_check_version(const char **message);
+int tap_ctl_check(const char **message);
int tap_ctl_connect(const char *path, int *socket);
int tap_ctl_connect_id(int id, int *socket);
int tap_ctl_read_message(int fd, tapdisk_message_t *message, int timeout);
int tap_ctl_write_message(int fd, tapdisk_message_t *message, int timeout);
int tap_ctl_send_and_receive(int fd, tapdisk_message_t *message, int timeout);
-int tap_ctl_connect_send_and_receive(int id, tapdisk_message_t *message, int timeout);
+int tap_ctl_connect_send_and_receive(int id,
+ tapdisk_message_t *message, int timeout);
char *tap_ctl_socket_name(int id);
typedef struct {
int tap_ctl_list(tap_list_t ***list);
void tap_ctl_free_list(tap_list_t **list);
-int tap_ctl_allocate(int argc, char **argv);
-int _tap_ctl_allocate(int *minor, char **devname);
-
-int tap_ctl_free(int argc, char **argv);
-int _tap_ctl_free(const int minor);
-
-int tap_ctl_create(int argc, char **argv);
-int _tap_ctl_create(const char *params, char **devname);
+int tap_ctl_allocate(int *minor, char **devname);
+int tap_ctl_free(const int minor);
-int tap_ctl_destroy(int argc, char **argv);
-int _tap_ctl_destroy(const int id, const int minor);
+int tap_ctl_create(const char *params, char **devname);
+int tap_ctl_destroy(const int id, const int minor);
-int tap_ctl_spawn(int argc, char **argv);
-int _tap_ctl_spawn(const int id);
-pid_t _tap_ctl_get_pid(const int id);
+int tap_ctl_spawn(void);
+pid_t tap_ctl_get_pid(const int id);
-int tap_ctl_attach(int argc, char **argv);
-int _tap_ctl_attach(const int id, const int minor);
-
-int tap_ctl_detach(int argc, char **argv);
-int _tap_ctl_detach(const int id, const int minor);
+int tap_ctl_attach(const int id, const int minor);
+int tap_ctl_detach(const int id, const int minor);
int tap_ctl_open(const int id, const int minor, const char *params);
-
-int tap_ctl_close(int argc, char **argv);
-int _tap_ctl_close(const int id, const int minor, const int force);
+int tap_ctl_close(const int id, const int minor, const int force);
int tap_ctl_pause(const int id, const int minor);
-
-int tap_ctl_unpause(const int id, const int minor, const char *args);
+int tap_ctl_unpause(const int id, const int minor, const char *params);
int tap_ctl_blk_major(void);
#include <stdarg.h>
#include <xs.h>
+#define TAPDISK
#include "xs_api.h"
#include "blktaplib.h"
CFLAGS += -I../include
CFLAGS += -D_GNU_SOURCE
CFLAGS += -DUSE_NFS_LOCKS
+CFLAGS += -DTAPDISK
LIBS += -lrt
TAP-OBJS += tapdisk-logfile.o
TAP-OBJS += tapdisk-log.o
TAP-OBJS += tapdisk-utils.o
+TAP-OBJS += tapdisk-disktype.o
TAP-OBJS += tapdisk-syslog.o
TAP-OBJS += io-optimize.o
TAP-OBJS += lock.o
static void
tapdisk_control_initialize(void)
{
- td_control.uuid = -1;
td_control.socket = -1;
td_control.event_id = -1;
tapdisk_control_allocate_connection(int fd)
{
struct tapdisk_control_connection *connection;
+ size_t sz;
connection = calloc(1, sizeof(*connection));
if (!connection) {
- EPRINTF("failed to allocate new connection\n");
+ EPRINTF("calloc");
return NULL;
}
goto out;
}
- if (!vbd->name) {
- err = -EBADF;
- goto out;
- }
-
if (!list_empty(&vbd->pending_requests)) {
err = -EAGAIN;
goto out;
tapdisk_control_close_connection(connection);
}
-static void
-tapdisk_control_close_vbd(struct tapdisk_control_connection *connection,
- tapdisk_message_t *request)
-{
- int err;
- td_vbd_t *vbd;
- tapdisk_message_t response;
-
- memset(&response, 0, sizeof(response));
-
- response.type = TAPDISK_MESSAGE_CLOSE_RSP;
-
- vbd = tapdisk_server_get_vbd(request->cookie);
- if (!vbd)
- err = EINVAL;
- else
- err = tapdisk_vbd_close(vbd);
-
- response.cookie = (vbd ? vbd->uuid : -1);
- response.u.response.error = err;
- tapdisk_control_write_message(connection->socket, &response, 2);
- tapdisk_control_close_connection(connection);
-}
-
static void
tapdisk_control_handle_request(event_id_t id, char mode, void *private)
{
}
static int
-tapdisk_control_create_socket(const int uuid, const char *socket_path)
+tapdisk_control_create_socket(char **socket_path)
{
int err, flags;
struct sockaddr_un saddr;
return err;
}
+ err = asprintf(&td_control.path, "%s/%s%d",
+ BLKTAP2_CONTROL_DIR, BLKTAP2_CONTROL_SOCKET, getpid());
+ if (err == -1) {
+ td_control.path = NULL;
+ err = (errno ? : ENOMEM);
+ goto fail;
+ }
+
+ if (unlink(td_control.path) && errno != ENOENT) {
+ err = errno;
+ EPRINTF("failed to unlink %s: %d\n", td_control.path, errno);
+ goto fail;
+ }
+
td_control.socket = socket(AF_UNIX, SOCK_STREAM, 0);
if (td_control.socket == -1) {
err = errno;
}
memset(&saddr, 0, sizeof(saddr));
- strncpy(saddr.sun_path, socket_path, sizeof(saddr.sun_path));
+ strncpy(saddr.sun_path, td_control.path, sizeof(saddr.sun_path));
saddr.sun_family = AF_UNIX;
err = bind(td_control.socket,
(const struct sockaddr *)&saddr, sizeof(saddr));
if (err == -1) {
err = errno;
- EPRINTF("failed to bind to %s: %d\n", socket_path, err);
+ EPRINTF("failed to bind to %s: %d\n", saddr.sun_path, err);
goto fail;
}
goto fail;
}
- td_control.path = strdup(saddr.sun_path);
- if (!td_control.path) {
- err = errno;
- EPRINTF("failed to dup socket path: %d\n", err);
- goto fail_unlink;
- }
-
err = tapdisk_server_register_event(SCHEDULER_POLL_READ_FD,
td_control.socket, 0,
tapdisk_control_accept, NULL);
goto fail;
}
- td_control.uuid = uuid;
td_control.event_id = err;
+ *socket_path = td_control.path;
return 0;
fail:
tapdisk_control_close();
return err;
-
-fail_unlink:
- unlink(saddr.sun_path);
- goto fail;
}
int
-tapdisk_control_open(const int uuid, const char *control)
+tapdisk_control_open(char **path)
{
int err;
tapdisk_control_initialize();
- return tapdisk_control_create_socket(uuid, control);
+ return tapdisk_control_create_socket(path);
}
#ifndef __TAPDISK_CONTROL_H__
#define __TAPDISK_CONTROL_H__
-int tapdisk_control_open(const int uuid, const char *path);
+int tapdisk_control_open(char **path);
void tapdisk_control_close(void);
#endif
}
int
-td_open(td_image_t *image)
+__td_open(td_image_t *image, td_disk_info_t *info)
{
int err;
td_driver_t *driver;
image->storage);
if (!driver)
return -ENOMEM;
+
+ if (info) /* pre-seed driver->info for virtual drivers */
+ driver->info = *info;
}
if (!td_flag_test(driver->state, TD_DRIVER_OPEN)) {
return 0;
}
+int
+td_open(td_image_t *image)
+{
+ return __td_open(image, NULL);
+}
+
int
td_close(td_image_t *image)
{
#include "tapdisk-queue.h"
int td_open(td_image_t *);
+int __td_open(td_image_t *, td_disk_info_t *);
int td_load(td_image_t *);
int td_close(td_image_t *);
int td_get_parent_id(td_image_t *, td_disk_id_t *);
if (xfsz_error_sent)
break;
- tapdisk_server_send_error("received SIGXFSZ, closing queues");
xfsz_error_sent = 1;
break;
int
tapdisk_server_init(void)
{
-
+ memset(&server, 0, sizeof(server));
INIT_LIST_HEAD(&server.vbds);
scheduler_initialize(&server.scheduler);
*/
#include <stdio.h>
#include <errno.h>
+#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
static void
usage(const char *app, int err)
{
- fprintf(stderr,
- "usage: %s [-h] [-l <syslog>] "
- "-u <uuid> -c <control socket>\n", app);
+ fprintf(stderr, "usage: %s <-u uuid> <-c control socket>\n", app);
exit(err);
}
main(int argc, char *argv[])
{
char *control;
- int c, uuid, err, nodaemon;
- const char *facility;
+ int c, err, nodaemon;
- uuid = -1;
control = NULL;
- facility = "daemon";
nodaemon = 0;
- while ((c = getopt(argc, argv, "l:u:c:Dh")) != -1) {
+ while ((c = getopt(argc, argv, "Dh")) != -1) {
switch (c) {
- case 'l':
- facility = optarg;
- break;
- case 'u':
- uuid = atoi(optarg);
- break;
- case 'c':
- control = optarg;
- break;
case 'D':
nodaemon = 1;
break;
case 'h':
usage(argv[0], 0);
+ break;
default:
usage(argv[0], EINVAL);
}
}
- if (optind != argc || uuid == -1 || !control)
+ if (optind != argc)
usage(argv[0], EINVAL);
chdir("/");
- tapdisk_start_logging("tapdisk2", facility);
+ tapdisk_start_logging("tapdisk2", NULL);
err = tapdisk_server_init();
if (err) {
goto out;
}
- err = tapdisk_control_open(uuid, control);
+ if (!nodaemon) {
+ err = daemon(0, 1);
+ if (err) {
+ DPRINTF("failed to daemonize: %d\n", errno);
+ goto out;
+ }
+ }
+
+ err = tapdisk_control_open(&control);
if (err) {
DPRINTF("failed to open control socket: %d\n", err);
goto out;
}
+ fprintf(stdout, "%s\n", control);
+ fflush(stdout);
+
if (!nodaemon) {
- err = daemon(0, 0);
- if (err) {
- DPRINTF("failed to daemonize: %d\n", errno);
- goto out;
+ int fd;
+
+ fd = open("/dev/null", O_RDWR);
+ if (fd != -1) {
+ dup2(fd, STDIN_FILENO);
+ dup2(fd, STDOUT_FILENO);
+ dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ close(fd);
}
}
#include <xenctrl.h>
#include <xen/io/blkif.h>
+#ifdef TAPDISK
#if 1
#define DPRINTF(_f, _a...) syslog(LOG_INFO, _f, ##_a)
#else
#define EPRINTF(_f, _a...) syslog(LOG_ERR, "tap-err:%s: " _f, __func__, ##_a)
#define PERROR(_f, _a...) EPRINTF(_f ": %s", ##_a, strerror(errno))
+#endif
#define BLK_RING_SIZE __RING_SIZE((blkif_sring_t *)0, XC_PAGE_SIZE)
uint8_t storage;
uint32_t devnum;
uint32_t domid;
- uint16_t path_len;
char path[TAPDISK_MESSAGE_MAX_PATH_LENGTH];
};