# HG changeset patch
# User Ryan Grimm <grimm@xxxxxxxxxx>
# Date 1156190589 18000
# Node ID a19a066dea764a70f06b4e4341229db92c2eb5c3
# Parent 53c5bcecfcfdb70cb3a2aed0adb564312988fbdd
dm-userspace internal libdmu support for userspace tool
Signed-off-by: Ryan Grimm <grimm@xxxxxxxxxx>
Signed-off-by: Dan Smith <danms@xxxxxxxxxx>
diff -r 53c5bcecfcfd -r a19a066dea76 tools/Makefile
--- a/tools/Makefile Mon Aug 21 15:03:07 2006 -0500
+++ b/tools/Makefile Mon Aug 21 15:03:09 2006 -0500
@@ -76,7 +76,7 @@ endif
.PHONY: cowd cowdinstall cowclean
cowd/Makefile:
- cd cowd && sh autogen && sh configure
+ cd cowd && sh autogen && sh configure --enable-internal-dmu
cowd cowdinstall: cowd/Makefile
$(MAKE) -C cowd $(patsubst cowd%,%,$@)
cowdclean:
diff -r 53c5bcecfcfd -r a19a066dea76 tools/cowd/Makefile.am
--- a/tools/cowd/Makefile.am Mon Aug 21 15:03:07 2006 -0500
+++ b/tools/cowd/Makefile.am Mon Aug 21 15:03:09 2006 -0500
@@ -1,3 +1,5 @@ bin_PROGRAMS = cowd
+EXTRA_DIST = libdmu/dmu.c libdmu/dmu.h
+
bin_PROGRAMS = cowd
cowd_SOURCES = cowd.c util.c cowd_loader.c cowd_control_loop.c \
@@ -7,5 +9,9 @@ cowd_LDADD = -ldevmapper -lltdl
cowd_LDADD = -ldevmapper -lltdl
cowd_LDFLAGS = -rdynamic -L./lib
+if INTERNAL_DMU
+cowd_SOURCES += libdmu/dmu.c
+endif
+
clean-local:
rm -f *~
diff -r 53c5bcecfcfd -r a19a066dea76 tools/cowd/configure.in
--- a/tools/cowd/configure.in Mon Aug 21 15:03:07 2006 -0500
+++ b/tools/cowd/configure.in Mon Aug 21 15:03:09 2006 -0500
@@ -11,7 +11,19 @@ libdevmapper_error() {
echo "* The version of libdevmapper on this system does *"
echo "* not contain dm-userspace support *"
echo "* *"
+ echo "* If you cannot reinstall libdevmapper, you can include *"
+ echo "* rough internal support with --enable-internal-dmu *"
echo "*************************************************************"
+
+ exit
+}
+
+libdevmapper_conflict() {
+ echo "*************************************************************"
+ echo "* ERROR: The system libdevmapper library has dm-userspace *"
+ echo "* support, which cannot be used in combination with *"
+ echo "* internal support. *"
+ echo "*************************************************************"
exit
}
@@ -30,6 +42,13 @@ AC_ARG_ENABLE(gcov,
COVERAGE="-fprofile-arcs -ftest-coverage",
COVERAGE="")
+AC_ARG_ENABLE(internal-dmu,
+ [AC_HELP_STRING([--enable-internal-dmu],
+ [Enable internal dm-user library support])],
+ need_internal_dmu="yes",
+ need_internal_dmu="")
+AM_CONDITIONAL(INTERNAL_DMU, test x$need_internal_dmu = xyes)
+
# Checks for programs.
AC_PROG_CC
AC_PROG_LIBTOOL
@@ -37,7 +56,14 @@ AC_PROG_LIBTOOL
# Checks for libraries.
AC_CHECK_LIB([devmapper], [dm_task_create],, exit)
AC_CHECK_LIB([ltdl], [lt_dlsym],, exit)
-AC_CHECK_LIB([devmapper], [dmu_ctl_open],, libdevmapper_error)
+
+if test x$need_internal_dmu = xyes; then
+ AC_CHECK_LIB([devmapper], [dmu_ctl_open], libdevmapper_conflict)
+ abs_libdmu_dir=$(readlink -f .)/libdmu
+ GLOBAL_CFLAGS="$GLOBAL_CFLAGS -DINTERNAL_DMU -I$abs_libdmu_dir"
+else
+ AC_CHECK_LIB([devmapper], [dmu_ctl_open],, libdevmapper_error)
+fi
if test -z "$COVERAGE"; then
GLOBAL_CFLAGS="$GLOBAL_CFLAGS"
diff -r 53c5bcecfcfd -r a19a066dea76 tools/cowd/cowd.c
--- a/tools/cowd/cowd.c Mon Aug 21 15:03:07 2006 -0500
+++ b/tools/cowd/cowd.c Mon Aug 21 15:03:09 2006 -0500
@@ -24,6 +24,10 @@
#include <syslog.h>
#include <libdevmapper.h>
+
+#ifdef INTERNAL_DMU
+# include <dmu.h>
+#endif
#include "cowd.h"
#include "cowd_plugin.h"
diff -r 53c5bcecfcfd -r a19a066dea76 tools/cowd/libdmu/dmu.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/libdmu/dmu.c Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,554 @@
+/*
+ * Copyright (C) International Business Machines Corp., 2006
+ * Author: Dan Smith <danms@xxxxxxxxxx>
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License. See the file COPYING in the main directory
+ * of this archive for more details.
+ *
+ */
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+#include <errno.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <libdevmapper.h>
+#include <linux/dm-userspace.h>
+
+#include <dmu.h>
+
+#define DMU_MSG_DEBUG 0
+
+#define QUEUE_SIZE_KB 4096
+
+#if DMU_MSG_DEBUG
+#define DPRINTF( s, arg... ) fprintf(stderr, s, ##arg)
+#else
+#define DPRINTF( s, arg... )
+#endif
+
+struct dmu_events {
+ status_handler status_fn;
+ map_req_handler map_fn;
+};
+
+struct dmu_event_data {
+ void *status_user_data;
+ void *map_user_data;
+};
+
+struct dmu_context {
+ int fd;
+ unsigned int buf_size;
+ unsigned int in_ptr;
+ unsigned int out_ptr;
+ uint8_t *in_buf;
+ uint8_t *out_buf;
+ uint32_t id_ctr;
+ struct dmu_events events;
+ struct dmu_event_data event_data;
+};
+
+struct dmu_map_data {
+ uint64_t block;
+ int64_t offset;
+ uint32_t id;
+ uint32_t flags;
+ dev_t dest_dev;
+ dev_t copy_src_dev;
+};
+
+void dmu_map_set_block(struct dmu_map_data *data, uint64_t block)
+{
+ data->block = block;
+}
+
+uint64_t dmu_map_get_block(struct dmu_map_data *data)
+{
+ return data->block;
+}
+
+void dmu_map_set_offset(struct dmu_map_data *data, int64_t offset)
+{
+ data->offset = offset;
+}
+
+uint32_t dmu_map_get_id(struct dmu_map_data *data)
+{
+ return data->id;
+}
+
+void dmu_map_set_dest_dev(struct dmu_map_data *data, dev_t dev)
+{
+ data->dest_dev = dev;
+}
+
+void dmu_map_set_copy_src_dev(struct dmu_map_data *data, dev_t dev)
+{
+ data->copy_src_dev = dev;
+ dmu_set_flag(&data->flags, DMU_FLAG_COPY_FIRST);
+}
+
+void dmu_map_set_writable(struct dmu_map_data *data, int writable)
+{
+ if (writable)
+ dmu_set_flag(&data->flags, DMU_FLAG_WR);
+ else
+ dmu_clr_flag(&data->flags, DMU_FLAG_WR);
+}
+
+int dmu_map_is_write(struct dmu_map_data *data)
+{
+ return dmu_get_flag(&data->flags, DMU_FLAG_WR);
+}
+
+void dmu_map_set_sync(struct dmu_map_data *data)
+{
+ dmu_set_flag(&data->flags, DMU_FLAG_SYNC);
+}
+
+/*
+ * Get the major/minor of the character control device that @dm_device
+ * has exported for us. We do this by looking at the device status
+ * string.
+ */
+static int get_dm_control_dev(char *dm_device,
+ unsigned *maj, unsigned *min)
+{
+ struct dm_task *task;
+ int ret;
+ void *next = NULL;
+ uint64_t start, length;
+ char *ttype = NULL, *params = NULL;
+
+ task = dm_task_create(DM_DEVICE_STATUS);
+
+ ret = dm_task_set_name(task, dm_device);
+ if (!ret) {
+ DPRINTF("Failed to set device-mapper target name\n");
+ dm_task_destroy(task);
+ return -1;
+ }
+
+ ret = dm_task_run(task);
+ if (!ret) {
+ DPRINTF("Failed to run device-mapper task\n");
+ dm_task_destroy(task);
+ return -1;
+ }
+
+ ret = 0;
+ do {
+ next = dm_get_next_target(task, next, &start, &length,
+ &ttype, ¶ms);
+
+ if (strcmp(ttype, "userspace") == 0) {
+ ret = sscanf(params, "%x:%x", maj, min);
+ if (ret == 2)
+ break;
+ }
+
+ } while (next);
+
+ return 0;
+}
+
+/*
+ * Create the character device node for our control channel
+ */
+static int make_device_node(unsigned major, unsigned minor)
+{
+ char path[256];
+
+ sprintf(path, "/dev/dmu%i", minor);
+
+ return mknod(path, S_IFCHR, makedev(major, minor));
+}
+
+static char *dmu_get_ctl_device(char *dm_device)
+{
+ unsigned ctl_major, ctl_minor;
+ static char path[256];
+
+ if (get_dm_control_dev(dm_device, &ctl_major, &ctl_minor) < 0)
+ return NULL;
+
+ if (ctl_major == 0) {
+ DPRINTF("Unable to get device number\n");
+ return NULL;
+ }
+
+ sprintf(path, "/dev/dmu%i", ctl_minor);
+
+ if (access(path, R_OK | W_OK)) {
+ if (make_device_node(ctl_major, ctl_minor)) {
+ DPRINTF("Failed to create device node: %s",
+ strerror(errno));
+ return NULL;
+ }
+ }
+
+ return path;
+}
+
+static uint32_t make_version(int maj, int min, int patch)
+{
+ return 0 | (maj << 16) | (min << 8) | patch;
+}
+
+static void dmu_split_dev(dev_t dev, uint32_t *maj, uint32_t *min)
+{
+ *maj = (dev & 0xFF00) >> 8;
+ *min = (dev & 0x00FF);
+}
+
+/* Queue a message for sending */
+static int dmu_ctl_queue_msg(struct dmu_context *ctx, int type, void *msg)
+{
+ struct dmu_msg_header hdr;
+
+ hdr.msg_type = type;
+ hdr.payload_len = dmu_get_msg_len(type);
+ hdr.id = ctx->id_ctr++;
+
+ if ((ctx->out_ptr + (sizeof(hdr) + hdr.payload_len)) > ctx->buf_size)
+ return 0; /* No room for this */
+
+ memcpy(ctx->out_buf+ctx->out_ptr, &hdr, sizeof(hdr));
+ ctx->out_ptr += sizeof(hdr);
+
+ memcpy(ctx->out_buf+ctx->out_ptr, msg, hdr.payload_len);
+ ctx->out_ptr += hdr.payload_len;
+
+ return 1;
+}
+
+int dmu_invalidate_block(struct dmu_context *ctx, uint64_t block)
+{
+ struct dmu_msg_invalidate_map inv_msg;
+
+ inv_msg.org_block = block;
+
+ DPRINTF("Queuing invalidation for block %llu\n", block);
+
+ return dmu_ctl_queue_msg(ctx, DM_USERSPACE_MAP_INVALIDATE,
+ &inv_msg);
+}
+
+int dmu_sync_complete(struct dmu_context *ctx, uint32_t id)
+{
+ struct dmu_msg_status status_msg;
+
+ status_msg.id_of_op = id;
+ status_msg.status = DM_USERSPACE_SYNC_COMPLETE;
+
+ DPRINTF("Queuing metadata written for block %llu\n", block);
+
+ return dmu_ctl_queue_msg(ctx, DM_USERSPACE_STATUS,
+ &status_msg);
+}
+
+static int dmu_ctl_peek_queue(struct dmu_context *ctx,
+ int *type, void **msg)
+{
+ struct dmu_msg_header *hdr;
+
+ if (ctx->in_ptr < sizeof(*hdr))
+ return 0;
+
+ hdr = (struct dmu_msg_header *)ctx->in_buf;
+
+ *type = hdr->msg_type;
+ *msg = ctx->in_buf + sizeof(*hdr);
+
+ return 1;
+}
+
+/* Flush queue of messages to the kernel */
+int dmu_ctl_send_queue(struct dmu_context *ctx)
+{
+ int r;
+
+ DPRINTF("Flushing outgoing queue\n");
+
+ r = write(ctx->fd, ctx->out_buf, ctx->out_ptr);
+
+ if (r == ctx->out_ptr)
+ r = 1;
+ else
+ r = 0;
+
+ ctx->out_ptr = 0;
+
+ DPRINTF("Finished flushing queue\n");
+
+ return r;
+}
+
+/* Fill the queue with requests from the kernel */
+static int dmu_ctl_recv_queue(struct dmu_context *ctx)
+{
+ int r;
+
+ r = read(ctx->fd, ctx->in_buf, ctx->buf_size);
+
+ ctx->in_ptr = r;
+
+ if (r >= 0)
+ r = 1;
+ else
+ r = 0;
+
+ return r;
+}
+
+struct dmu_context *dmu_ctl_open(char *dev, int flags)
+{
+ int fd, r, type = 0;
+ struct dmu_msg_version msg;
+ struct dmu_msg_version *response;
+ struct dmu_context *ctx = NULL;
+ char *ctl_dev;
+
+ ctl_dev = dmu_get_ctl_device(dev);
+ if (ctl_dev == NULL)
+ return NULL;
+ else if (access(ctl_dev, R_OK | W_OK))
+ return NULL;
+
+ fd = open(ctl_dev, O_RDWR | flags);
+ if (fd < 0)
+ goto out;
+
+ ctx = calloc(sizeof(*ctx), 1);
+ if (!ctx)
+ goto out;
+
+ ctx->in_buf = malloc(QUEUE_SIZE_KB << 10);
+ if (!ctx->in_buf)
+ goto out;
+ ctx->out_buf = malloc(QUEUE_SIZE_KB << 10);
+ if (!ctx->out_buf)
+ goto out;
+
+ ctx->fd = fd;
+ ctx->in_ptr = ctx->out_ptr = 0;
+ ctx->id_ctr = 0;
+ ctx->buf_size = 4 << 20;
+ memset(&ctx->events, 0, sizeof(ctx->events));
+ memset(&ctx->event_data, 0, sizeof(ctx->event_data));
+
+ msg.userspace_ver = make_version(0, 1, 0);
+
+ r = dmu_ctl_queue_msg(ctx, DM_USERSPACE_GET_VERSION, &msg);
+ if (r < 0)
+ goto out;
+
+ dmu_ctl_send_queue(ctx);
+ dmu_ctl_recv_queue(ctx);
+
+ r = dmu_ctl_peek_queue(ctx, &type, (void**)&response);
+ if (r < 0)
+ goto out;
+
+ if (type != DM_USERSPACE_GET_VERSION) {
+ DPRINTF(stderr, "Got non-version ping back: %i\n", type);
+ goto out;
+ }
+
+ if (response->kernel_ver != msg.userspace_ver) {
+ DPRINTF(stderr, "Version mismatch: %x != %x\n",
+ msg.userspace_ver, response->kernel_ver);
+ goto out;
+ } else {
+ DPRINTF("Version match: %x == %x\n",
+ msg.userspace_ver, response->kernel_ver);
+ }
+
+ return ctx;
+
+ out:
+ if (ctx && ctx->in_buf)
+ free(ctx->in_buf);
+
+ if (ctx && ctx->out_buf)
+ free(ctx->out_buf);
+
+ if (ctx)
+ free(ctx);
+
+ return NULL;
+}
+
+int dmu_ctl_close(struct dmu_context *ctx)
+{
+ return close(ctx->fd);
+}
+
+void dmu_register_status_handler(struct dmu_context *ctx,
+ status_handler handler,
+ void *data)
+{
+ ctx->events.status_fn = handler;
+ ctx->event_data.status_user_data = data;
+}
+
+void dmu_register_map_handler(struct dmu_context *ctx,
+ map_req_handler handler,
+ void *data)
+{
+ ctx->events.map_fn = handler;
+ ctx->event_data.map_user_data = data;
+}
+
+int dmu_events_pending(struct dmu_context *ctx, unsigned int msec)
+{
+ fd_set fds;
+ struct timeval tv;
+
+ FD_ZERO(&fds);
+ FD_SET(ctx->fd, &fds);
+
+ tv.tv_sec = msec / 1000;
+ tv.tv_usec = (msec % 1000) * 1000;
+
+ if (select(ctx->fd + 1, &fds, NULL, NULL, &tv) < 0)
+ return 0;
+
+ if (FD_ISSET(ctx->fd, &fds))
+ return 1;
+ else
+ return 0;
+}
+
+static int fire_map_req_event(struct dmu_context *ctx,
+ struct dmu_msg_map_request *req,
+ uint32_t id)
+{
+ struct dmu_msg_map_response resp;
+ struct dmu_map_data data;
+ int ret;
+
+ if (!ctx->events.map_fn)
+ return 1;
+
+ DPRINTF("Map event for %llu %c\n",
+ req->org_block,
+ dmu_get_flag(&req->flags, DMU_FLAG_WR) ? 'W':'R');
+
+ data.block = req->org_block;
+ data.offset = 0;
+ data.id = id;
+ data.flags = req->flags;
+ data.dest_dev = data.copy_src_dev = 0;
+
+ dmu_clr_flag(&data.flags, DMU_FLAG_COPY_FIRST);
+ dmu_clr_flag(&data.flags, DMU_FLAG_SYNC);
+
+ ret = ctx->events.map_fn(ctx->event_data.map_user_data, &data);
+
+ resp.org_block = req->org_block;
+ resp.new_block = data.block;
+ resp.offset = data.offset;
+ resp.flags = data.flags;
+ resp.id_of_req = data.id;
+
+ dmu_split_dev(data.copy_src_dev, &resp.src_maj, &resp.src_min);
+ dmu_split_dev(data.dest_dev, &resp.dst_maj, &resp.dst_min);
+
+ DPRINTF("Mapped %llu -> %llu\n", resp.org_block, resp.new_block);
+
+ if (ret < 0)
+ dmu_ctl_queue_msg(ctx, DM_USERSPACE_MAP_FAILED, &resp);
+ else
+ dmu_ctl_queue_msg(ctx, DM_USERSPACE_MAP_BLOCK_RESP, &resp);
+
+ return ret;
+}
+
+static int fire_status_event(struct dmu_context *ctx,
+ struct dmu_msg_status *status,
+ uint32_t id)
+{
+ uint32_t user_code;
+
+ switch (status->status) {
+ case DM_USERSPACE_INVAL_COMPLETE:
+ user_code = DMU_STATUS_INVAL_COMPLETE;
+ break;
+ case DM_USERSPACE_INVAL_FAILED:
+ user_code = DMU_STATUS_INVAL_FAILED;
+ break;
+ case DM_USERSPACE_SYNC_COMPLETE:
+ user_code = DMU_STATUS_SYNC_COMPLETE;
+ break;
+ default:
+ user_code = DMU_STATUS_UNKNOWN;
+ };
+
+ if (ctx->events.status_fn)
+ ctx->events.status_fn(ctx->event_data.status_user_data,
+ status->id_of_op, user_code);
+
+ return 0;
+}
+
+static int decode_message(struct dmu_context *ctx, int type, uint32_t id,
+ uint8_t *msg)
+{
+ switch (type) {
+ case DM_USERSPACE_MAP_BLOCK_REQ:
+ DPRINTF("Request event: %u\n", id);
+ return fire_map_req_event(ctx,
+ (struct dmu_msg_map_request *)msg,
+ id);
+ case DM_USERSPACE_STATUS:
+ DPRINTF("Status event\n");
+ return fire_status_event(ctx,
+ (struct dmu_msg_status *)msg,
+ id);
+ default:
+ DPRINTF("Unknown message type: %i\n", type);
+ return -1; /* Unknown message type */
+ };
+}
+
+int dmu_process_events(struct dmu_context *ctx)
+{
+ struct dmu_msg_header *hdr;
+ int ptr = 0, ret, do_flush = 0;
+
+ if (!dmu_ctl_recv_queue(ctx))
+ return -1; /* Receive failed */
+
+ DPRINTF("Got %i bytes\n", ctx->in_ptr);
+
+ ptr = 0;
+ while (ptr < ctx->in_ptr) {
+ hdr = (struct dmu_msg_header *)&ctx->in_buf[ptr];
+ ptr += sizeof(*hdr);
+
+ ret = decode_message(ctx, hdr->msg_type, hdr->id,
+ &ctx->in_buf[ptr]);
+ if (ret > 0)
+ do_flush = 1;
+
+ ptr += hdr->payload_len;
+ };
+
+ ctx->in_ptr = 0;
+
+ if (do_flush) {
+ DPRINTF("Flushing outgoing message queue as requested\n");
+ dmu_ctl_send_queue(ctx);
+ }
+
+ return 1;
+}
+
diff -r 53c5bcecfcfd -r a19a066dea76 tools/cowd/libdmu/dmu.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/libdmu/dmu.h Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,50 @@
+#ifndef __DMU_H
+#define __DMU_H
+
+#include <stdint.h>
+
+/**************
+ * dm-userspace
+ **************/
+
+enum {
+ DMU_STATUS_UNKNOWN = 0,
+ DMU_STATUS_BLOCK_FLUSHED,
+ DMU_STATUS_INVAL_COMPLETE,
+ DMU_STATUS_INVAL_FAILED,
+ DMU_STATUS_SYNC_COMPLETE
+};
+
+struct dmu_context;
+struct dmu_map_data;
+
+typedef int (*status_handler)(void *data, uint32_t id, uint32_t status);
+typedef int (*map_req_handler)(void *data, struct dmu_map_data *map_data);
+
+/* High-level control operations */
+struct dmu_context *dmu_ctl_open(char *dev, int flags);
+int dmu_ctl_close(struct dmu_context *ctx);
+int dmu_ctl_send_queue(struct dmu_context *ctx);
+void dmu_register_status_handler(struct dmu_context *ctx,
+ status_handler handler,
+ void *data);
+void dmu_register_map_handler(struct dmu_context *ctx,
+ map_req_handler handler,
+ void *data);
+int dmu_invalidate_block(struct dmu_context *ctx, uint64_t block);
+int dmu_sync_complete(struct dmu_context *ctx, uint32_t id);
+int dmu_events_pending(struct dmu_context *ctx, unsigned int msec);
+int dmu_process_events(struct dmu_context *ctx);
+
+/* Map manipulation functions */
+void dmu_map_set_block(struct dmu_map_data *data, uint64_t block);
+uint64_t dmu_map_get_block(struct dmu_map_data *data);
+void dmu_map_set_offset(struct dmu_map_data *data, int64_t offset);
+uint32_t dmu_map_get_id(struct dmu_map_data *data);
+void dmu_map_set_dest_dev(struct dmu_map_data *data, dev_t dev);
+void dmu_map_set_copy_src_dev(struct dmu_map_data *data, dev_t dev);
+void dmu_map_set_writable(struct dmu_map_data *data, int writable);
+int dmu_map_is_write(struct dmu_map_data *data);
+void dmu_map_set_sync(struct dmu_map_data *data);
+
+#endif
diff -r 53c5bcecfcfd -r a19a066dea76 tools/cowd/libdmu/linux/dm-userspace.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/libdmu/linux/dm-userspace.h Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) International Business Machines Corp., 2006
+ * Author: Dan Smith <danms@xxxxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __DM_USERSPACE_H
+#define __DM_USERSPACE_H
+
+#include <linux/types.h>
+
+/*
+ * Message Types
+ */
+#define DM_USERSPACE_GET_VERSION 1
+#define DM_USERSPACE_MAP_BLOCK_REQ 2
+#define DM_USERSPACE_MAP_BLOCK_RESP 3
+#define DM_USERSPACE_MAP_FAILED 4
+#define DM_USERSPACE_MAP_INVALIDATE 5
+#define DM_USERSPACE_STATUS 6
+
+/*
+ * Status codes
+ */
+#define DM_USERSPACE_INVAL_COMPLETE 101
+#define DM_USERSPACE_INVAL_FAILED 102
+#define DM_USERSPACE_SYNC_COMPLETE 103
+
+/*
+ * Flags and associated macros
+ */
+#define DMU_FLAG_VALID 1
+#define DMU_FLAG_RD 2
+#define DMU_FLAG_WR 4
+#define DMU_FLAG_COPY_FIRST 8
+#define DMU_FLAG_TEMPORARY 16
+#define DMU_FLAG_INUSE 32
+#define DMU_FLAG_SYNC 64
+#define DMU_FLAG_WAITING 128
+
+static int dmu_get_flag(uint32_t *flags, uint32_t flag)
+{
+ return (*flags & flag) != 0;
+}
+
+static void dmu_set_flag(uint32_t *flags, uint32_t flag)
+{
+ *flags |= flag;
+}
+
+static void dmu_clr_flag(uint32_t *flags, uint32_t flag)
+{
+ *flags &= (~flag);
+}
+
+static void dmu_cpy_flag(uint32_t *flags, uint32_t src, uint32_t flag)
+{
+ *flags = (*flags & ~flag) | (src & flag);
+}
+
+/*
+ * This message header is sent in front of every message, in both
+ * directions
+ */
+struct dmu_msg_header {
+ uint32_t msg_type;
+ uint32_t payload_len;
+ uint32_t id;
+};
+
+/* DM_USERSPACE_GET_VERSION */
+struct dmu_msg_version {
+ uint32_t userspace_ver;
+ uint32_t kernel_ver;
+};
+
+/* For status codes */
+struct dmu_msg_status {
+ uint32_t id_of_op;
+ uint32_t status;
+};
+
+/* DM_USERSPACE_MAP_BLOCK_REQ */
+struct dmu_msg_map_request {
+ uint64_t org_block;
+
+ uint32_t flags;
+};
+
+/* DM_USERSPACE_MAP_BLOCK_RESP
+ * DM_USERSPACE_MAP_BLOCK_FAILED
+ */
+struct dmu_msg_map_response {
+ uint64_t org_block;
+ uint64_t new_block;
+ int64_t offset;
+
+ uint32_t id_of_req;
+ uint32_t flags;
+
+ uint32_t src_maj;
+ uint32_t src_min;
+
+ uint32_t dst_maj;
+ uint32_t dst_min;
+};
+
+/* DM_USERSPACE_MAP_INVALIDATE */
+struct dmu_msg_invalidate_map {
+ uint64_t org_block;
+};
+
+static inline int dmu_get_msg_len(int type)
+{
+ switch (type) {
+ case DM_USERSPACE_GET_VERSION:
+ return sizeof(struct dmu_msg_version);
+ case DM_USERSPACE_INVAL_COMPLETE:
+ case DM_USERSPACE_INVAL_FAILED:
+ case DM_USERSPACE_STATUS:
+ return sizeof(struct dmu_msg_status);
+ case DM_USERSPACE_MAP_BLOCK_REQ:
+ return sizeof(struct dmu_msg_map_request);
+ case DM_USERSPACE_MAP_BLOCK_RESP:
+ case DM_USERSPACE_MAP_FAILED:
+ return sizeof(struct dmu_msg_map_response);
+ case DM_USERSPACE_MAP_INVALIDATE:
+ return sizeof(struct dmu_msg_invalidate_map);
+ default:
+ return -1;
+ };
+}
+
+#endif
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|