WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: Xen Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 3 of 6] dm-userspace internal libdmu support for userspace tool
From: Ryan Grimm <grimm@xxxxxxxxxx>
Date: Fri, 25 Aug 2006 16:24:00 -0500
Cc: Dan Smith <danms@xxxxxxxxxx>
Delivery-date: Fri, 25 Aug 2006 14:26:17 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1156540578@venkman-64>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.5.6+20040907i
Signed-off-by: Ryan Grimm <grimm@xxxxxxxxxx>
Signed-off-by: Dan Smith <danms@xxxxxxxxxx>

# HG changeset patch
# User Ryan Grimm <grimm@xxxxxxxxxx>
# Date 1156536094 18000
# Node ID 8c8d5dc4eaf4f0044f7fdd5adb282359eff7263a
# Parent  7ca9885684d9eaeef4422d52f9ae9efd033650d0
dm-userspace internal libdmu support for userspace tool

diff -r 7ca9885684d9 -r 8c8d5dc4eaf4 tools/Makefile
--- a/tools/Makefile    Fri Aug 25 15:01:33 2006 -0500
+++ b/tools/Makefile    Fri Aug 25 15:01:34 2006 -0500
@@ -77,7 +77,7 @@ endif
 .PHONY: cowd cowdinstall cowclean
 cowd/Makefile:
        -which libtoolize && which aclocal && which automake && \
-         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 7ca9885684d9 -r 8c8d5dc4eaf4 tools/cowd/Makefile.am
--- a/tools/cowd/Makefile.am    Fri Aug 25 15:01:33 2006 -0500
+++ b/tools/cowd/Makefile.am    Fri Aug 25 15:01:34 2006 -0500
@@ -1,3 +1,5 @@ bin_PROGRAMS = cowd
+EXTRA_DIST = libdmu/dmu.c libdmu/dmu.h libdmu/internal_renames
+
 bin_PROGRAMS = cowd
 
 cowd_SOURCES = cowd.c util.c cowd_loader.c cowd_control_loop.c \
@@ -7,5 +9,13 @@ cowd_LDADD   = -ldevmapper -lltdl
 cowd_LDADD   = -ldevmapper -lltdl
 cowd_LDFLAGS = -rdynamic -L./lib
 
+if INTERNAL_DMU
+cowd_SOURCES += libdmu/dmu.c
+all-local:
+       for obj in cowd lib/*.so; do \
+         objcopy --redefine-syms libdmu/internal_renames $$obj; \
+       done
+endif
+
 clean-local:
        rm -f *~
diff -r 7ca9885684d9 -r 8c8d5dc4eaf4 tools/cowd/configure.in
--- a/tools/cowd/configure.in   Fri Aug 25 15:01:33 2006 -0500
+++ b/tools/cowd/configure.in   Fri Aug 25 15:01:34 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 1
 }
@@ -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 7ca9885684d9 -r 8c8d5dc4eaf4 tools/cowd/cowd.c
--- a/tools/cowd/cowd.c Fri Aug 25 15:01:33 2006 -0500
+++ b/tools/cowd/cowd.c Fri Aug 25 15:01:34 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 7ca9885684d9 -r 8c8d5dc4eaf4 tools/cowd/libdmu/dmu.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/libdmu/dmu.c   Fri Aug 25 15:01:34 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 7ca9885684d9 -r 8c8d5dc4eaf4 tools/cowd/libdmu/dmu.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/libdmu/dmu.h   Fri Aug 25 15:01:34 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 7ca9885684d9 -r 8c8d5dc4eaf4 tools/cowd/libdmu/internal_renames
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/libdmu/internal_renames        Fri Aug 25 15:01:34 2006 -0500
@@ -0,0 +1,23 @@
+dmu_ctl_open int__dmu_ctl_open 
+dmu_clr_flag int__dmu_clr_flag
+dmu_ctl_close int__dmu_ctl_close
+dmu_ctl_queue_msg int__dmu_ctl_queue_msg
+dmu_ctl_recv_queue int__dmu_ctl_recv_queue
+dmu_ctl_send_queue int__dmu_ctl_send_queue
+dmu_events_pending int__dmu_events_pending
+dmu_invalidate_block int__dmu_invalidate_block
+dmu_map_get_block int__dmu_map_get_block
+dmu_map_get_id int__dmu_map_get_id
+dmu_map_is_write int__dmu_map_is_write
+dmu_map_set_block int__dmu_map_set_block
+dmu_map_set_copy_src_dev int__dmu_map_set_copy_src_dev
+dmu_map_set_dest_dev int__dmu_map_set_dest_dev
+dmu_map_set_offset int__dmu_map_set_offset
+dmu_map_set_sync int__dmu_map_set_sync
+dmu_map_set_writable int__dmu_map_set_writable
+dmu_process_events int__dmu_process_events
+dmu_register_map_handler int__dmu_register_map_handler
+dmu_register_status_handler int__dmu_register_status_handler
+dmu_set_flag int__dmu_set_flag
+dmu_split_dev int__dmu_split_dev
+dmu_sync_complete int__dmu_sync_complete
diff -r 7ca9885684d9 -r 8c8d5dc4eaf4 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    Fri Aug 25 15:01:34 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

<Prev in Thread] Current Thread [Next in Thread>