diff -r 538eaa381f54 tools/blktap2/Makefile --- a/tools/blktap2/Makefile Tue Jun 16 14:54:26 2009 -0700 +++ b/tools/blktap2/Makefile Tue Jun 16 17:52:43 2009 -0700 @@ -10,7 +10,6 @@ SUBDIRS-y += vhd SUBDIRS-y += parallax SUBDIRS-y += drivers -SUBDIRS-y += daemon clean: rm -rf *.a *.so *.o *.rpm $(LIB) *~ $(DEPS) TAGS diff -r 538eaa381f54 tools/blktap2/daemon/Makefile --- a/tools/blktap2/daemon/Makefile Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -XEN_ROOT=../../../ -BLKTAP_ROOT := .. -include $(XEN_ROOT)/tools/Rules.mk - -SUBDIRS-y := -SUBDIRS-y += lib - -IBIN = blktapctrl -INST_DIR = $(SBINDIR) - -LIBS := -lxenstore -LIBS += -Llib -LIBS += -lblktap -LIBS += -lxenctrl - -ifneq ($(USE_SYSTEM_LIBRARIES),y) -INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE) -LIBS += -L $(XEN_LIBXC) -L $(XEN_XENSTORE) -endif - -OBJS := tapdisk-dispatch-common.o -OBJS += tapdisk-channel.o - -CFLAGS += -Werror -CFLAGS += -Wno-unused -CFLAGS += -fno-strict-aliasing -fPIC -CFLAGS += -Ilib -I../include -I../drivers -I../../include $(INCLUDES) -CFLAGS += -D_GNU_SOURCE -CFLAGS += -g - -# Get gcc to generate the dependencies for us. -CFLAGS += -Wp,-MD,.$(@F).d -DEPS = .*.d - -all: subdirs-all $(IBIN) - -LIBS_DEPENDS := lib/libblktap.a lib/libblktap.so -$(LIBS_DEPENDS):subdirs-all - -blktapctrl: tapdisk-daemon.c $(OBJS) $(LIBS_DEPENDS) - $(CC) $(CFLAGS) -o blktapctrl tapdisk-daemon.c $(LDFLAGS) $(LIBS) $(OBJS) - -install: all - $(MAKE) subdirs-install - $(INSTALL_DIR) -p $(DESTDIR)$(INST_DIR) - $(INSTALL_PROG) $(IBIN) $(DESTDIR)$(INST_DIR) - -clean: subdirs-clean - rm -rf *.o *~ $(IBIN) $(DEPS) xen TAGS - -.PHONY: all clean install blktapctrl - --include $(DEPS) - diff -r 538eaa381f54 tools/blktap2/daemon/lib/Makefile --- a/tools/blktap2/daemon/lib/Makefile Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -XEN_ROOT=../../../../ -BLKTAP_ROOT := ../../ -include $(XEN_ROOT)/tools/Rules.mk - -MAJOR = 3.1 -MINOR = 0 -SONAME = libblktap.so.$(MAJOR) - -BLKTAP_INSTALL_DIR = /usr/sbin - -LIBS := -lxenstore - -ifneq ($(USE_SYSTEM_LIBRARIES),y) -INCLUDES += -I $(XEN_LIBXC) -I $(XEN_XENSTORE) -LIBS += -L$(XEN_XENSTORE) -endif - -SRCS := -SRCS += xs_api.c -CFLAGS += -Werror -CFLAGS += -Wno-unused -CFLAGS += -fno-strict-aliasing -fPIC -# get asprintf(): -CFLAGS += -D _GNU_SOURCE -CFLAGS += -g -CFLAGS += -I../../include -I../../../include/ $(INCLUDES) - - -# Get gcc to generate the dependencies for us. -CFLAGS += -Wp,-MD,.$(@F).d -DEPS = .*.d - -OBJS = $(patsubst %.c,%.o,$(SRCS)) -IBINS := - -LIB = libblktap.a libblktap.so.$(MAJOR).$(MINOR) - -.PHONY: all -all: build - -.PHONY: build -build: libblktap.a - -.PHONY: libblktap -libblktap: libblktap.a - -install: all - $(INSTALL_DIR) -p $(DESTDIR)$(LIBDIR) - $(INSTALL_DATA) $(LIB) $(DESTDIR)$(LIBDIR) - ln -sf libblktap.so.$(MAJOR).$(MINOR) $(DESTDIR)$(LIBDIR)/libblktap.so.$(MAJOR) - ln -sf libblktap.so.$(MAJOR) $(DESTDIR)$(LIBDIR)/libblktap.so - -clean: - rm -rf *.a *.so* *.o *.rpm $(LIB) *~ $(DEPS) xen TAGS - -libblktap.a: $(OBJS) - $(CC) $(CFLAGS) -Wl,$(SONAME_LDFLAG) -Wl,$(SONAME) $(SHLIB_CFLAGS) \ - $(LDFLAGS) -o libblktap.so.$(MAJOR).$(MINOR) $^ $(LIBS) - ln -sf libblktap.so.$(MAJOR).$(MINOR) libblktap.so.$(MAJOR) - ln -sf libblktap.so.$(MAJOR) libblktap.so - $(AR) rc $@ libblktap.so - -.PHONY: TAGS all build clean install libblktap - -TAGS: - etags -t $(SRCS) *.h - --include $(DEPS) - diff -r 538eaa381f54 tools/blktap2/daemon/lib/xs_api.c --- a/tools/blktap2/daemon/lib/xs_api.c Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,323 +0,0 @@ -/* - * xs_api.c - * - * blocktap interface functions to xenstore - * - * (c) 2005 Andrew Warfield and Julian Chesterfield - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "xs_api.h" -#include "blktaplib.h" - -#define DOMNAME "Domain-0" -#define BASE_DEV_VAL 2048 - -static LIST_HEAD(watches); - -int -xs_gather(struct xs_handle *xs, const char *dir, ...) -{ - va_list ap; - const char *name; - char *path, **e; - int ret = 0, num,i; - unsigned int len; - xs_transaction_t xth; - -again: - if ((xth = xs_transaction_start(xs)) == XBT_NULL) { - DPRINTF("unable to start xs trasanction\n"); - ret = ENOMEM; - return ret; - } - - va_start(ap, dir); - while ((ret == 0) && (name = va_arg(ap, char *)) != NULL) { - char *p; - const char *fmt = va_arg(ap, char *); - void *result = va_arg(ap, void *); - - if (asprintf(&path, "%s/%s", dir, name) == -1) { - EPRINTF("allocation error in xs_gather!\n"); - ret = ENOMEM; - break; - } - - p = xs_read(xs, xth, path, &len); - free(path); - - if (!p) { - ret = ENOENT; - break; - } - - if (fmt) { - if (sscanf(p, fmt, result) == 0) - ret = EINVAL; - free(p); - } else - *(char **)result = p; - } - - va_end(ap); - - if (!xs_transaction_end(xs, xth, ret)) { - if (ret == 0 && errno == EAGAIN) - goto again; - else - ret = errno; - } - - return ret; -} - -/* Single printf and write: returns -errno or 0. */ -int -xs_printf(struct xs_handle *h, const char *dir, - const char *node, const char *fmt, ...) -{ - int ret; - va_list ap; - char *buf, *path; - - va_start(ap, fmt); - ret = vasprintf(&buf, fmt, ap); - va_end(ap); - - if (ret == -1) - return 0; - - ret = asprintf(&path, "%s/%s", dir, node); - if (ret == -1) { - free(buf); - return 0; - } - - ret = xs_write(h, XBT_NULL, path, buf, strlen(buf)+1); - - free(buf); - free(path); - - return ret; -} - -int -xs_exists(struct xs_handle *h, const char *path) -{ - char **d; - unsigned int num; - xs_transaction_t xth; - - if ((xth = xs_transaction_start(h)) == XBT_NULL) { - EPRINTF("unable to start xs trasanction\n"); - return 0; - } - - d = xs_directory(h, xth, path, &num); - xs_transaction_end(h, xth, 0); - if (!d) - return 0; - - free(d); - return 1; -} - - - -/** - * This assumes that the domain name we are looking for is unique. - * Name parameter Domain-0 - */ -char * -get_dom_domid(struct xs_handle *h) -{ - int i; - xs_transaction_t xth; - unsigned int num, len; - char *val, *path, *domid, **e; - - e = NULL; - domid = NULL; - - if ((xth = xs_transaction_start(h)) == XBT_NULL) { - EPRINTF("unable to start xs trasanction\n"); - return NULL; - } - - e = xs_directory(h, xth, "/local/domain", &num); - if (e == NULL) - goto done; - - for (i = 0; (i < num) && (domid == NULL); i++) { - if (asprintf(&path, "/local/domain/%s/name", e[i]) == -1) - break; - - val = xs_read(h, xth, path, &len); - free(path); - if (val == NULL) - continue; - - if (strcmp(val, DOMNAME) == 0) { - /* match! */ - if (asprintf(&path, - "/local/domain/%s/domid", e[i]) == -1) { - free(val); - break; - } - domid = xs_read(h, xth, path, &len); - free(path); - } - free(val); - } - - done: - xs_transaction_end(h, xth, 0); - free(e); - return domid; -} - -/* - * a little paranoia: we don't just trust token - */ -static struct xenbus_watch *find_watch(const char *token) -{ - int ret; - long nonce; - unsigned long addr; - struct xenbus_watch *i, *cmp; - - ret = sscanf(token, "%lX:%lX", &addr, &nonce); - if (ret != 2) { - EPRINTF("invalid watch token %s\n", token); - return NULL; - } - - cmp = (struct xenbus_watch *)addr; - list_for_each_entry(i, &watches, list) - if (i == cmp && i->nonce == nonce) - return i; - - return NULL; -} - -/* - * Register callback to watch this node; - * like xs_watch, return 0 on failure - */ -int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch) -{ - /* Pointer in ascii is the token. */ - char token[(sizeof(watch) + sizeof(long)) * 2 + 2]; - - /* 1-second granularity should suffice here */ - watch->nonce = time(NULL); - - sprintf(token, "%lX:%lX", (long)watch, watch->nonce); - if (find_watch(token)) { - EPRINTF("watch collision!\n"); - return -EINVAL; - } - - if (!xs_watch(h, watch->node, token)) { - EPRINTF("unable to set watch!\n"); - return -EINVAL; - } - - list_add(&watch->list, &watches); - - return 0; -} - -int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch) -{ - char token[(sizeof(watch) + sizeof(long)) * 2 + 2]; - - sprintf(token, "%lX:%lX", (long)watch, watch->nonce); - if (!find_watch(token)) { - EPRINTF("no such watch!\n"); - return -EINVAL; - } - - if (!xs_unwatch(h, watch->node, token)) - EPRINTF("XENBUS Failed to release watch %s\n", watch->node); - - list_del(&watch->list); - - return 0; -} - -/* - * re-register callbacks to all watches - */ -void reregister_xenbus_watches(struct xs_handle *h) -{ - struct xenbus_watch *watch; - char token[(sizeof(watch) + sizeof(long)) * 2 + 2]; - - list_for_each_entry(watch, &watches, list) { - sprintf(token, "%lX:%lX", (long)watch, watch->nonce); - xs_watch(h, watch->node, token); - } -} - -/* - * based on watch_thread() - */ -int xs_fire_next_watch(struct xs_handle *h) -{ - unsigned int num; - struct xenbus_watch *w; - char **res, *token, *node = NULL; - - res = xs_read_watch(h, &num); - if (res == NULL) - return -EAGAIN; /* in O_NONBLOCK, read_watch returns 0... */ - - node = res[XS_WATCH_PATH]; - token = res[XS_WATCH_TOKEN]; - DPRINTF("got watch %s on %s\n", token, node); - - w = find_watch(token); - if (w) - w->callback(h, w, node); - - DPRINTF("handled watch %s on %s\n", token, node); - - free(res); - - return 1; -} diff -r 538eaa381f54 tools/blktap2/daemon/lib/xs_api.h --- a/tools/blktap2/daemon/lib/xs_api.h Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * xs_api.h - * - * (c) 2005 Andrew Warfield and Julian Chesterfield - * - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -#ifndef _XS_API_H_ -#define _XS_API_H_ - -#include - -#include "list.h" - -struct xenbus_watch -{ - struct list_head list; - char *node; - void *data; - long nonce; - void (*callback) (struct xs_handle *h, - struct xenbus_watch *, - const char *node); -}; - -int xs_gather(struct xs_handle *xs, const char *dir, ...); -int xs_printf(struct xs_handle *h, const char *dir, const char *node, - const char *fmt, ...) __attribute__((format(printf, 4, 5))); -int xs_exists(struct xs_handle *h, const char *path); -char *get_dom_domid(struct xs_handle *h); -int convert_dev_name_to_num(char *name); - -int register_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch); -int unregister_xenbus_watch(struct xs_handle *h, struct xenbus_watch *watch); -void reregister_xenbus_watches(struct xs_handle *h); -int xs_fire_next_watch(struct xs_handle *h); - -#endif diff -r 538eaa381f54 tools/blktap2/daemon/tapdisk-channel.c --- a/tools/blktap2/daemon/tapdisk-channel.c Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1367 +0,0 @@ -/* 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "disktypes.h" -#include "tapdisk-dispatch.h" - -#define TAPDISK_CHANNEL_IDLE 1 -#define TAPDISK_CHANNEL_WAIT_PID 2 -#define TAPDISK_CHANNEL_WAIT_OPEN 3 -#define TAPDISK_CHANNEL_WAIT_PAUSE 4 -#define TAPDISK_CHANNEL_WAIT_RESUME 5 -#define TAPDISK_CHANNEL_WAIT_CLOSE 6 -#define TAPDISK_CHANNEL_CLOSED 7 - -static void tapdisk_channel_error(tapdisk_channel_t *, - const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -static void tapdisk_channel_fatal(tapdisk_channel_t *, - const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -static int tapdisk_channel_parse_params(tapdisk_channel_t *); -static void tapdisk_channel_pause_event(struct xs_handle *, - struct xenbus_watch *, - const char *); - -static int -tapdisk_channel_check_uuid(tapdisk_channel_t *channel) -{ - uint32_t uuid; - char *uuid_str; - - uuid_str = xs_read(channel->xsh, XBT_NULL, channel->uuid_str, NULL); - if (!uuid_str) - return -errno; - - uuid = strtoul(uuid_str, NULL, 10); - free(uuid_str); - - if (uuid != channel->cookie) - return -EINVAL; - - return 0; -} - -static inline int -tapdisk_channel_validate_watch(tapdisk_channel_t *channel, const char *path) -{ - int err, len; - - len = strsep_len(path, '/', 7); - if (len < 0) - return -EINVAL; - - err = tapdisk_channel_check_uuid(channel); - if (err) - return err; - - if (!xs_exists(channel->xsh, path)) - return -ENOENT; - - return 0; -} - -static inline int -tapdisk_channel_validate_message(tapdisk_channel_t *channel, - tapdisk_message_t *message) -{ - switch (message->type) { - case TAPDISK_MESSAGE_PID_RSP: - if (channel->state != TAPDISK_CHANNEL_WAIT_PID) - return -EINVAL; - break; - - case TAPDISK_MESSAGE_OPEN_RSP: - if (channel->state != TAPDISK_CHANNEL_WAIT_OPEN) - return -EINVAL; - break; - - case TAPDISK_MESSAGE_PAUSE_RSP: - if (channel->state != TAPDISK_CHANNEL_WAIT_PAUSE) - return -EINVAL; - break; - - case TAPDISK_MESSAGE_RESUME_RSP: - if (channel->state != TAPDISK_CHANNEL_WAIT_RESUME) - return -EINVAL; - break; - - case TAPDISK_MESSAGE_CLOSE_RSP: - if (channel->state != TAPDISK_CHANNEL_WAIT_CLOSE) - return -EINVAL; - break; - - case TAPDISK_MESSAGE_RUNTIME_ERROR: - /* - * runtime errors can be received at any time - * and should not affect the state machine - */ - return 0; - } - - channel->state = TAPDISK_CHANNEL_IDLE; - return 0; -} - -static int -tapdisk_channel_send_message(tapdisk_channel_t *channel, - tapdisk_message_t *message, int timeout) -{ - fd_set writefds; - struct timeval tv; - int ret, len, offset; - - tv.tv_sec = timeout; - tv.tv_usec = 0; - offset = 0; - len = sizeof(tapdisk_message_t); - - DPRINTF("%s: sending '%s' message to %d:%d\n", - channel->path, tapdisk_message_name(message->type), - channel->channel_id, channel->cookie); - - if (channel->state != TAPDISK_CHANNEL_IDLE && - message->type != TAPDISK_MESSAGE_CLOSE) - EPRINTF("%s: writing message to non-idle channel (%d)\n", - channel->path, channel->state); - - while (offset < len) { - FD_ZERO(&writefds); - FD_SET(channel->write_fd, &writefds); - - /* we don't bother reinitializing tv. at worst, it will wait a - * bit more time than expected. */ - - ret = select(channel->write_fd + 1, - NULL, &writefds, NULL, &tv); - if (ret == -1) - break; - else if (FD_ISSET(channel->write_fd, &writefds)) { - ret = write(channel->write_fd, - message + offset, len - offset); - if (ret <= 0) - break; - offset += ret; - } else - break; - } - - if (offset != len) { - EPRINTF("%s: error writing '%s' message to %d:%d\n", - channel->path, tapdisk_message_name(message->type), - channel->channel_id, channel->cookie); - return -EIO; - } - - switch (message->type) { - case TAPDISK_MESSAGE_PID: - channel->state = TAPDISK_CHANNEL_WAIT_PID; - break; - - case TAPDISK_MESSAGE_OPEN: - channel->state = TAPDISK_CHANNEL_WAIT_OPEN; - break; - - case TAPDISK_MESSAGE_PAUSE: - channel->state = TAPDISK_CHANNEL_WAIT_PAUSE; - break; - - case TAPDISK_MESSAGE_RESUME: - channel->state = TAPDISK_CHANNEL_WAIT_RESUME; - break; - - case TAPDISK_MESSAGE_CLOSE: - channel->state = TAPDISK_CHANNEL_WAIT_CLOSE; - break; - - default: - EPRINTF("%s: unrecognized message type %d\n", - channel->path, message->type); - } - - return 0; -} - -static void -__tapdisk_channel_error(tapdisk_channel_t *channel, - const char *fmt, va_list ap) -{ - int err; - char *dir, *buf, *message; - - err = vasprintf(&buf, fmt, ap); - if (err == -1) { - EPRINTF("failed to allocate error message\n"); - buf = NULL; - } - - if (buf) - message = buf; - else - message = "tapdisk error"; - - EPRINTF("%s: %s\n", channel->path, message); - - err = asprintf(&dir, "%s/tapdisk-error", channel->path); - if (err == -1) { - EPRINTF("%s: failed to write %s\n", __func__, message); - dir = NULL; - goto out; - } - - xs_write(channel->xsh, XBT_NULL, dir, message, strlen(message)); - -out: - free(dir); - free(buf); -} - -static void -tapdisk_channel_error(tapdisk_channel_t *channel, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - __tapdisk_channel_error(channel, fmt, ap); - va_end(ap); -} - -static void -tapdisk_channel_fatal(tapdisk_channel_t *channel, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - __tapdisk_channel_error(channel, fmt, ap); - va_end(ap); - - tapdisk_channel_close(channel); -} - -static int -tapdisk_channel_connect_backdev(tapdisk_channel_t *channel) -{ - int err, major, minor; - char *s, *path, *devname; - - s = NULL; - path = NULL; - devname = NULL; - - err = ioctl(channel->blktap_fd, - BLKTAP_IOCTL_BACKDEV_SETUP, channel->minor); - if (err) { - err = -errno; - goto fail; - } - - err = asprintf(&path, "%s/backdev-node", channel->path); - if (err == -1) { - path = NULL; - err = -ENOMEM; - goto fail; - } - - s = xs_read(channel->xsh, XBT_NULL, path, NULL); - if (!s) { - err = -errno; - goto fail; - } - - err = sscanf(s, "%d:%d", &major, &minor); - if (err != 2) { - err = -EINVAL; - goto fail; - } - - err = asprintf(&devname,"%s/%s%d", - BLKTAP_DEV_DIR, BACKDEV_NAME, minor); - if (err == -1) { - devname = NULL; - err = -ENOMEM; - goto fail; - } - - err = make_blktap_device(devname, major, minor, S_IFBLK | 0600); - if (err) - goto fail; - - free(path); - err = asprintf(&path, "%s/backdev-path", channel->path); - if (err == -1) { - path = NULL; - err = -ENOMEM; - goto fail; - } - - err = xs_write(channel->xsh, XBT_NULL, path, devname, strlen(devname)); - if (err == 0) { - err = -errno; - goto fail; - } - - err = 0; - out: - free(devname); - free(path); - free(s); - return err; - - fail: - EPRINTF("backdev setup failed [%d]\n", err); - goto out; -} - -static int -tapdisk_channel_complete_connection(tapdisk_channel_t *channel) -{ - int err; - char *path; - - if (!xs_printf(channel->xsh, channel->path, - "sectors", "%llu", channel->image.size)) { - EPRINTF("ERROR: Failed writing sectors"); - return -errno; - } - - if (!xs_printf(channel->xsh, channel->path, - "sector-size", "%lu", channel->image.secsize)) { - EPRINTF("ERROR: Failed writing sector-size"); - return -errno; - } - - if (!xs_printf(channel->xsh, channel->path, - "info", "%u", channel->image.info)) { - EPRINTF("ERROR: Failed writing info"); - return -errno; - } - - err = tapdisk_channel_connect_backdev(channel); - if (err) - goto clean; - - channel->connected = 1; - return 0; - - clean: - if (asprintf(&path, "%s/info", channel->path) == -1) - return err; - - if (!xs_rm(channel->xsh, XBT_NULL, path)) - goto clean_out; - - free(path); - if (asprintf(&path, "%s/sector-size", channel->path) == -1) - return err; - - if (!xs_rm(channel->xsh, XBT_NULL, path)) - goto clean_out; - - free(path); - if (asprintf(&path, "%s/sectors", channel->path) == -1) - return err; - - xs_rm(channel->xsh, XBT_NULL, path); - - clean_out: - free(path); - return err; -} - -static int -tapdisk_channel_send_open_request(tapdisk_channel_t *channel) -{ - int len; - tapdisk_message_t message; - - memset(&message, 0, sizeof(tapdisk_message_t)); - - len = strlen(channel->vdi_path); - - message.type = TAPDISK_MESSAGE_OPEN; - message.cookie = channel->cookie; - message.drivertype = channel->drivertype; - message.u.params.storage = channel->storage; - message.u.params.devnum = channel->minor; - message.u.params.domid = channel->domid; - message.u.params.path_len = len; - strncpy(message.u.params.path, channel->vdi_path, len); - - if (channel->mode == 'r') - message.u.params.flags |= TAPDISK_MESSAGE_FLAG_RDONLY; - if (channel->shared) - message.u.params.flags |= TAPDISK_MESSAGE_FLAG_SHARED; - - /* TODO: clean this up */ - if (xs_exists(channel->xsh, "/local/domain/0/tapdisk/add-cache")) - message.u.params.flags |= TAPDISK_MESSAGE_FLAG_ADD_CACHE; - if (xs_exists(channel->xsh, "/local/domain/0/tapdisk/log-dirty")) - message.u.params.flags |= TAPDISK_MESSAGE_FLAG_LOG_DIRTY; - - return tapdisk_channel_send_message(channel, &message, 2); -} - -static int -tapdisk_channel_receive_open_response(tapdisk_channel_t *channel, - tapdisk_message_t *message) -{ - int err; - - channel->image.size = message->u.image.sectors; - channel->image.secsize = message->u.image.sector_size; - channel->image.info = message->u.image.info; - - err = tapdisk_channel_complete_connection(channel); - if (err) - goto fail; - - /* did we receive a pause request before the connection completed? */ - if (channel->pause_needed) { - DPRINTF("%s: deferred pause request\n", channel->path); - tapdisk_channel_pause_event(channel->xsh, - &channel->pause_watch, - channel->pause_str); - channel->pause_needed = 0; - } - - return 0; - -fail: - tapdisk_channel_fatal(channel, - "failure completing connection: %d", err); - return err; -} - -static int -tapdisk_channel_send_shutdown_request(tapdisk_channel_t *channel) -{ - tapdisk_message_t message; - - memset(&message, 0, sizeof(tapdisk_message_t)); - - message.type = TAPDISK_MESSAGE_CLOSE; - message.drivertype = channel->drivertype; - message.cookie = channel->cookie; - - return tapdisk_channel_send_message(channel, &message, 2); -} - -static int -tapdisk_channel_receive_shutdown_response(tapdisk_channel_t *channel, - tapdisk_message_t *message) -{ - channel->open = 0; - channel->state = TAPDISK_CHANNEL_CLOSED; - tapdisk_channel_close(channel); - return 0; -} - -static int -tapdisk_channel_receive_runtime_error(tapdisk_channel_t *channel, - tapdisk_message_t *message) -{ - tapdisk_channel_error(channel, - "runtime error: %s", message->u.string.text); - return 0; -} - -static int -tapdisk_channel_send_pid_request(tapdisk_channel_t *channel) -{ - int err; - tapdisk_message_t message; - - memset(&message, 0, sizeof(tapdisk_message_t)); - - message.type = TAPDISK_MESSAGE_PID; - message.drivertype = channel->drivertype; - message.cookie = channel->cookie; - - err = tapdisk_channel_send_message(channel, &message, 2); - - if (!err) - channel->open = 1; - - return err; -} - -static int -tapdisk_channel_receive_pid_response(tapdisk_channel_t *channel, - tapdisk_message_t *message) -{ - int err; - - channel->tapdisk_pid = message->u.tapdisk_pid; - - DPRINTF("%s: tapdisk pid: %d\n", channel->path, channel->tapdisk_pid); - - err = setpriority(PRIO_PROCESS, channel->tapdisk_pid, PRIO_SPECIAL_IO); - if (err) { - tapdisk_channel_fatal(channel, - "setting tapdisk priority: %d", err); - return err; - } - - err = tapdisk_channel_send_open_request(channel); - if (err) { - tapdisk_channel_fatal(channel, - "sending open request: %d", err); - return err; - } - - return 0; -} - -static int -tapdisk_channel_send_pause_request(tapdisk_channel_t *channel) -{ - tapdisk_message_t message; - - memset(&message, 0, sizeof(tapdisk_message_t)); - - DPRINTF("pausing %s\n", channel->path); - - message.type = TAPDISK_MESSAGE_PAUSE; - message.drivertype = channel->drivertype; - message.cookie = channel->cookie; - - return tapdisk_channel_send_message(channel, &message, 2); -} - -static int -tapdisk_channel_receive_pause_response(tapdisk_channel_t *channel, - tapdisk_message_t *message) -{ - int err; - - if (!xs_write(channel->xsh, XBT_NULL, - channel->pause_done_str, "", strlen(""))) { - err = -errno; - goto fail; - } - - return 0; - -fail: - tapdisk_channel_fatal(channel, - "failure receiving pause response: %d\n", err); - return err; -} - -static int -tapdisk_channel_send_resume_request(tapdisk_channel_t *channel) -{ - int len; - tapdisk_message_t message; - - memset(&message, 0, sizeof(tapdisk_message_t)); - - len = strlen(channel->vdi_path); - - DPRINTF("resuming %s\n", channel->path); - - message.type = TAPDISK_MESSAGE_RESUME; - message.drivertype = channel->drivertype; - message.cookie = channel->cookie; - message.u.params.path_len = len; - strncpy(message.u.params.path, channel->vdi_path, len); - - return tapdisk_channel_send_message(channel, &message, 2); -} - -static int -tapdisk_channel_receive_resume_response(tapdisk_channel_t *channel, - tapdisk_message_t *message) -{ - int err; - - if (!xs_rm(channel->xsh, XBT_NULL, channel->pause_done_str)) { - err = -errno; - goto fail; - } - - return 0; - -fail: - tapdisk_channel_fatal(channel, - "failure receiving pause response: %d", err); - return err; -} - -static void -tapdisk_channel_shutdown_event(struct xs_handle *xsh, - struct xenbus_watch *watch, const char *path) -{ - int err; - tapdisk_channel_t *channel; - - channel = watch->data; - - DPRINTF("%s: got watch on %s\n", channel->path, path); - - if (!xs_exists(channel->xsh, channel->path)) { - tapdisk_channel_close(channel); - return; - } - - err = tapdisk_channel_validate_watch(channel, path); - if (err) { - if (err == -EINVAL) - tapdisk_channel_fatal(channel, "bad shutdown watch"); - return; - } - - tapdisk_channel_send_shutdown_request(channel); -} - -static void -tapdisk_channel_pause_event(struct xs_handle *xsh, - struct xenbus_watch *watch, const char *path) -{ - int err, paused; - tapdisk_channel_t *channel; - - channel = watch->data; - - DPRINTF("%s: got watch on %s\n", channel->path, path); - - if (!xs_exists(channel->xsh, channel->path)) { - tapdisk_channel_close(channel); - return; - } - - /* NB: The VBD is essentially considered ready since the - * backend hotplug event ocurred, which is just after - * start-tapdisk, not after watch registration. We start - * testing xenstore keys with the very first shot, but defer - * until after connection completion. */ - - err = tapdisk_channel_validate_watch(channel, path); - if (err) { - if (err == -EINVAL) - tapdisk_channel_fatal(channel, "bad pause watch"); - - if (err != -ENOENT) - return; - - err = 0; - } - - paused = xs_exists(xsh, channel->pause_done_str); - - if (xs_exists(xsh, channel->pause_str)) { - /* - * Duplicate requests are a protocol validation, but - * impossible to identify if watch registration and an - * actual pause request may fire separately in close - * succession. Warn, but do not signal an error. - */ - int pausing = channel->state == TAPDISK_CHANNEL_WAIT_PAUSE; - if (pausing || paused) { - DPRINTF("Ignoring pause event for %s vbd %s\n", - pausing ? "pausing" : "paused", channel->path); - goto out; - } - - /* defer if tapdisk is not ready yet */ - if (!channel->connected) { - DPRINTF("%s: deferring pause request\n", path); - channel->pause_needed = 1; - goto out; - } - - err = tapdisk_channel_send_pause_request(channel); - - } else if (xs_exists(xsh, channel->pause_done_str)) { - free(channel->params); - channel->params = NULL; - channel->vdi_path = NULL; - - err = xs_gather(channel->xsh, channel->path, - "params", NULL, &channel->params, NULL); - if (err) { - EPRINTF("failure re-reading params: %d\n", err); - channel->params = NULL; - goto out; - } - - err = tapdisk_channel_parse_params(channel); - if (err) - goto out; - - err = tapdisk_channel_send_resume_request(channel); - if (err) - goto out; - } - - err = 0; - -out: - if (err) - tapdisk_channel_error(channel, "pause event failed: %d", err); -} - -static int -tapdisk_channel_open_control_socket(char *devname) -{ - int err, fd; - fd_set socks; - struct timeval timeout; - - err = mkdir(BLKTAP_CTRL_DIR, 0755); - if (err == -1 && errno != EEXIST) { - EPRINTF("Failure creating %s directory: %d\n", - BLKTAP_CTRL_DIR, errno); - return -errno; - } - - err = mkfifo(devname, S_IRWXU | S_IRWXG | S_IRWXO); - if (err) { - if (errno == EEXIST) { - /* - * Remove fifo since it may have data from - * it's previous use --- earlier invocation - * of tapdisk may not have read all messages. - */ - err = unlink(devname); - if (err) { - EPRINTF("ERROR: unlink(%s) failed (%d)\n", - devname, errno); - return -errno; - } - - err = mkfifo(devname, S_IRWXU | S_IRWXG | S_IRWXO); - } - - if (err) { - EPRINTF("ERROR: pipe failed (%d)\n", errno); - return -errno; - } - } - - fd = open(devname, O_RDWR | O_NONBLOCK); - if (fd == -1) { - EPRINTF("Failed to open %s\n", devname); - return -errno; - } - - return fd; -} - -static int -tapdisk_channel_get_device_number(tapdisk_channel_t *channel) -{ - char *devname; - domid_translate_t tr; - int major, minor, err; - - tr.domid = channel->domid; - tr.busid = channel->busid; - - minor = ioctl(channel->blktap_fd, BLKTAP_IOCTL_NEWINTF, tr); - if (minor <= 0 || minor > MAX_TAP_DEV) { - EPRINTF("invalid dev id: %d\n", minor); - return -EINVAL; - } - - major = ioctl(channel->blktap_fd, BLKTAP_IOCTL_MAJOR, minor); - if (major < 0) { - EPRINTF("invalid major id: %d\n", major); - return -EINVAL; - } - - err = asprintf(&devname, "%s/%s%d", - BLKTAP_DEV_DIR, BLKTAP_DEV_NAME, minor); - if (err == -1) { - EPRINTF("get_new_dev: malloc failed\n"); - return -ENOMEM; - } - - err = make_blktap_device(devname, major, minor, S_IFCHR | 0600); - free(devname); - - if (err) - return err; - - DPRINTF("Received device id %d and major %d, " - "sent domid %d and be_id %d\n", - minor, major, tr.domid, tr.busid); - - channel->major = major; - channel->minor = minor; - - return 0; -} - -static int -tapdisk_channel_start_process(tapdisk_channel_t *channel, - char *write_dev, char *read_dev) -{ - pid_t child; - char *argv[] = { "tapdisk", write_dev, read_dev, NULL }; - - if ((child = fork()) == -1) - return -errno; - - if (!child) { - int i; - for (i = 0 ; i < sysconf(_SC_OPEN_MAX) ; i++) - if (i != STDIN_FILENO && - i != STDOUT_FILENO && - i != STDERR_FILENO) - close(i); - - execvp("tapdisk", argv); - _exit(1); - } else { - pid_t got; - do { - got = waitpid(child, NULL, 0); - } while (got != child); - } - return 0; -} - -static int -tapdisk_channel_launch_tapdisk(tapdisk_channel_t *channel) -{ - int err; - char *read_dev, *write_dev; - - read_dev = NULL; - write_dev = NULL; - channel->read_fd = -1; - channel->write_fd = -1; - - err = tapdisk_channel_get_device_number(channel); - if (err) - return err; - - err = asprintf(&write_dev, - "%s/tapctrlwrite%d", BLKTAP_CTRL_DIR, channel->minor); - if (err == -1) { - err = -ENOMEM; - write_dev = NULL; - goto fail; - } - - err = asprintf(&read_dev, - "%s/tapctrlread%d", BLKTAP_CTRL_DIR, channel->minor); - if (err == -1) { - err = -ENOMEM; - read_dev = NULL; - goto fail; - } - - channel->write_fd = tapdisk_channel_open_control_socket(write_dev); - if (channel->write_fd < 0) { - err = channel->write_fd; - channel->write_fd = -1; - goto fail; - } - - channel->read_fd = tapdisk_channel_open_control_socket(read_dev); - if (channel->read_fd < 0) { - err = channel->read_fd; - channel->read_fd = -1; - goto fail; - } - - err = tapdisk_channel_start_process(channel, write_dev, read_dev); - if (err) - goto fail; - - channel->open = 1; - channel->channel_id = channel->write_fd; - - free(read_dev); - free(write_dev); - - DPRINTF("process launched, channel = %d:%d\n", - channel->channel_id, channel->cookie); - - return tapdisk_channel_send_pid_request(channel); - -fail: - free(read_dev); - free(write_dev); - if (channel->read_fd != -1) - close(channel->read_fd); - if (channel->write_fd != -1) - close(channel->write_fd); - return err; -} - -static int -tapdisk_channel_connect(tapdisk_channel_t *channel) -{ - int err; - - tapdisk_daemon_find_channel(channel); - - if (!channel->tapdisk_pid) - return tapdisk_channel_launch_tapdisk(channel); - - DPRINTF("%s: process exists: %d, channel = %d:%d\n", - channel->path, channel->tapdisk_pid, - channel->channel_id, channel->cookie); - - err = tapdisk_channel_get_device_number(channel); - if (err) - return err; - - return tapdisk_channel_send_pid_request(channel); -} - -static int -tapdisk_channel_init(tapdisk_channel_t *channel) -{ - int err; - - channel->uuid_str = NULL; - channel->pause_str = NULL; - channel->pause_done_str = NULL; - channel->shutdown_str = NULL; - channel->share_tapdisk_str = NULL; - - err = asprintf(&channel->uuid_str, - "%s/tapdisk-uuid", channel->path); - if (err == -1) { - channel->uuid_str = NULL; - goto fail; - } - - err = asprintf(&channel->pause_str, "%s/pause", channel->path); - if (err == -1) { - channel->pause_str = NULL; - goto fail; - } - - err = asprintf(&channel->pause_done_str, - "%s/pause-done", channel->path); - if (err == -1) { - channel->pause_done_str = NULL; - goto fail; - } - - err = asprintf(&channel->shutdown_str, - "%s/shutdown-tapdisk", channel->path); - if (err == -1) { - channel->shutdown_str = NULL; - goto fail; - } - - channel->share_tapdisk_str = "/local/domain/0/tapdisk/share-tapdisks"; - - return 0; - -fail: - free(channel->uuid_str); - free(channel->pause_str); - free(channel->pause_done_str); - free(channel->shutdown_str); - channel->uuid_str = NULL; - channel->pause_str = NULL; - channel->pause_done_str = NULL; - channel->shutdown_str = NULL; - channel->share_tapdisk_str = NULL; - return -ENOMEM; -} - -static int -tapdisk_channel_set_watches(tapdisk_channel_t *channel) -{ - int err; - - /* watch for pause events */ - channel->pause_watch.node = channel->pause_str; - channel->pause_watch.callback = tapdisk_channel_pause_event; - channel->pause_watch.data = channel; - err = register_xenbus_watch(channel->xsh, &channel->pause_watch); - if (err) { - channel->pause_watch.node = NULL; - goto fail; - } - - /* watch for shutdown events */ - channel->shutdown_watch.node = channel->shutdown_str; - channel->shutdown_watch.callback = tapdisk_channel_shutdown_event; - channel->shutdown_watch.data = channel; - err = register_xenbus_watch(channel->xsh, &channel->shutdown_watch); - if (err) { - channel->shutdown_watch.node = NULL; - goto fail; - } - - return 0; - -fail: - if (channel->pause_watch.node) { - unregister_xenbus_watch(channel->xsh, &channel->pause_watch); - channel->pause_watch.node = NULL; - } - if (channel->shutdown_watch.node) { - unregister_xenbus_watch(channel->xsh, &channel->shutdown_watch); - channel->shutdown_watch.node = NULL; - } - return err; -} - -static void -tapdisk_channel_get_storage_type(tapdisk_channel_t *channel) -{ - int err, type; - unsigned int len; - char *path, *stype; - - channel->storage = TAPDISK_STORAGE_TYPE_DEFAULT; - - err = asprintf(&path, "%s/sm-data/storage-type", channel->path); - if (err == -1) - return; - - stype = xs_read(channel->xsh, XBT_NULL, path, &len); - if (!stype) - goto out; - else if (!strcmp(stype, "nfs")) - channel->storage = TAPDISK_STORAGE_TYPE_NFS; - else if (!strcmp(stype, "ext")) - channel->storage = TAPDISK_STORAGE_TYPE_EXT; - else if (!strcmp(stype, "lvm")) - channel->storage = TAPDISK_STORAGE_TYPE_LVM; - -out: - free(path); - free(stype); -} - -static int -tapdisk_channel_get_busid(tapdisk_channel_t *channel) -{ - int len, end; - const char *ptr; - char *tptr, num[10]; - - len = strsep_len(channel->path, '/', 6); - end = strlen(channel->path); - if(len < 0 || end < 0) { - EPRINTF("invalid path: %s\n", channel->path); - return -EINVAL; - } - - ptr = channel->path + len + 1; - strncpy(num, ptr, end - len); - tptr = num + (end - (len + 1)); - *tptr = '\0'; - - channel->busid = atoi(num); - return 0; -} - -static int -tapdisk_channel_parse_params(tapdisk_channel_t *channel) -{ - int i, size, err; - unsigned int len; - char *ptr, *path, handle[10]; - char *vdi_type; - char *vtype; - - path = channel->params; - size = sizeof(dtypes) / sizeof(disk_info_t *); - - if (strlen(path) + 1 >= TAPDISK_MESSAGE_MAX_PATH_LENGTH) - goto fail; - - ptr = strchr(path, ':'); - if (!ptr) - goto fail; - - channel->vdi_path = ptr + 1; - memcpy(handle, path, (ptr - path)); - ptr = handle + (ptr - path); - *ptr = '\0'; - - err = asprintf(&vdi_type, "%s/sm-data/vdi-type", channel->path); - if (err == -1) - goto fail; - - if (xs_exists(channel->xsh, vdi_type)) { - vtype = xs_read(channel->xsh, XBT_NULL, vdi_type, &len); - free(vdi_type); - if (!vtype) - goto fail; - if (len >= sizeof(handle) - 1) { - free(vtype); - goto fail; - } - sprintf(handle, "%s", vtype); - free(vtype); - } - - for (i = 0; i < size; i++) { - if (strncmp(handle, dtypes[i]->handle, (ptr - path))) - continue; - - if (dtypes[i]->idnum == -1) - goto fail; - - channel->drivertype = dtypes[i]->idnum; - return 0; - } - -fail: - EPRINTF("%s: invalid blktap params: %s\n", - channel->path, channel->params); - channel->vdi_path = NULL; - return -EINVAL; -} - -static int -tapdisk_channel_gather_info(tapdisk_channel_t *channel) -{ - int err; - - err = xs_gather(channel->xsh, channel->path, - "frontend", NULL, &channel->frontpath, - "frontend-id", "%li", &channel->domid, - "params", NULL, &channel->params, - "mode", "%c", &channel->mode, NULL); - if (err) { - EPRINTF("could not find device info: %d\n", err); - return err; - } - - err = tapdisk_channel_parse_params(channel); - if (err) - return err; - - err = tapdisk_channel_get_busid(channel); - if (err) - return err; - - tapdisk_channel_get_storage_type(channel); - - return 0; -} - -static int -tapdisk_channel_verify_start_request(tapdisk_channel_t *channel) -{ - char *path; - unsigned int err; - - err = asprintf(&path, "%s/start-tapdisk", channel->path); - if (err == -1) - goto mem_fail; - - if (!xs_exists(channel->xsh, path)) - goto fail; - - free(path); - err = asprintf(&path, "%s/shutdown-request", channel->path); - if (err == -1) - goto mem_fail; - - if (xs_exists(channel->xsh, path)) - goto fail; - - if (xs_exists(channel->xsh, channel->shutdown_str)) - goto fail; - - free(path); - err = asprintf(&path, "%s/shutdown-done", channel->path); - if (err == -1) - goto mem_fail; - - if (xs_exists(channel->xsh, path)) - goto fail; - - free(path); - - return 0; - -fail: - free(path); - EPRINTF("%s:%s: invalid start request\n", __func__, channel->path); - return -EINVAL; - -mem_fail: - EPRINTF("%s:%s: out of memory\n", __func__, channel->path); - return -ENOMEM; -} - -void -tapdisk_channel_close(tapdisk_channel_t *channel) -{ - if (channel->channel_id) - DPRINTF("%s: closing channel %d:%d\n", - channel->path, channel->channel_id, channel->cookie); - - if (channel->open) - tapdisk_channel_send_shutdown_request(channel); - - if (channel->pause_watch.node) { - unregister_xenbus_watch(channel->xsh, &channel->pause_watch); - channel->pause_watch.node = NULL; - } - - if (channel->shutdown_watch.node) { - unregister_xenbus_watch(channel->xsh, &channel->shutdown_watch); - channel->shutdown_watch.node = NULL; - } - - tapdisk_daemon_close_channel(channel); - - free(channel->params); - free(channel->frontpath); - free(channel->shutdown_str); - free(channel->pause_done_str); - free(channel->pause_str); - free(channel->uuid_str); - free(channel->path); - free(channel); -} - -int -tapdisk_channel_open(tapdisk_channel_t **_channel, - char *path, struct xs_handle *xsh, - int blktap_fd, uint16_t cookie) -{ - int err; - char *msg; - tapdisk_channel_t *channel; - - msg = NULL; - *_channel = NULL; - - channel = calloc(1, sizeof(tapdisk_channel_t)); - if (!channel) - return -ENOMEM; - - channel->xsh = xsh; - channel->blktap_fd = blktap_fd; - channel->cookie = cookie; - channel->state = TAPDISK_CHANNEL_IDLE; - - INIT_LIST_HEAD(&channel->list); - - channel->path = strdup(path); - if (!channel->path) { - err = -ENOMEM; - goto fail; - } - - err = tapdisk_channel_init(channel); - if (err) { - msg = "allocating device"; - goto fail; - } - - err = tapdisk_channel_check_uuid(channel); - if (err) { - msg = "checking uuid"; - goto fail; - } - - err = tapdisk_channel_gather_info(channel); - if (err) { - msg = "gathering parameters"; - goto fail; - } - - err = tapdisk_channel_verify_start_request(channel); - if (err) { - msg = "invalid start request"; - goto fail; - } - - err = tapdisk_channel_set_watches(channel); - if (err) { - msg = "registering xenstore watches"; - goto fail; - } - - err = tapdisk_channel_connect(channel); - if (err) { - msg = "connecting to tapdisk"; - goto fail; - } - - *_channel = channel; - return 0; - -fail: - tapdisk_channel_fatal(channel, "%s: %d", (msg ? : "failure"), err); - return err; -} - -int -tapdisk_channel_receive_message(tapdisk_channel_t *c, tapdisk_message_t *m) -{ - int err; - - err = tapdisk_channel_validate_message(c, m); - if (err) - goto fail; - - switch (m->type) { - case TAPDISK_MESSAGE_PID_RSP: - return tapdisk_channel_receive_pid_response(c, m); - - case TAPDISK_MESSAGE_OPEN_RSP: - return tapdisk_channel_receive_open_response(c, m); - - case TAPDISK_MESSAGE_PAUSE_RSP: - return tapdisk_channel_receive_pause_response(c, m); - - case TAPDISK_MESSAGE_RESUME_RSP: - return tapdisk_channel_receive_resume_response(c, m); - - case TAPDISK_MESSAGE_CLOSE_RSP: - return tapdisk_channel_receive_shutdown_response(c, m); - - case TAPDISK_MESSAGE_RUNTIME_ERROR: - return tapdisk_channel_receive_runtime_error(c, m); - } - -fail: - tapdisk_channel_fatal(c, "received unexpected message %s in state %d", - tapdisk_message_name(m->type), c->state); - return -EINVAL; -} diff -r 538eaa381f54 tools/blktap2/daemon/tapdisk-daemon.c --- a/tools/blktap2/daemon/tapdisk-daemon.c Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,599 +0,0 @@ -/* 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 -#include -#include -#include -#include -#include -#include -#include - -#include -#include "disktypes.h" -#include "tapdisk-dispatch.h" - -#define TAPDISK_DAEMON_DOMID_WATCH "domid-watch" -#define TAPDISK_DAEMON_PIDFILE "/var/run/blktapctrl.pid" - -typedef struct tapdisk_daemon { - char *node; - int blktap_fd; - uint16_t cookie; - - struct xs_handle *xsh; - struct list_head channels; - struct xenbus_watch watch; -} tapdisk_daemon_t; - -static tapdisk_daemon_t tapdisk_daemon; - -#define tapdisk_daemon_for_each_channel(c, tmp) \ - list_for_each_entry_safe(c, tmp, &tapdisk_daemon.channels, list) - -#define MAX(a, b) ((a) >= (b) ? (a) : (b)) - -static void -tapdisk_daemon_print_drivers(void) -{ - int i, size; - - DPRINTF("blktap-daemon: v1.0.2\n"); - - size = sizeof(dtypes) / sizeof(disk_info_t *); - for (i = 0; i < size; i++) - DPRINTF("Found driver: [%s]\n", dtypes[i]->name); -} - -static int -tapdisk_daemon_write_pidfile(long pid) -{ - char buf[100]; - int len, fd, flags, err; - - fd = open(TAPDISK_DAEMON_PIDFILE, O_RDWR | O_CREAT, 0600); - if (fd == -1) { - EPRINTF("Opening pid file failed (%d)\n", errno); - return -errno; - } - - /* We exit silently if daemon already running */ - err = lockf(fd, F_TLOCK, 0); - if (err == -1) - exit(0); - - /* Set FD_CLOEXEC, so that tapdisk doesn't get this file descriptor */ - flags = fcntl(fd, F_GETFD); - if (flags == -1) { - EPRINTF("F_GETFD failed (%d)\n", errno); - return -errno; - } - - flags |= FD_CLOEXEC; - err = fcntl(fd, F_SETFD, flags); - if (err == -1) { - EPRINTF("F_SETFD failed (%d)\n", errno); - return -errno; - } - - len = sprintf(buf, "%ld\n", pid); - err = write(fd, buf, len); - if (err != len) { - EPRINTF("Writing pid file failed (%d)\n", errno); - return -errno; - } - - return 0; -} - -static int -tapdisk_daemon_init(void) -{ - char *devname; - int i, err, blktap_major; - - memset(&tapdisk_daemon, 0, sizeof(tapdisk_daemon_t)); - - err = asprintf(&devname, "%s/%s0", BLKTAP_DEV_DIR, BLKTAP_DEV_NAME); - if (err == -1) { - devname = NULL; - err = -ENOMEM; - goto fail; - } - - err = xc_find_device_number("blktap0"); - if (err < 0) - goto fail; - - blktap_major = major(err); - err = make_blktap_device(devname, blktap_major, 0, S_IFCHR | 0600); - if (err) - goto fail; - - tapdisk_daemon.blktap_fd = open(devname, O_RDWR); - if (tapdisk_daemon.blktap_fd == -1) { - err = -errno; - EPRINTF("blktap0 open failed\n"); - goto fail; - } - - for (i = 0; i < 2; i++) { - tapdisk_daemon.xsh = xs_daemon_open(); - if (!tapdisk_daemon.xsh) { - EPRINTF("xs_daemon_open failed -- is xenstore running?\n"); - sleep(2); - } else - break; - } - - if (!tapdisk_daemon.xsh) { - err = -ENOSYS; - goto fail; - } - - INIT_LIST_HEAD(&tapdisk_daemon.channels); - - free(devname); - return 0; - -fail: - if (tapdisk_daemon.blktap_fd > 0) - close(tapdisk_daemon.blktap_fd); - free(devname); - memset(&tapdisk_daemon, 0, sizeof(tapdisk_daemon_t)); - EPRINTF("%s: %d\n", __func__, err); - - return err; -} - -static int -tapdisk_daemon_set_node(void) -{ - int err; - char *domid; - - domid = get_dom_domid(tapdisk_daemon.xsh); - if (!domid) - return -EAGAIN; - - err = asprintf(&tapdisk_daemon.node, - "/local/domain/%s/backend/tap", domid); - if (err == -1) { - tapdisk_daemon.node = NULL; - err = -ENOMEM; - goto out; - } - - err = 0; - -out: - free(domid); - return err; -} - -static int -tapdisk_daemon_get_domid(void) -{ - int err; - unsigned int num; - char **res, *node, *token, *domid; - - res = xs_read_watch(tapdisk_daemon.xsh, &num); - if (!res) - return -EAGAIN; - - err = 0; - node = res[XS_WATCH_PATH]; - token = res[XS_WATCH_TOKEN]; - - if (strcmp(token, TAPDISK_DAEMON_DOMID_WATCH)) { - err = -EINVAL; - goto out; - } - - err = tapdisk_daemon_set_node(); - -out: - free(res); - return err; -} - -static int -tapdisk_daemon_wait_for_domid(void) -{ - int err; - char *domid; - fd_set readfds; - - err = tapdisk_daemon_set_node(); - if (!err) - return 0; - - if (!xs_watch(tapdisk_daemon.xsh, "/local/domain", - TAPDISK_DAEMON_DOMID_WATCH)) { - EPRINTF("unable to set domain id watch\n"); - return -EINVAL; - } - - do { - FD_ZERO(&readfds); - FD_SET(xs_fileno(tapdisk_daemon.xsh), &readfds); - - select(xs_fileno(tapdisk_daemon.xsh) + 1, - &readfds, NULL, NULL, NULL); - - if (FD_ISSET(xs_fileno(tapdisk_daemon.xsh), &readfds)) - err = tapdisk_daemon_get_domid(); - else - err = -EAGAIN; - } while (err == -EAGAIN); - - xs_unwatch(tapdisk_daemon.xsh, - "/local/domain", TAPDISK_DAEMON_DOMID_WATCH); - return err; -} - -static inline int -tapdisk_daemon_new_vbd_event(const char *node) -{ - return (!strcmp(node, "start-tapdisk")); -} - -static int -tapdisk_daemon_write_uuid(char *path, uint32_t uuid) -{ - int err; - char *cpath, uuid_str[12]; - - snprintf(uuid_str, sizeof(uuid_str), "%u", uuid); - - err = asprintf(&cpath, "%s/tapdisk-uuid", path); - if (err == -1) - return -ENOMEM; - - err = xs_write(tapdisk_daemon.xsh, XBT_NULL, - cpath, uuid_str, strlen(uuid_str)); - free(cpath); - - return (err ? 0 : -errno); -} - -static void -tapdisk_daemon_probe(struct xs_handle *xsh, - struct xenbus_watch *watch, const char *path) -{ - char *cpath; - int len, err; - uint32_t cookie; - const char *node; - tapdisk_channel_t *channel; - - len = strsep_len(path, '/', 7); - if (len < 0) - return; - - node = path + len + 1; - - if (!tapdisk_daemon_new_vbd_event(node)) - return; - - if (!xs_exists(xsh, path)) - return; - - cpath = strdup(path); - if (!cpath) { - EPRINTF("failed to allocate control path for %s\n", path); - return; - } - cpath[len] = '\0'; - - cookie = tapdisk_daemon.cookie++; - err = tapdisk_daemon_write_uuid(cpath, cookie); - if (err) - goto out; - - DPRINTF("%s: got watch on %s, uuid = %u\n", __func__, path, cookie); - - err = tapdisk_channel_open(&channel, cpath, - tapdisk_daemon.xsh, - tapdisk_daemon.blktap_fd, - cookie); - if (!err) - list_add(&channel->list, &tapdisk_daemon.channels); - else - EPRINTF("failed to open tapdisk channel for %s: %d\n", - path, err); - -out: - free(cpath); -} - -static int -tapdisk_daemon_start(void) -{ - int err; - - err = tapdisk_daemon_wait_for_domid(); - if (err) - return err; - - tapdisk_daemon.watch.node = tapdisk_daemon.node; - tapdisk_daemon.watch.callback = tapdisk_daemon_probe; - - err = register_xenbus_watch(tapdisk_daemon.xsh, &tapdisk_daemon.watch); - if (err) - goto fail; - - ioctl(tapdisk_daemon.blktap_fd, - BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_INTERPOSE); - ioctl(tapdisk_daemon.blktap_fd, BLKTAP_IOCTL_SENDPID, getpid()); - - return 0; - -fail: - free(tapdisk_daemon.node); - tapdisk_daemon.node = NULL; - tapdisk_daemon.watch.node = NULL; - EPRINTF("%s: %d\n", __func__, err); - return err; -} - -static int -tapdisk_daemon_stop(void) -{ - unregister_xenbus_watch(tapdisk_daemon.xsh, &tapdisk_daemon.watch); - - ioctl(tapdisk_daemon.blktap_fd, - BLKTAP_IOCTL_SETMODE, BLKTAP_MODE_PASSTHROUGH); - close(tapdisk_daemon.blktap_fd); - - return 0; -} - -static void -tapdisk_daemon_free(void) -{ - free(tapdisk_daemon.node); - xs_daemon_close(tapdisk_daemon.xsh); - memset(&tapdisk_daemon, 0, sizeof(tapdisk_daemon_t)); -} - -static int -tapdisk_daemon_read_message(int fd, tapdisk_message_t *message, int timeout) -{ - fd_set readfds; - struct timeval tv; - int ret, len, offset; - - tv.tv_sec = timeout; - tv.tv_usec = 0; - offset = 0; - len = sizeof(tapdisk_message_t); - - memset(message, 0, sizeof(tapdisk_message_t)); - - while (offset < len) { - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - - /* we don't bother reinitializing tv. at worst, it will wait a - * bit more time than expected. */ - - ret = select(fd + 1, &readfds, NULL, NULL, &tv); - if (ret == -1) - break; - else if (FD_ISSET(fd, &readfds)) { - ret = read(fd, message + offset, len - offset); - if (ret <= 0) - break; - offset += ret; - } else - break; - } - - return (offset == len ? 0 : -EIO); -} - -static int -tapdisk_daemon_receive_message(int fd) -{ - int err; - tapdisk_message_t m; - tapdisk_channel_t *c, *tmp; - - err = tapdisk_daemon_read_message(fd, &m, 2); - if (err) { - EPRINTF("failed reading message on %d: %d\n", fd, err); - return err; - } - - tapdisk_daemon_for_each_channel(c, tmp) - if (c->cookie == m.cookie && c->read_fd == fd) { - DPRINTF("got '%s' message from %d:%d\n", - tapdisk_message_name(m.type), - c->channel_id, c->cookie); - - return tapdisk_channel_receive_message(c, &m); - } - - EPRINTF("unrecognized message on %d: '%s' (uuid = %u)\n", - fd, tapdisk_message_name(m.type), m.cookie); - - return -EINVAL; -} - -static int -tapdisk_daemon_set_fds(fd_set *readfds) -{ - int max, fd; - tapdisk_channel_t *channel, *tmp; - - max = xs_fileno(tapdisk_daemon.xsh); - - FD_ZERO(readfds); - FD_SET(max, readfds); - - tapdisk_daemon_for_each_channel(channel, tmp) { - fd = channel->read_fd; - max = MAX(fd, max); - FD_SET(fd, readfds); - } - - return max; -} - -static int -tapdisk_daemon_check_fds(fd_set *readfds) -{ - int err; - tapdisk_channel_t *channel, *tmp; - - if (FD_ISSET(xs_fileno(tapdisk_daemon.xsh), readfds)) - xs_fire_next_watch(tapdisk_daemon.xsh); - - tapdisk_daemon_for_each_channel(channel, tmp) - if (FD_ISSET(channel->read_fd, readfds)) - return tapdisk_daemon_receive_message(channel->read_fd); - - return 0; -} - -static int -tapdisk_daemon_run(void) -{ - int err, max; - fd_set readfds; - - while (1) { - max = tapdisk_daemon_set_fds(&readfds); - - err = select(max + 1, &readfds, NULL, NULL, NULL); - if (err < 0) - continue; - - err = tapdisk_daemon_check_fds(&readfds); - } - - return err; -} - -void -tapdisk_daemon_find_channel(tapdisk_channel_t *channel) -{ - tapdisk_channel_t *c, *tmp; - - channel->read_fd = 0; - channel->write_fd = 0; - channel->tapdisk_pid = 0; - - /* do we want multiple vbds per tapdisk? */ - if (!xs_exists(tapdisk_daemon.xsh, channel->share_tapdisk_str)) { - channel->shared = 0; - return; - } - - channel->shared = 1; - - /* check if we already have a process started */ - tapdisk_daemon_for_each_channel(c, tmp) - if (c->drivertype == channel->drivertype) { - channel->write_fd = c->write_fd; - channel->read_fd = c->read_fd; - channel->channel_id = c->channel_id; - channel->tapdisk_pid = c->tapdisk_pid; - return; - } -} - -void -tapdisk_daemon_close_channel(tapdisk_channel_t *channel) -{ - tapdisk_channel_t *c, *tmp; - - list_del(&channel->list); - - tapdisk_daemon_for_each_channel(c, tmp) - if (c->channel_id == channel->channel_id) - return; - - close(channel->read_fd); - close(channel->write_fd); -} - -int -main(int argc, char *argv[]) -{ - int err; - char buf[128]; - - if (daemon(0, 0)) { - EPRINTF("daemon() failed (%d)\n", errno); - return -errno; - } - -#define CORE_DUMP -#if defined(CORE_DUMP) - { - /* set up core-dumps*/ - struct rlimit rlim; - rlim.rlim_cur = RLIM_INFINITY; - rlim.rlim_max = RLIM_INFINITY; - if (setrlimit(RLIMIT_CORE, &rlim) < 0) - EPRINTF("setrlimit failed: %d\n", errno); - } -#endif - - snprintf(buf, sizeof(buf), "BLKTAP-DAEMON[%d]", getpid()); - openlog(buf, LOG_CONS | LOG_ODELAY, LOG_DAEMON); - - err = tapdisk_daemon_write_pidfile(getpid()); - if (err) - goto out; - - tapdisk_daemon_print_drivers(); - - err = tapdisk_daemon_init(); - if (err) - goto out; - - err = tapdisk_daemon_start(); - if (err) - goto out; - - tapdisk_daemon_run(); - - tapdisk_daemon_stop(); - tapdisk_daemon_free(); - - err = 0; - -out: - if (err) - EPRINTF("failed to start %s: %d\n", argv[0], err); - closelog(); - return err; -} diff -r 538eaa381f54 tools/blktap2/daemon/tapdisk-dispatch-common.c --- a/tools/blktap2/daemon/tapdisk-dispatch-common.c Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,94 +0,0 @@ -/* - * (c) 2005 Andrew Warfield and Julian Chesterfield - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation; or, when distributed - * separately from the Linux kernel or incorporated into other - * software packages, subject to the following license: - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this source file (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, modify, - * merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ -#include -#include -#include -#include -#include - -#include "tapdisk-dispatch.h" - -int -strsep_len(const char *str, char c, unsigned int len) -{ - unsigned int i; - - for (i = 0; str[i]; i++) - if (str[i] == c) { - if (len == 0) - return i; - len--; - } - - return (len == 0) ? i : -ERANGE; -} - -int -make_blktap_device(char *devname, int major, int minor, int perm) -{ - int err; - - err = unlink(devname); - if (err && errno != ENOENT) { - EPRINTF("unlink %s failed: %d\n", devname, errno); - return -errno; - } - - /* Need to create device */ - err = mkdir(BLKTAP_DEV_DIR, 0755); - if (err && errno != EEXIST) { - EPRINTF("Failed to create %s directory\n", BLKTAP_DEV_DIR); - return -errno; - } - - err = mknod(devname, perm, makedev(major, minor)); - if (err) { - int ret = -errno; - struct stat st; - - EPRINTF("mknod %s failed: %d\n", devname, -errno); - - err = lstat(devname, &st); - if (err) { - DPRINTF("lstat %s failed: %d\n", devname, -errno); - err = access(devname, F_OK); - if (err) - DPRINTF("access %s failed: %d\n", devname, -errno); - else - DPRINTF("access %s succeeded\n", devname); - } else - DPRINTF("lstat %s: %u:%u\n", devname, - (unsigned int)st.st_rdev >> 8, - (unsigned int)st.st_rdev & 0xff); - - return ret; - } - - DPRINTF("Created %s device\n", devname); - return 0; -} diff -r 538eaa381f54 tools/blktap2/daemon/tapdisk-dispatch.h --- a/tools/blktap2/daemon/tapdisk-dispatch.h Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,95 +0,0 @@ -/* 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. -*/ -#ifndef _TAPDISK_DISPATCH_H_ -#define _TAPDISK_DISPATCH_H_ - -#include "xs_api.h" -#include "blktaplib.h" -#include "tapdisk-message.h" - -struct tapdisk_channel { - int state; - - int read_fd; - int write_fd; - int blktap_fd; - int channel_id; - - char mode; - char shared; - char open; - unsigned int domid; - unsigned int busid; - unsigned int major; - unsigned int minor; - unsigned int storage; - unsigned int drivertype; - uint16_t cookie; - pid_t tapdisk_pid; - - /* - * special accounting needed to handle pause - * requests received before tapdisk process is ready - */ - char connected; - char pause_needed; - - char *path; - char *frontpath; - char *params; - char *vdi_path; - char *uuid_str; - char *pause_str; - char *pause_done_str; - char *shutdown_str; - char *share_tapdisk_str; - - image_t image; - - struct list_head list; - struct xenbus_watch pause_watch; - struct xenbus_watch shutdown_watch; - - struct xs_handle *xsh; -}; - -typedef struct tapdisk_channel tapdisk_channel_t; - -int strsep_len(const char *str, char c, unsigned int len); -int make_blktap_device(char *devname, int major, int minor, int perm); - -int tapdisk_channel_open(tapdisk_channel_t **, - char *node, struct xs_handle *, - int blktap_fd, uint16_t cookie); -void tapdisk_channel_close(tapdisk_channel_t *); - -void tapdisk_daemon_find_channel(tapdisk_channel_t *); -void tapdisk_daemon_close_channel(tapdisk_channel_t *); - -int tapdisk_channel_receive_message(tapdisk_channel_t *, tapdisk_message_t *); - -#endif diff -r 538eaa381f54 tools/blktap2/drivers/Makefile --- a/tools/blktap2/drivers/Makefile Tue Jun 16 14:54:26 2009 -0700 +++ b/tools/blktap2/drivers/Makefile Tue Jun 16 17:52:43 2009 -0700 @@ -5,7 +5,7 @@ LIBVHDDIR = $(BLKTAP_ROOT)/vhd/lib LIBPLXDIR = $(BLKTAP_ROOT)/parallax -IBIN = tapdisk tapdisk2 td-util tapdisk-client tapdisk-stream tapdisk-diff +IBIN = tapdisk2 td-util tapdisk-client tapdisk-stream tapdisk-diff QCOW_UTIL = img2qcow qcow-create qcow2raw LOCK_UTIL = lock-util INST_DIR = $(SBINDIR) @@ -35,11 +35,11 @@ LDFLAGS_img := $(CRYPT_LIB) -lpthread -lz -tapdisk tapdisk2 td-util tapdisk-stream tapdisk-diff $(QCOW_UTIL): LIBS += -L$(LIBVHDDIR) -lvhd -L$(LIBPLXDIR) -lparallax -luuid +tapdisk2 td-util tapdisk-stream tapdisk-diff $(QCOW_UTIL): LIBS += -L$(LIBVHDDIR) -lvhd -L$(LIBPLXDIR) -lparallax -luuid LIBAIO_DIR = $(XEN_ROOT)/tools/libaio/src -tapdisk tapdisk2 tapdisk-stream tapdisk-diff $(QCOW_UTIL): AIOLIBS := $(LIBAIO_DIR)/libaio.a -tapdisk tapdisk-client tapdisk-stream tapdisk-diff $(QCOW_UTIL): CFLAGS += -I$(LIBAIO_DIR) -I$(XEN_LIBXC) +tapdisk2 tapdisk-stream tapdisk-diff $(QCOW_UTIL): AIOLIBS := $(LIBAIO_DIR)/libaio.a +tapdisk-client tapdisk-stream tapdisk-diff $(QCOW_UTIL): CFLAGS += -I$(LIBAIO_DIR) -I$(XEN_LIBXC) ifeq ($(VHD_STATIC),y) td-util: CFLAGS += -static @@ -73,8 +73,6 @@ all: $(IBIN) lock-util qcow-util -tapdisk: $(TAP-OBJS-y) $(BLK-OBJS-y) $(MISC-OBJS-y) tapdisk.c - $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) $(AIOLIBS) $(LDFLAGS_img) tapdisk2: $(TAP-OBJS-y) $(BLK-OBJS-y) $(MISC-OBJS-y) tapdisk2.c $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LIBS) $(AIOLIBS) $(LDFLAGS_img) diff -r 538eaa381f54 tools/blktap2/drivers/tapdisk.c --- a/tools/blktap2/drivers/tapdisk.c Tue Jun 16 14:54:26 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * 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 -#include -#include -#include - -#include "tapdisk-utils.h" -#include "tapdisk-server.h" - -static void -usage(void) -{ - fprintf(stderr, "blktap-utils: v2.0.0\n"); - fprintf(stderr, "usage: tapdisk \n"); - exit(EINVAL); -} - -int -main(int argc, char *argv[]) -{ - int err; - - if (argc != 3) - usage(); - - daemon(0, 0); - tapdisk_start_logging("TAPDISK"); - - err = tapdisk_server_initialize(argv[1], argv[2]); - if (err) { - EPRINTF("failed to initialize tapdisk server: %d\n", err); - goto out; - } - - err = tapdisk_server_run(); - -out: - tapdisk_stop_logging(); - return err; -} diff -r 538eaa381f54 tools/python/xen/xend/server/BlktapController.py --- a/tools/python/xen/xend/server/BlktapController.py Tue Jun 16 14:54:26 2009 -0700 +++ b/tools/python/xen/xend/server/BlktapController.py Tue Jun 16 17:52:43 2009 -0700 @@ -127,9 +127,19 @@ except: (typ, params, file) = string.split(uname, ':', 2) subtyp = 'tapdisk' + + #check for blktap2 installation. + blktap2_installed=0; + (rc,stdout, stderr) = doexec("cat /proc/devices"); + out = stdout.read(); + stdout.close(); + stderr.close(); + if( out.find("blktap2") >= 0 ): + blktap2_installed=1; + if typ in ('tap'): if subtyp in ('tapdisk'): - if params in ('ioemu', 'qcow2', 'vmdk', 'sync'): + if params in ('ioemu', 'qcow2', 'vmdk', 'sync') or not blktap2_installed: log.warn('WARNING: using deprecated blktap module'); return BlkifController.createDevice(self, config);