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: Mon, 21 Aug 2006 15:55:25 -0500
Cc: Dan Smith <danms@xxxxxxxxxx>
Delivery-date: Mon, 21 Aug 2006 13:58:06 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1156192193@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
# 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

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