All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ryan Grimm <grimm@us.ibm.com>
To: Xen Devel <xen-devel@lists.xensource.com>
Cc: Dan Smith <danms@us.ibm.com>
Subject: [PATCH 4 of 6] dscow plugin for dm-userspace userspace tool
Date: Fri, 25 Aug 2006 16:24:04 -0500	[thread overview]
Message-ID: <20060825212404.GE31071@localhost.localdomain> (raw)
In-Reply-To: <patchbomb.1156540578@venkman-64>

Signed-off-by: Ryan Grimm <grimm@us.ibm.com>
Signed-off-by: Dan Smith <danms@us.ibm.com>

# HG changeset patch
# User Ryan Grimm <grimm@us.ibm.com>
# 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@us.ibm.com>
+ * Author: Ryan Grimm <grimm@us.ibm.com>
  *
  * 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@us.ibm.com>
+ *
+ * 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@us.ibm.com>
+ *
+ * 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@us.ibm.com>
+ * Author: Ryan Grimm <grimm@us.ibm.com>
+ *
+ * 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@us.ibm.com>
+ *
+ * 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@us.ibm.com>\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);
+}

  parent reply	other threads:[~2006-08-25 21:24 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <patchbomb.1156540578@venkman-64>
2006-08-25 21:23 ` [PATCH 1 of 6] dm-userspace xen kernel patch Ryan Grimm
2006-08-25 21:23 ` [PATCH 2 of 6] dm-userspace userspace tool base patch Ryan Grimm
2006-08-25 21:24 ` [PATCH 3 of 6] dm-userspace internal libdmu support for userspace tool Ryan Grimm
2006-08-25 21:24 ` Ryan Grimm [this message]
2006-08-25 21:24 ` [PATCH 5 of 6] qcow plugin for dm-userspace " Ryan Grimm
2006-08-25 21:24 ` [PATCH 6 of 6] dm-userspace backend script and xmexample change Ryan Grimm
     [not found] <patchbomb.1156192193@venkman-64>
2006-08-21 20:55 ` [PATCH 4 of 6] dscow plugin for dm-userspace userspace tool Ryan Grimm

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060825212404.GE31071@localhost.localdomain \
    --to=grimm@us.ibm.com \
    --cc=danms@us.ibm.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.