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 4 of 6] dscow plugin for dm-userspace userspace tool

To: Xen Devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH 4 of 6] dscow plugin for dm-userspace userspace tool
From: Ryan Grimm <grimm@xxxxxxxxxx>
Date: Fri, 25 Aug 2006 16:24:04 -0500
Cc: Dan Smith <danms@xxxxxxxxxx>
Delivery-date: Fri, 25 Aug 2006 14:27:57 -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 1156536095 18000
# Node ID a3656acd770b4f21ad54fa961032ff39562058eb
# Parent  8c8d5dc4eaf4f0044f7fdd5adb282359eff7263a
dscow plugin for dm-userspace userspace tool

diff -r 8c8d5dc4eaf4 -r a3656acd770b tools/cowd/Makefile.am
--- a/tools/cowd/Makefile.am    Fri Aug 25 15:01:34 2006 -0500
+++ b/tools/cowd/Makefile.am    Fri Aug 25 15:01:35 2006 -0500
@@ -1,3 +1,5 @@ EXTRA_DIST = libdmu/dmu.c libdmu/dmu.h l
+SUBDIRS = plugins
+
 EXTRA_DIST = libdmu/dmu.c libdmu/dmu.h libdmu/internal_renames
 
 bin_PROGRAMS = cowd
diff -r 8c8d5dc4eaf4 -r a3656acd770b tools/cowd/configure.in
--- a/tools/cowd/configure.in   Fri Aug 25 15:01:34 2006 -0500
+++ b/tools/cowd/configure.in   Fri Aug 25 15:01:35 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 8c8d5dc4eaf4 -r a3656acd770b tools/cowd/cowd_control_loop.c
--- a/tools/cowd/cowd_control_loop.c    Fri Aug 25 15:01:34 2006 -0500
+++ b/tools/cowd/cowd_control_loop.c    Fri Aug 25 15:01:35 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 8c8d5dc4eaf4 -r a3656acd770b tools/cowd/plugins/Makefile.am
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/Makefile.am    Fri Aug 25 15:01:35 2006 -0500
@@ -0,0 +1,1 @@
+SUBDIRS = dscow
diff -r 8c8d5dc4eaf4 -r a3656acd770b tools/cowd/plugins/dscow/Makefile.am
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/Makefile.am      Fri Aug 25 15:01:35 2006 -0500
@@ -0,0 +1,10 @@
+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@
diff -r 8c8d5dc4eaf4 -r a3656acd770b tools/cowd/plugins/dscow/README
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/cowd/plugins/dscow/README   Fri Aug 25 15:01:35 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 8c8d5dc4eaf4 -r a3656acd770b 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      Fri Aug 25 15:01:35 2006 -0500
@@ -0,0 +1,428 @@
+/*
+ * 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++) {
+               if (dscow->dirty_bitmaps[i]) {
+                       lseek64(dscow->fd, i * sizeof(uint32_t), SEEK_CUR);
+                                               
+                       ret = write(dscow->fd,
+                                   &dscow->bitmap[i],
+                                   sizeof(dscow->bitmap[i]));
+                       if (ret < 0) {
+                               dscow_errno = errno;
+                               break;
+                       }
+                       dscow->dirty_bitmaps[i] = 0;
+               }
+
+               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 | O_LARGEFILE);
+       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_bitmaps = calloc(handle->bitmap_count, 
+                                       sizeof(uint32_t));
+       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 | O_LARGEFILE, 
+                         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));
+       handle->dirty_bitmaps = 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->dirty_bitmaps[field] = 1;
+       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 8c8d5dc4eaf4 -r a3656acd770b 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      Fri Aug 25 15:01:35 2006 -0500
@@ -0,0 +1,51 @@
+/*
+ * 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;
+        uint32_t *dirty_bitmaps;
+        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 8c8d5dc4eaf4 -r a3656acd770b 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   Fri Aug 25 15:01:35 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 8c8d5dc4eaf4 -r a3656acd770b 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     Fri Aug 25 15:01:35 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

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