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

[Xen-devel] [PATCH 4 of 6] dscow plugin for dm-userspace userspace tool



# HG changeset patch
# User Ryan Grimm <grimm@xxxxxxxxxx>
# Date 1156190589 18000
# Node ID 6a7ea5a3554309b4e37e3e8bcbd6a11b8cdc4386
# Parent  a19a066dea764a70f06b4e4341229db92c2eb5c3
dscow plugin for dm-userspace userspace tool

Signed-off-by: Ryan Grimm <grimm@xxxxxxxxxx>
Signed-off-by: Dan Smith <danms@xxxxxxxxxx>

diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/Makefile.am
--- a/tools/cowd/Makefile.am    Mon Aug 21 15:03:09 2006 -0500
+++ b/tools/cowd/Makefile.am    Mon Aug 21 15:03:09 2006 -0500
@@ -1,3 +1,5 @@ EXTRA_DIST = libdmu/dmu.c libdmu/dmu.h
+SUBDIRS = plugins
+
 EXTRA_DIST = libdmu/dmu.c libdmu/dmu.h
 
 bin_PROGRAMS = cowd
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/configure.in
--- a/tools/cowd/configure.in   Mon Aug 21 15:03:09 2006 -0500
+++ b/tools/cowd/configure.in   Mon Aug 21 15:03:09 2006 -0500
@@ -93,11 +93,15 @@ AC_SUBST(PLUGIN_DIR)
 AC_SUBST(PLUGIN_DIR)
 AC_SUBST(GLOBAL_CFLAGS)
 
-AC_CONFIG_FILES([Makefile])
+AC_CONFIG_FILES([Makefile
+                plugins/Makefile
+                plugins/dscow/Makefile])
 
 # This just makes it easier to run cowd from the source directory
 # for testing
 mkdir -p lib
+ln -sf ../plugins/dscow/.libs/libcowd_dscow.so.0 lib/libcowd_dscow.so
+ln -sf ../plugins/dscow/.libs/libcowd_dscow.la lib/libcowd_dscow.la
 
 AC_OUTPUT
 
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/cowd_control_loop.c
--- a/tools/cowd/cowd_control_loop.c    Mon Aug 21 15:03:09 2006 -0500
+++ b/tools/cowd/cowd_control_loop.c    Mon Aug 21 15:03:09 2006 -0500
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) International Business Machines Corp., 2006
  * Author: Dan Smith <danms@xxxxxxxxxx>
+ * Author: Ryan Grimm <grimm@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
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/plugins/Makefile.am
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/Makefile.am    Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,1 @@
+SUBDIRS = dscow
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/plugins/dscow/Makefile.am
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/Makefile.am      Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,14 @@
+EXTRA_DIST = README
+
+lib_LTLIBRARIES = libcowd_dscow.la
+libcowd_dscow_la_CFLAGS = -I../.. -I../../../../module @GLOBAL_CFLAGS@
+libcowd_dscow_la_SOURCES = dscow_ops.c dscow_plugin.c dscow_ops.h
+libcowd_dscow_la_LIBADD = 
+
+bin_PROGRAMS = dscow_tool
+dscow_tool_SOURCES = dscow_tool.c dscow_ops.c ../../util.c
+dscow_tool_CFLAGS = @GLOBAL_CFLAGS@
+
+#noinst_PROGRAMS = dscow_test
+#dscow_test_SOURCES = dscow_test.c dscow_ops.c
+
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/plugins/dscow/README
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/README   Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,13 @@
+To create a dscow image, run "dscow_tool" as follows:
+
+ # dscow_tool -c foo.dscow /path/to/base.img
+
+Which will create a "foo.dscow" file that uses '/path/to/base.img' as
+its base and 64kb blocks.
+
+Then, start a cowd instance like this:
+
+ # cowd -p dscow mydev /path/to/foo.dscow
+
+The base image will be loaded automatically.
+
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/plugins/dscow/dscow_ops.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/dscow_ops.c      Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,417 @@
+/*
+ * 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.
+ *
+ */
+
+#define _LARGEFILE64_SOURCE
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "dscow_ops.h"
+
+#define MAX_VERSION 1
+
+#if 0
+#define DPRINTF( s, arg... ) fprintf(stderr, s, ##arg)
+#else
+#define DPRINTF( s, arg... )
+#endif
+
+int dscow_errno = 0;
+
+void dscow_print_info(struct dscow *handle)
+{
+       uint32_t i;
+       uint64_t size_mb = handle->header.size >> 20;
+       uint32_t bsize_kb = handle->header.block_size >> 10;
+       uint64_t mapped_blocks = 0;
+
+       printf("Base Image:      %s\n", handle->base_filename);
+       printf("Size:            %llu (%llu MB)\n", 
+              handle->header.size, size_mb);
+       printf("Block size:      %lu (%lu KB)\n",
+              handle->header.block_size, bsize_kb);
+       printf("First block:     %llu\n", handle->header.first_block);
+       printf("Blocks:          %llu\n", handle->blocks);
+       printf("Bitmap count:    %u\n", handle->bitmap_count);
+       printf("Format Version:  %u (we support up to version %u)\n", 
+              handle->header.version, MAX_VERSION);
+
+       if (!handle->bitmap)
+               return;
+
+       for (i = 0; i < handle->bitmap_count; i++) {
+               uint32_t field = handle->bitmap[i];
+               for (field = handle->bitmap[i]; field; field >>= 1)
+                       mapped_blocks++;
+               DPRINTF(" Field %u: %08x\n", i, handle->bitmap[i]);
+       }
+
+       printf("Usage:           %2.1f%% %lluMB (%llu blocks)\n",
+              ((float)mapped_blocks / handle->blocks) * 100.0,
+              (mapped_blocks * handle->header.block_size) >> 20,
+              mapped_blocks);
+
+}
+
+static int _dscow_read_bitmap(struct dscow *dscow)
+{
+       uint32_t i;
+       int ret = 0;
+
+       dscow_errno = 0;
+
+       dscow->bitmap = calloc(dscow->bitmap_count, sizeof(uint32_t));
+       if (!dscow->bitmap) {
+               dscow_errno = ENOMEM;
+               return -1;
+       }
+       
+       DPRINTF("Seeking to bitmap @ %llu for read\n",
+               dscow->header.bitmap_offset);
+
+       lseek64(dscow->fd, dscow->header.bitmap_offset, SEEK_SET);
+
+       for (i = 0; i < dscow->bitmap_count; i++) {
+               ret = read(dscow->fd, 
+                          &dscow->bitmap[i],
+                          sizeof(dscow->bitmap[i]));
+               if (ret < 0) {
+                       dscow_errno = errno;
+                       break;
+               }
+
+               if (dscow->bitmap[i] != 0)
+                       DPRINTF("  Bitmap:%08x %08x\n", i, dscow->bitmap[i]);
+       }
+
+       return ret;
+}
+
+static int _dscow_write_bitmap(struct dscow *dscow)
+{
+       uint32_t i;
+       int ret = 0;
+
+       DPRINTF("Seeking to bitmap @ %llu for write \n",
+               dscow->header.bitmap_offset);
+
+       lseek64(dscow->fd, dscow->header.bitmap_offset, SEEK_SET);
+
+       for (i = 0; i < dscow->bitmap_count; i++) {
+               ret = write(dscow->fd,
+                           &dscow->bitmap[i],
+                           sizeof(dscow->bitmap[i]));
+               if (ret < 0) {
+                       dscow_errno = errno;
+                       break;
+               }
+
+               if (dscow->bitmap[i] != 0)
+                       DPRINTF("  Bitmap:%08x %08x\n", i, dscow->bitmap[i]);
+       }
+       
+       return ret;
+}
+
+static int _dscow_read_base_file(struct dscow *dscow)
+{
+       int ret = 0;
+
+       dscow->base_filename = malloc(dscow->header.base_file_size+1);
+       memset(dscow->base_filename, 0, dscow->header.base_file_size);
+
+       lseek64(dscow->fd, dscow->header.base_file_offset, SEEK_SET);
+       ret = read(dscow->fd, 
+                  dscow->base_filename, 
+                  dscow->header.base_file_size);
+       dscow->base_filename[dscow->header.base_file_size] = '\0';
+
+       if (ret < 0) {
+               dscow_errno = errno;
+       }
+
+       return ret;
+}
+
+static int _dscow_write_base_file(struct dscow *dscow)
+{
+       int ret = 0;
+
+       lseek64(dscow->fd, dscow->header.base_file_offset, SEEK_SET);
+       ret = write(dscow->fd,
+                   dscow->base_filename, 
+                   dscow->header.base_file_size);
+
+       if (ret < 0)
+               dscow_errno = errno;
+
+       return ret;
+}
+
+static int _dscow_read_disk_header(struct dscow *dscow)
+{
+       int ret = 0;
+
+       lseek64(dscow->fd, 0, SEEK_SET);
+
+       ret = read(dscow->fd, &dscow->header, sizeof(dscow->header));
+       if (ret < 0) {
+               dscow_errno = errno;
+               return ret;
+       } else if (ret != sizeof(dscow->header)) {
+               return 1;
+       }
+
+       dscow->blocks = dscow->header.size / dscow->header.block_size;
+       dscow->bitmap_count = dscow->blocks / (sizeof(uint32_t) * 8) + 1;
+       
+       if (dscow->header.magic != DSCOW_MAGIC) {
+               dscow_errno = EINVAL;
+               return -1;
+       }
+
+       if (_dscow_read_bitmap(dscow) < 0)
+               return -1;
+
+       if (_dscow_read_base_file(dscow) < 0)
+               return -1;
+
+       return 0;
+}
+
+static int _dscow_write_disk_header(struct dscow *dscow)
+{
+       int ret = 0;
+
+       lseek64(dscow->fd, 0, SEEK_SET);
+       
+       ret = write(dscow->fd, &dscow->header, sizeof(dscow->header));
+       if (ret < 0) {
+               dscow_errno = errno;
+               return ret;
+       } else if (ret != sizeof(dscow->header)) {
+               return 1;
+       }
+
+       if (!_dscow_write_bitmap(dscow) < 0)
+               return -1;
+
+       if (!_dscow_write_base_file(dscow) < 0)
+               return -1;
+       
+       return 0;
+}
+
+void dscow_cleanup(struct dscow *dscow)
+{
+       if (!dscow)
+               return;
+
+       if (dscow->bitmap)
+               free(dscow->bitmap);
+       
+       if (dscow->base_filename)
+               free(dscow->base_filename);
+       
+       free(dscow);
+}
+
+struct dscow *dscow_open(char *path)
+{
+       struct dscow *handle;
+       int ret;
+
+       handle = malloc(sizeof(*handle));
+       if (!handle) {
+               dscow_errno = ENOMEM;
+               return NULL;
+       }
+
+       handle->fd = open(path, O_RDWR | O_SYNC);
+       if (handle->fd < 0) {
+               DPRINTF("Failed to open %s\n", path);
+               dscow_errno = errno;
+               return NULL;
+       }
+
+       ret = _dscow_read_disk_header(handle);
+       if (ret < 0) {
+               dscow_cleanup(handle);
+               dscow_errno = EINVAL;
+               return NULL;
+       } else if (ret != 0) {
+               dscow_errno = EIO;
+               return NULL;
+       }
+
+       if (handle->header.version > MAX_VERSION) {
+               DPRINTF("Unknown format version %u\n", 
+                       handle->header.version);
+               /* FIXME: Leak */
+               dscow_errno = ENOTSUP;
+               return NULL;
+       }
+
+       handle->dirty = 0;
+
+       return handle;
+}
+
+struct dscow *dscow_create(char *filename, char *base, uint32_t block_size)
+{
+       struct dscow *handle;
+       struct stat st;
+       uint64_t bitmap_end;
+       uint64_t s2;
+       char x;
+       int ret;
+       off64_t offset;
+
+       handle = malloc(sizeof(*handle));
+       if (!handle) {
+               dscow_errno = ENOMEM;
+               return NULL;
+       }
+
+       handle->header.magic = DSCOW_MAGIC;
+       handle->header.version = 1;
+
+       handle->fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+       if (handle->fd < 0) {
+               dscow_errno = errno;
+               perror("open");
+               dscow_cleanup(handle);
+               return NULL;
+       }
+
+       /* Virtual Size */
+       stat(base, &st);
+       if (S_ISREG(st.st_mode))
+               handle->header.size = st.st_size;
+       else if (S_ISBLK(st.st_mode)) {
+               get_device_size(base, &s2);
+               handle->header.size = s2;
+       }
+       else
+               return NULL; /* Unknown type */
+
+       handle->header.block_size = block_size;
+
+       handle->base_filename = malloc(strlen(base) + 1);
+       strcpy(handle->base_filename, base);
+
+       handle->blocks = handle->header.size / handle->header.block_size;
+       handle->bitmap_count = (handle->blocks / (sizeof(uint32_t) * 8)) + 1;
+       
+       /* Base Filename Location */
+       handle->header.base_file_offset = sizeof(handle->header);
+       handle->header.base_file_size = strlen(handle->base_filename);
+
+       /* Bitmap Location */
+       handle->header.bitmap_offset = handle->header.base_file_offset + 
+               handle->header.base_file_size;
+               
+       /* First Block Location */
+       bitmap_end = handle->header.bitmap_offset + 
+               (handle->bitmap_count * sizeof(uint32_t));
+       handle->header.first_block = 
+               (bitmap_end + (handle->header.block_size - 1)) &
+               ~(handle->header.block_size - 1);
+
+       handle->bitmap = calloc(handle->bitmap_count, sizeof(uint32_t));
+
+       
+       ret = _dscow_write_disk_header(handle);
+       if (ret < 0) {
+               dscow_errno = errno;
+               dscow_cleanup(handle);
+               return NULL;
+       } else if (ret > 0) {
+               dscow_errno = EIO;
+               return NULL;
+       }               
+
+       /* Inflate by seeking to the last byte in the file and then
+          writing to it */
+       offset = lseek64(handle->fd,
+                      (handle->header.size + handle->header.first_block) - 1, 
+                      SEEK_SET);
+       if (offset != (handle->header.size + handle->header.first_block) - 1) {
+               DPRINTF("Failed to lseek to %llu\n",
+                       (handle->header.size + handle->header.first_block)-1);
+               dscow_errno = EIO;
+               /* FIXME: Leak */
+               return NULL;
+       }
+       if (write(handle->fd, &x, 1) != 1) {
+               DPRINTF("Failed to write inflation byte\n");
+               dscow_errno = EIO;
+               return NULL;
+       }
+
+       handle->dirty = 0;
+
+       return handle;
+}
+
+int dscow_sync(struct dscow *handle)
+{
+       int ret = 0;
+
+       ret = _dscow_write_disk_header(handle);
+       if (ret != 0)
+               dscow_errno = EIO;
+       else
+               handle->dirty = 0;
+
+       return ret;
+}
+
+void dscow_close(struct dscow *handle)
+{
+       if (handle->dirty)
+               dscow_sync(handle);
+
+       close(handle->fd);
+
+       dscow_cleanup(handle);
+}
+
+void dscow_map_block(struct dscow *handle, uint64_t block)
+{
+       uint32_t field;
+       uint32_t bit;
+
+       field = block / (sizeof(uint32_t) * 8);
+       bit = block % (sizeof(uint32_t) * 8);
+
+       handle->bitmap[field] |= (1 << bit);
+
+       handle->dirty = 1;
+}
+
+int dscow_is_block_mapped(struct dscow *handle, uint64_t block)
+{
+       uint32_t field;
+       uint32_t bit;
+       
+       field = block / (sizeof(uint32_t) * 8);
+       bit = block % (sizeof(uint32_t) * 8);
+       
+       return (handle->bitmap[field] & (1 << bit)) != 0;
+}
+
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/plugins/dscow/dscow_ops.h
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/dscow_ops.h      Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef __DSCOW_OPS_H
+#define __DSCOW_OPS_H
+
+#include <stdint.h>
+
+#define DSCOW_MAGIC (('D'<<24) | ('a'<<16) | ('n'<<8) | ('S'))
+
+struct dscow_disk_header {
+       uint32_t magic;
+       uint32_t version;
+       uint64_t size;
+       uint64_t base_file_offset;
+       uint32_t base_file_size;
+       uint64_t bitmap_offset;
+       uint64_t first_block;
+       uint32_t block_size;
+};
+
+struct dscow {
+        struct dscow_disk_header header;
+
+        uint64_t blocks;
+        uint32_t *bitmap;
+        uint32_t bitmap_count;
+        char *base_filename;
+
+        int fd;
+       int dirty;      
+};
+
+extern int dscow_errno;
+
+struct dscow *dscow_create(char *filename, char *base, uint32_t block_size);
+struct dscow *dscow_open(char *path);
+void dscow_close(struct dscow *handle);
+int dscow_sync(struct dscow *handle);
+int dscow_is_block_mapped(struct dscow *handle, uint64_t block);
+void dscow_map_block(struct dscow *handle, uint64_t block);
+void dscow_print_info(struct dscow *handle);
+#endif
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/plugins/dscow/dscow_plugin.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/dscow_plugin.c   Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) International Business Machines Corp., 2006
+ * Author: Dan Smith <danms@xxxxxxxxxx>
+ * Author: Ryan Grimm <grimm@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 <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdint.h>
+
+#include <cowd_plugin.h>
+
+#include "dscow_ops.h"
+
+#define ERR_LEN 256
+#define PATH_LEN 256
+
+static char errmsg[ERR_LEN];
+
+struct dscow_prv {
+       char base_dev[PATH_LEN];
+       char cow_dev[PATH_LEN];
+       dev_t base;
+       dev_t cow;
+       struct dscow *dscow;
+};
+
+static dev_t *dscow_get_devs(struct cow_device *dev, int *count)
+{
+       struct dscow_prv *prv = dev->plugin_private;
+       dev_t *devs;
+
+       devs = malloc(sizeof(*devs) * 2);
+       if (!devs) {
+               *count = 0;
+               return NULL;
+       }
+       
+       devs[0] = prv->base;
+       devs[1] = prv->cow;
+
+       *count = 2;
+       return devs;
+}
+
+static int dscow_init(struct cow_device *dev, int debug)
+{
+       struct dscow_prv *prv;
+       struct stat s;
+       char loop_dev[128];
+
+       debug = 1;
+
+       if (dev->plugin_num_args != 2) {
+               snprintf(errmsg, ERR_LEN, "Need two arguments");
+               return PLUGIN_FAIL;
+       }
+
+       prv = malloc(sizeof(*prv));
+       if (!prv) {
+               snprintf(errmsg, ERR_LEN, "Failed to allocate memory");
+               return PLUGIN_FAIL;
+       }
+
+       /* Need some grace here */
+       prv->dscow = dscow_open(dev->plugin_args[1]);
+       if (!prv->dscow) {
+               free(prv);
+               snprintf(errmsg, ERR_LEN, "Failed to open dscow: %s",
+                        strerror(dscow_errno));
+               return PLUGIN_FAIL;
+       }
+
+       snprintf(prv->base_dev, PATH_LEN, "%s", prv->dscow->base_filename);
+       snprintf(prv->cow_dev, PATH_LEN, "%s", dev->plugin_args[1]);
+
+       if (is_file(prv->base_dev)) {
+               int ret;
+               int i = 0;
+               for (i = 0; i < 256; i++) {
+                       sprintf(loop_dev, "/dev/loop%d", i);
+                       ret = loop_setup(loop_dev, prv->base_dev);
+                       if (ret)
+                               break;  
+               }
+               snprintf(prv->base_dev, PATH_LEN, loop_dev);
+       }
+
+       if (is_file(prv->cow_dev)) {
+               int ret;
+               int i = 0;
+               for (i = 0; i < 256; i++) {
+                       sprintf(loop_dev, "/dev/loop%d", i);
+                       ret = loop_setup(loop_dev, prv->cow_dev);
+                       if (ret)
+                               break;  
+               }
+               snprintf(prv->cow_dev, PATH_LEN, loop_dev);
+       }
+
+       /* FIXME: replace this with a call */
+       dev->block_size = (uint64_t)prv->dscow->header.block_size;
+       dev->blocks = prv->dscow->blocks;
+
+       fflush(stdout);
+       stat(prv->base_dev, &s);
+       prv->base = s.st_rdev;
+
+       stat(prv->cow_dev, &s);
+       prv->cow = s.st_rdev;
+
+       dev->plugin_private = prv;
+
+       return PLUGIN_OK;
+}
+
+static int dscow_write_metadata(struct cow_device *dev)
+{
+       struct dscow_prv *prv = dev->plugin_private;
+
+       if (dscow_sync(prv->dscow)) {
+               snprintf(errmsg, ERR_LEN, "Failed to sync: %s",
+                        strerror(dscow_errno));
+               return PLUGIN_FAIL;
+       } else {
+               return PLUGIN_OK;
+       }
+}
+
+static bool dscow_need_flush(struct cow_device *dev)
+{
+       struct dscow_prv *prv = dev->plugin_private;
+
+       return prv->dscow->dirty;
+}
+
+static int dscow_map(struct cow_device *dev, struct dmu_map_data *data)
+{
+       struct dscow_prv *prv = dev->plugin_private;
+       uint64_t block = dmu_map_get_block(data);
+
+       if (dscow_is_block_mapped(prv->dscow, block)) {
+               dmu_map_set_block(data, 
+                                 block + (prv->dscow->header.first_block /
+                                          prv->dscow->header.block_size));
+               dmu_map_set_dest_dev(data, prv->cow);
+               /* FIXME: Might as well mark as write here! */
+       } else if (dmu_map_is_write(data)) {
+               dmu_map_set_block(data,
+                                 block + (prv->dscow->header.first_block / 
+                                          prv->dscow->header.block_size));
+               dmu_map_set_copy_src_dev(data, prv->base);
+               dmu_map_set_dest_dev(data, prv->cow);
+       } else {
+               /* Don't change block */
+               dmu_map_set_dest_dev(data, prv->base);
+       }
+       
+       return PLUGIN_OK;
+}
+
+static int dscow_map_complete(struct cow_device *dev, uint64_t org_block)
+{
+       struct dscow_prv *prv = dev->plugin_private;
+
+       dscow_map_block(prv->dscow, org_block);
+
+       return PLUGIN_OK;
+}
+
+static void dscow_cleanup(struct cow_device *dev)
+{
+       struct dscow_prv *prv = dev->plugin_private;
+
+       if (!prv)
+               return;
+
+       dscow_close(prv->dscow);
+
+       loop_destroy(prv->base_dev);
+       loop_destroy(prv->cow_dev);
+       
+       free(prv);
+}
+
+int load_plugin(struct cowd_plugin *p)
+{
+       p->init_plugin = dscow_init;
+       p->write_metadata = dscow_write_metadata;
+       p->map_prepare = dscow_map;
+       p->map_complete = dscow_map_complete;
+       p->cleanup_plugin = dscow_cleanup;
+       p->need_flush = dscow_need_flush;
+       p->errmsg = errmsg;
+       p->get_devs = dscow_get_devs;
+
+       return 1;
+}
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/plugins/dscow/dscow_test.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/dscow_test.c     Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,33 @@
+/*
+ * 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 <stdint.h>
+
+#include "dscow_ops.h"
+
+int main(int argc, char **argv)
+{
+       struct dscow *h;
+       uint64_t i;
+
+       h = dscow_create("test.dscow", "test.base", 512);
+
+       for (i = 0; i < 1024; i+=2) {
+               dscow_map_block(h, i);
+       }
+       
+       for (i = 0; i < 1024; i++) {
+               if ((i%2) == dscow_is_block_mapped(h, i))
+                       printf("Error: %llu (%llu:%i)\n", 
+                              i, i%2, dscow_is_block_mapped(h, i));
+       }
+
+}
diff -r a19a066dea76 -r 6a7ea5a35543 tools/cowd/plugins/dscow/dscow_tool.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/dscow_tool.c     Mon Aug 21 15:03:09 2006 -0500
@@ -0,0 +1,190 @@
+/*
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+
+#include "dscow_ops.h"
+
+enum verbosity {NORMAL, LOUD, QUIET};
+
+usage(char *name)
+{
+       printf("Usage: %s [OPTIONS] [IMAGE] [BASE]\n"
+              "Create a dscow image\n"
+              "\n"
+              "Options:\n"
+              "  -c,--create        Create a new dscow image\n"
+              "  -i,--info          Display information about a dscow image\n"
+              "  -V,--version       Display version information\n"
+              "  -v,--verbose       Be verbose during image creation\n"
+              "  -b,--block-size=KB Set the block size in KB (default 64)\n"
+              "  -q,--quiet         Be quiet\n"
+              "\n"
+              "  IMAGE is the file to contain the changes\n"
+              "  BASE is the base read-only image\n",
+              name);
+}
+
+int do_create(char *image, char *base, unsigned long bs, int verbose)
+{
+       struct dscow *handle;
+
+       if (access(base, R_OK)) {
+               perror(base);
+               return 1;
+       }
+
+       handle = dscow_create(image, base, bs << 10);
+
+       if (handle) {
+               if (verbose == LOUD)
+                       dscow_print_info(handle);
+               else if (verbose == NORMAL)
+                       fprintf(stderr, "Created %s\n", image);
+       } else {
+               fprintf(stderr, "Failed: %s\n", strerror(dscow_errno));
+               return 1;
+       }
+
+       dscow_close(handle);
+
+       return 0;
+}
+
+int do_info(char *image, int verbose)
+{
+       struct dscow *handle;
+       char msg[256];
+
+       memset(msg, 0, 256);
+
+       if (access(image, R_OK)) {
+               perror(image);
+               return 1;
+       }
+
+       handle = dscow_open(image);
+
+       if (handle) {
+               if (verbose != QUIET)
+                       dscow_print_info(handle);
+       } else {
+               if (dscow_errno == EINVAL) {
+                       snprintf(msg, 256, "Not a dscow file");
+               } else if (dscow_errno == ENOTSUP) {
+                       snprintf(msg, 256, "File created with newer tools");
+               } else {
+                       strerror_r(dscow_errno, msg, 256);
+               }
+               if (verbose != QUIET)
+                       printf("Unable to read %s: %s\n", image, msg);
+               return 1;
+       }
+
+       dscow_close(handle);
+
+       return 0;
+}
+
+int do_version()
+{
+       printf("dscow_tool v0.1.0\n"
+              "\n"
+              "Copyright (C) International Business Machines Corp., 2006\n"
+              "Dan Smith <danms@xxxxxxxxxx>\n");
+
+       return 0;
+}
+
+int process_arguments(int argc, char **argv)
+{
+       int c;
+       enum {Create, Info, Version, Error} mode;
+       int verbose = NORMAL;
+       unsigned long block_size = 64;
+
+       while (1) { 
+               int this_optind = optind ? optind : 1;
+               int option_index = 0;
+               static struct option long_opts[] = {
+                       {"create",     0, 0, 'c'},
+                       {"info",       0, 0, 'i'},
+                       {"version",    0, 0, 'V'},
+                       {"verbose",    0, 0, 'v'},
+                       {"block-size", 1, 0, 'b'},
+                       {"quiet",      0, 0, 'q'},
+                       {0, 0, 0, 0}
+               };
+               
+               c = getopt_long(argc, argv, "ciVvb:q", 
+                               long_opts, &option_index);
+
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case 'c':
+                       mode = Create;
+                       break;
+
+               case 'V':
+                       mode = Version;
+                       break;
+
+               case 'i':
+                       mode = Info;
+                       break;
+
+               case 'v':
+                       verbose = LOUD;
+                       break;
+
+               case 'b':
+                       block_size = strtoul(optarg, NULL, 0);
+                       break;
+
+               case 'q':
+                       verbose = QUIET;
+                       break;
+               };
+       }
+
+       if (mode == Create) {
+               if ((argc - optind) != 2) {
+                       usage(argv[0]);
+                       return 1;
+               } else {
+                       return do_create(argv[optind], argv[optind+1], 
+                                        block_size, verbose);
+               }
+       } else if (mode == Info) {
+               if ((argc - optind) != 1) {
+                       usage(argv[0]);
+                       return 1;
+               } else {
+                       return do_info(argv[optind], verbose);
+               }
+       } else if (mode == Version) {
+               return do_version();
+       } else {
+               usage(argv[0]);
+               return 1;
+       }
+}
+
+int main(int argc, char **argv)
+{
+       return process_arguments(argc, argv);
+}

_______________________________________________
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®.