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
|