[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 3 of 6] dm-userspace internal libdmu support for userspace tool



# 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, &params);
+
+               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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.