[lvm-devel] [PATCH] more segtypes in one library
Mikulas Patocka
mpatocka at redhat.com
Thu Jun 25 14:04:14 UTC 2009
Hi
This is the patch for more segtypes in one shared library. You define
function init_segtypes (instead of init_segtype) and this function can
register arbitraty number of segtypes with lvm_add_segtype. It returns
nonzero on success or zero on failure (in this case, the registered
segtypes are destroyed and the library is unloaded).
The old function init_segtype to init one segtype is still available, so
it doesn't break binary compatibility.
Mikulas
---
lib/commands/toolcontext.c | 97 ++++++++++++++++++++++++++++++++-------------
lib/metadata/segtype.h | 2
2 files changed, 72 insertions(+), 27 deletions(-)
Index: LVM2.2.02.47/lib/commands/toolcontext.c
===================================================================
--- LVM2.2.02.47.orig/lib/commands/toolcontext.c 2009-06-23 12:32:08.000000000 +0200
+++ LVM2.2.02.47/lib/commands/toolcontext.c 2009-06-25 16:02:14.000000000 +0200
@@ -809,6 +809,47 @@ int init_lvmcache_orphans(struct cmd_con
return 1;
}
+static void *current_library = NULL;
+
+int lvm_add_segtype(struct cmd_context *cmd, struct segment_type *segtype)
+{
+ struct segment_type *segtype2;
+
+ segtype->library = current_library;
+ dm_list_iterate_items(segtype2, &cmd->segtypes) {
+ if (strcmp(segtype2->name, segtype->name))
+ continue;
+ log_error("Duplicate segment type %s: unloading shared library",
+ segtype->name);
+ segtype->ops->destroy(segtype);
+ return 0;
+ }
+
+ dm_list_add(&cmd->segtypes, &segtype->list);
+
+ return 1;
+}
+
+static int init_segtypes_legacy(struct cmd_context *cmd)
+{
+ struct segment_type *(*init_segtype_fn) (struct cmd_context *);
+ struct segment_type *segtype;
+
+ init_segtype_fn = dlsym(current_library, "init_segtype");
+ if (!init_segtype_fn) {
+ log_error("Shared library does not contain segment type "
+ "functions");
+ return 0;
+ }
+
+ segtype = init_segtype_fn(cmd);
+
+ if (!segtype)
+ return 0;
+
+ return lvm_add_segtype(cmd, segtype);
+}
+
static int _init_segtypes(struct cmd_context *cmd)
{
struct segment_type *segtype;
@@ -857,9 +898,7 @@ static int _init_segtypes(struct cmd_con
(cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
struct config_value *cv;
- struct segment_type *(*init_segtype_fn) (struct cmd_context *);
- void *lib;
- struct segment_type *segtype2;
+ int (*init_segtypes_fn) (struct cmd_context *);
for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) {
@@ -867,33 +906,31 @@ static int _init_segtypes(struct cmd_con
"global/segment_libraries");
return 0;
}
- if (!(lib = load_shared_library(cmd, cv->v.str,
- "segment type", 0)))
+ if (!(current_library = load_shared_library(cmd,
+ cv->v.str, "segment type", 0)))
return_0;
- if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) {
- log_error("Shared library %s does not contain "
- "segment type functions", cv->v.str);
- dlclose(lib);
- return 0;
+ if (!(init_segtypes_fn = dlsym(current_library,
+ "init_segtypes")))
+ init_segtypes_fn = init_segtypes_legacy;
+
+ if (!init_segtypes_fn(cmd)) {
+ struct dm_list *sgtl, *tmp;
+ log_error("Unloading shared library %s",
+ cv->v.str);
+ dm_list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
+ segtype = dm_list_item(sgtl, struct segment_type);
+ if (segtype->library == current_library) {
+ dm_list_del(&segtype->list);
+ segtype->ops->destroy(segtype);
+ }
+ }
+ dlclose(current_library);
+ current_library = NULL;
+ return_0;
}
- if (!(segtype = init_segtype_fn(cmd)))
- return 0;
- segtype->library = lib;
- dm_list_add(&cmd->segtypes, &segtype->list);
-
- dm_list_iterate_items(segtype2, &cmd->segtypes) {
- if ((segtype == segtype2) ||
- strcmp(segtype2->name, segtype->name))
- continue;
- log_error("Duplicate segment type %s: "
- "unloading shared library %s",
- segtype->name, cv->v.str);
- dm_list_del(&segtype->list);
- segtype->ops->destroy(segtype);
- dlclose(lib);
- }
+ current_library = NULL;
}
}
#endif
@@ -1170,8 +1207,14 @@ static void _destroy_segtypes(struct dm_
lib = segtype->library;
segtype->ops->destroy(segtype);
#ifdef HAVE_LIBDL
- if (lib)
+ if (lib) {
+ struct segment_type *segtype2;
+ dm_list_iterate_items(segtype2, segtypes)
+ if (segtype2->library == lib)
+ goto skip_dlclose;
dlclose(lib);
+skip_dlclose:;
+ }
#endif
}
}
Index: LVM2.2.02.47/lib/metadata/segtype.h
===================================================================
--- LVM2.2.02.47.orig/lib/metadata/segtype.h 2009-06-23 12:32:08.000000000 +0200
+++ LVM2.2.02.47/lib/metadata/segtype.h 2009-06-25 16:01:45.000000000 +0200
@@ -99,6 +99,8 @@ struct segtype_handler {
struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
const char *str);
+int lvm_add_segtype(struct cmd_context *cmd, struct segment_type *segtype);
+
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);
More information about the lvm-devel
mailing list