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

[lvm-devel] [PATCH] unknown segment types, part 1



Hi,

the attached patch makes LVM handle unknown segment types by a simple
copy-through mechanism, i.e. whenever an unknown segment is encountered, it is
left intact (and preserved) by LVM. We may still want to limit changes to LVs
that contain unknown segments, and maybe even some heuristic to find LV
references in unknown segments (hard to tell).

There's also one thread-unsafe bit in the patch, that's not so hard to fix, but
I'll do that when we know that this is the right direction we want to take.

(The patch itself will probably need another iteration. Consider this to be a
draft.)

Yours,
   Petr.

diff -rN -u -p old-upstream/lib/config/config.c new-upstream/lib/config/config.c
--- old-upstream/lib/config/config.c	2009-07-08 11:17:50.000000000 +0200
+++ new-upstream/lib/config/config.c	2009-07-08 11:17:50.000000000 +0200
@@ -71,6 +71,7 @@ struct cs {
 struct output_line {
 	FILE *fp;
 	struct dm_pool *mem;
+	putline_fn putline;
 };
 
 static void _get_token(struct parser *p, int tok_prev);
@@ -80,8 +81,8 @@ static struct config_node *_section(stru
 static struct config_value *_value(struct parser *p);
 static struct config_value *_type(struct parser *p);
 static int _match_aux(struct parser *p, int t);
-static struct config_value *_create_value(struct parser *p);
-static struct config_node *_create_node(struct parser *p);
+static struct config_value *_create_value(struct dm_pool *mem);
+static struct config_node *_create_node(struct dm_pool *mem);
 static char *_dup_tok(struct parser *p);
 
 static const int sep = '/';
@@ -392,10 +393,14 @@ static int _line_end(struct output_line 
 	}
 
 	line = dm_pool_end_object(outline->mem);
-	if (!outline->fp)
-		log_print("%s", line);
-	else
-		fprintf(outline->fp, "%s\n", line);
+	if (outline->putline)
+		outline->putline(line);
+	else {
+		if (!outline->fp)
+			log_print("%s", line);
+		else
+			fprintf(outline->fp, "%s\n", line);
+	}
 
 	return 1;
 }
@@ -487,6 +492,20 @@ static int _write_config(struct config_n
 	return 1;
 }
 
+int write_config_node(struct config_node *cn, putline_fn putline)
+{
+	struct output_line outline;
+	outline.fp = NULL;
+	outline.mem = dm_pool_create("config_line", 1024);
+	outline.putline = putline;
+	if (!_write_config(cn, 0, &outline, 0)) {
+		dm_pool_destroy(outline.mem);
+		return_0;
+	}
+	dm_pool_destroy(outline.mem);
+	return 1;
+}
+
 int write_config_file(struct config_tree *cft, const char *file,
 		      int argc, char **argv)
 {
@@ -494,6 +513,7 @@ int write_config_file(struct config_tree
 	int r = 1;
 	struct output_line outline;
 	outline.fp = NULL;
+	outline.putline = NULL;
 
 	if (!file)
 		file = "stdout";
@@ -555,7 +575,7 @@ static struct config_node *_section(stru
 {
 	/* IDENTIFIER SECTION_B_CHAR VALUE* SECTION_E_CHAR */
 	struct config_node *root, *n, *l = NULL;
-	if (!(root = _create_node(p)))
+	if (!(root = _create_node(p->mem)))
 		return_0;
 
 	if (!(root->key = _dup_tok(p)))
@@ -609,7 +629,7 @@ static struct config_value *_value(struc
 		 * Special case for an empty array.
 		 */
 		if (!h) {
-			if (!(h = _create_value(p)))
+			if (!(h = _create_value(p->mem)))
 				return NULL;
 
 			h->type = CFG_EMPTY_ARRAY;
@@ -624,7 +644,7 @@ static struct config_value *_value(struc
 static struct config_value *_type(struct parser *p)
 {
 	/* [+-]{0,1}[0-9]+ | [0-9]*\.[0-9]* | ".*" */
-	struct config_value *v = _create_value(p);
+	struct config_value *v = _create_value(p->mem);
 
 	if (!v)
 		return NULL;
@@ -820,9 +840,9 @@ static void _eat_space(struct parser *p)
 /*
  * memory management
  */
-static struct config_value *_create_value(struct parser *p)
+static struct config_value *_create_value(struct dm_pool *mem)
 {
-	struct config_value *v = dm_pool_alloc(p->mem, sizeof(*v));
+	struct config_value *v = dm_pool_alloc(mem, sizeof(*v));
 
 	if (v)
 		memset(v, 0, sizeof(*v));
@@ -830,9 +850,9 @@ static struct config_value *_create_valu
 	return v;
 }
 
-static struct config_node *_create_node(struct parser *p)
+static struct config_node *_create_node(struct dm_pool *mem)
 {
-	struct config_node *n = dm_pool_alloc(p->mem, sizeof(*n));
+	struct config_node *n = dm_pool_alloc(mem, sizeof(*n));
 
 	if (n)
 		memset(n, 0, sizeof(*n));
@@ -1280,3 +1300,29 @@ unsigned maybe_config_section(const char
 	else
 		return 0;
 }
+
+static struct config_value *_clone_config_value(struct dm_pool *mem, const struct config_value *v)
+{
+	if (!v)
+		return NULL;
+	struct config_value *new = _create_value(mem);
+	new->type = v->type;
+	if (v->type == CFG_STRING)
+		new->v.str = dm_pool_strdup(mem, v->v.str);
+	else
+		new->v = v->v;
+	new->next = _clone_config_value(mem, v->next);
+	return new;
+}
+
+struct config_node *clone_config_node(struct dm_pool *mem, const struct config_node *cn)
+{
+	if (!cn)
+		return NULL;
+	struct config_node *new = _create_node(mem);
+	new->key = dm_pool_strdup(mem, cn->key);
+	new->child = clone_config_node(mem, cn->child);
+	new->v = _clone_config_value(mem, cn->v);
+	new->sib = clone_config_node(mem, cn->sib);
+	return new;
+}
diff -rN -u -p old-upstream/lib/config/config.h new-upstream/lib/config/config.h
--- old-upstream/lib/config/config.h	2009-07-08 11:17:50.000000000 +0200
+++ new-upstream/lib/config/config.h	2009-07-08 11:17:50.000000000 +0200
@@ -67,6 +67,10 @@ int read_config_fd(struct config_tree *c
 int read_config_file(struct config_tree *cft);
 int write_config_file(struct config_tree *cft, const char *file,
 		      int argc, char **argv);
+
+typedef int (*putline_fn)(const char *line);
+int write_config_node(struct config_node *cn, putline_fn putline);
+
 time_t config_file_timestamp(struct config_tree *cft);
 int config_file_changed(struct config_tree *cft);
 int merge_config_tree(struct cmd_context *cmd, struct config_tree *cft,
@@ -110,4 +114,5 @@ int get_config_str(const struct config_n
 
 unsigned maybe_config_section(const char *str, unsigned len);
 
+struct config_node *clone_config_node(struct dm_pool *mem, const struct config_node *cn);
 #endif
diff -rN -u -p old-upstream/lib/format_text/export.c new-upstream/lib/format_text/export.c
--- old-upstream/lib/format_text/export.c	2009-07-08 11:17:50.000000000 +0200
+++ new-upstream/lib/format_text/export.c	2009-07-08 11:17:50.000000000 +0200
@@ -293,6 +293,28 @@ int out_text(struct formatter *f, const 
 	return r;
 }
 
+static int _out_config_nodes(struct formatter *f, const struct config_node *cn)
+{
+	while (cn) {
+		if (!out_config_node(f, cn))
+			return 0;
+		cn = cn->sib;
+	}
+	return 1;
+}
+
+static struct formatter *_formatter; /* FIXME This is not threadsafe! */
+
+static int _out_line(const char *line) {
+	return out_text(_formatter, "%s", line);
+}
+
+int out_config_node(struct formatter *f, const struct config_node *cn)
+{
+	_formatter = f;
+	return write_config_node(cn, _out_line);
+}
+
 static int _print_header(struct formatter *f,
 			 const char *desc)
 {
diff -rN -u -p old-upstream/lib/format_text/text_export.h new-upstream/lib/format_text/text_export.h
--- old-upstream/lib/format_text/text_export.h	2009-07-08 11:17:50.000000000 +0200
+++ new-upstream/lib/format_text/text_export.h	2009-07-08 11:17:50.000000000 +0200
@@ -21,6 +21,7 @@
 
 struct formatter;
 struct lv_segment;
+struct config_node;
 
 int out_size(struct formatter *f, uint64_t size, const char *fmt, ...)
     __attribute__ ((format(printf, 3, 4)));
@@ -31,6 +32,8 @@ int out_hint(struct formatter *f, const 
 int out_text(struct formatter *f, const char *fmt, ...)
     __attribute__ ((format(printf, 2, 3)));
 
+int out_config_node(struct formatter *f, const struct config_node *cn);
+
 int out_areas(struct formatter *f, const struct lv_segment *seg,
 	      const char *type);
 
diff -rN -u -p old-upstream/lib/Makefile.in new-upstream/lib/Makefile.in
--- old-upstream/lib/Makefile.in	2009-07-08 11:17:50.000000000 +0200
+++ new-upstream/lib/Makefile.in	2009-07-08 11:17:50.000000000 +0200
@@ -46,6 +46,7 @@ SOURCES =\
 	device/device.c \
 	display/display.c \
 	error/errseg.c \
+	unknown/unknown.c \
 	filters/filter-composite.c \
 	filters/filter-persistent.c \
 	filters/filter-regex.c \
diff -rN -u -p old-upstream/lib/metadata/metadata-exported.h new-upstream/lib/metadata/metadata-exported.h
--- old-upstream/lib/metadata/metadata-exported.h	2009-07-08 11:17:50.000000000 +0200
+++ new-upstream/lib/metadata/metadata-exported.h	2009-07-08 11:17:50.000000000 +0200
@@ -303,6 +303,7 @@ struct lv_segment {
 	uint32_t region_size;	/* For mirrors - in sectors */
 	uint32_t extents_copied;
 	struct logical_volume *log_lv;
+	void *segtype_private;
 
 	struct dm_list tags;
 
diff -rN -u -p old-upstream/lib/metadata/segtype.c new-upstream/lib/metadata/segtype.c
--- old-upstream/lib/metadata/segtype.c	2009-07-08 11:17:50.000000000 +0200
+++ new-upstream/lib/metadata/segtype.c	2009-07-08 11:17:50.000000000 +0200
@@ -27,6 +27,11 @@ struct segment_type *get_segtype_from_st
 			return segtype;
 	}
 
-	log_error("Unrecognised segment type %s", str);
-	return NULL;
+	if (!(segtype = init_unknown_segtype(cmd, str)))
+		return_NULL;
+
+	segtype->library = NULL;
+	dm_list_add(&cmd->segtypes, &segtype->list);
+	log_warn("WARNING: Unknown segment type %s", str);
+	return segtype;
 }
diff -rN -u -p old-upstream/lib/metadata/segtype.h new-upstream/lib/metadata/segtype.h
--- old-upstream/lib/metadata/segtype.h	2009-07-08 11:17:50.000000000 +0200
+++ new-upstream/lib/metadata/segtype.h	2009-07-08 11:17:50.000000000 +0200
@@ -93,6 +93,7 @@ struct segtype_handler {
 struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
 					     const char *str);
 
+struct segment_type *init_unknown_segtype(struct cmd_context *cmd, const char *name);
 struct segment_type *init_striped_segtype(struct cmd_context *cmd);
 struct segment_type *init_zero_segtype(struct cmd_context *cmd);
 struct segment_type *init_error_segtype(struct cmd_context *cmd);
diff -rN -u -p old-upstream/lib/unknown/unknown.c new-upstream/lib/unknown/unknown.c
--- old-upstream/lib/unknown/unknown.c	1970-01-01 01:00:00.000000000 +0100
+++ new-upstream/lib/unknown/unknown.c	2009-07-08 11:17:50.000000000 +0200
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "lib.h"
+#include "toolcontext.h"
+#include "segtype.h"
+#include "display.h"
+#include "text_export.h"
+#include "text_import.h"
+#include "config.h"
+#include "str_list.h"
+#include "targets.h"
+#include "lvm-string.h"
+#include "activate.h"
+#include "str_list.h"
+#include "metadata.h"
+
+static const char *_unknown_name(const struct lv_segment *seg)
+{
+
+	return seg->segtype->name;
+}
+
+static int _unknown_text_import(struct lv_segment *seg, const struct config_node *sn,
+			struct dm_hash_table *pv_hash)
+{
+	seg->segtype_private = clone_config_node(seg->lv->vg->vgmem, sn);
+	return 1;
+}
+
+static int _unknown_text_export(const struct lv_segment *seg, struct formatter *f)
+{
+	struct config_node *cn = seg->segtype_private, *next;
+	for (; cn != NULL; cn = cn->sib) {
+		if (!strcmp(cn->key, "type") || !strcmp(cn->key, "start_extent") ||
+		    !strcmp(cn->key, "tags") || !strcmp(cn->key, "extent_count"))
+			continue;
+		next = cn->sib;
+		cn->sib = NULL;
+		log_very_verbose("writing node %s of unknown segment type %s",
+				 cn->key, seg->segtype->name);
+		out_config_node(f, cn);
+		cn->sib = next;
+	}
+	return 1;
+}
+
+#ifdef DEVMAPPER_SUPPORT
+static int _unknown_add_target_line(struct dev_manager *dm __attribute((unused)),
+				struct dm_pool *mem __attribute((unused)),
+				struct cmd_context *cmd __attribute((unused)),
+				void **target_state __attribute((unused)),
+				struct lv_segment *seg __attribute((unused)),
+				struct dm_tree_node *node, uint64_t len,
+				uint32_t *pvmove_mirror_count __attribute((unused)))
+{
+	return dm_tree_node_add_error_target(node, len);
+}
+#endif
+
+static void _unknown_destroy(const struct segment_type *segtype)
+{
+	dm_free((void *)segtype);
+}
+
+static struct segtype_handler _unknown_ops = {
+	.name = _unknown_name,
+	.text_import = _unknown_text_import,
+	.text_export = _unknown_text_export,
+#ifdef DEVMAPPER_SUPPORT
+	.add_target_line = _unknown_add_target_line,
+#endif
+	.destroy = _unknown_destroy,
+};
+
+struct segment_type *init_unknown_segtype(struct cmd_context *cmd, const char *name)
+{
+	struct segment_type *segtype = dm_malloc(sizeof(*segtype));
+
+	if (!segtype)
+		return_NULL;
+
+	segtype->cmd = cmd;
+	segtype->ops = &_unknown_ops;
+	segtype->name = name;
+	segtype->private = NULL;
+	segtype->flags = SEG_VIRTUAL | SEG_CANNOT_BE_ZEROED;
+
+	log_very_verbose("Initialised segtype: %s", segtype->name);
+
+	return segtype;
+}

--- old-upstream/test/t-unknown-segment.sh	1970-01-01 01:00:00.000000000 +0100
+++ new-upstream/test/t-unknown-segment.sh	2009-07-08 11:17:50.000000000 +0200
@@ -0,0 +1,31 @@
+#!/bin/sh
+# Copyright (C) 2009 Red Hat, Inc. All rights reserved.
+#
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU General Public License v.2.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+. ./test-utils.sh
+
+aux prepare_vg 4
+
+lvcreate -l 1 -n $lv1 $vg
+lvcreate -l 2 -m 1 -n $lv2 $vg
+
+vgcfgbackup -f bak0
+sed -e 's,striped,unstriped,;s,mirror,unmirror,' -i.orig bak0
+vgcfgrestore -f bak0 $vg
+
+vgcfgbackup -f bak1
+cat bak1
+sed -e 's,unstriped,striped,;s,unmirror,mirror,' -i.orig bak1
+vgcfgrestore -f bak1 $vg
+vgcfgbackup -f bak2
+
+egrep -v 'description|seqno' < bak0.orig > a
+egrep -v 'description|seqno' < bak2 > b
+diff -u a b



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