]> sourceware.org Git - lvm2.git/commitdiff
Permit several segment types to be registered by a single shared object.
authorAlasdair Kergon <agk@redhat.com>
Wed, 8 Jul 2009 12:36:01 +0000 (12:36 +0000)
committerAlasdair Kergon <agk@redhat.com>
Wed, 8 Jul 2009 12:36:01 +0000 (12:36 +0000)
WHATS_NEW
lib/commands/toolcontext.c
lib/metadata/segtype.h

index 74daffc1321011609b14294ac718ac132f7ce1fc..9449f3c3cbe7070b48780e666ffb6537d658ed03 100644 (file)
--- a/WHATS_NEW
+++ b/WHATS_NEW
@@ -1,5 +1,6 @@
 Version 2.02.49 - 
 ================================
+  Permit several segment types to be registered by a single shared object.
   Update the man pages to document size units uniformly.
   Allow commandline sizes to be specified in terms of bytes and sectors.
   Update 'md_chunk_alignment' to use stripe-width to align PV data area.
index 4f6cf98841ca39317340ec21008e0c7627ed7b68..2ffea19af6a0878ea92b8816abcf7da3bd4d51b8 100644 (file)
@@ -806,12 +806,59 @@ int init_lvmcache_orphans(struct cmd_context *cmd)
        return 1;
 }
 
+struct segtype_library {
+       struct cmd_context *cmd;
+       void *lib;
+       const char *libname;
+};
+
+int lvm_register_segtype(struct segtype_library *seglib,
+                        struct segment_type *segtype)
+{
+       struct segment_type *segtype2;
+
+       segtype->library = seglib->lib;
+       segtype->cmd = seglib->cmd;
+
+       dm_list_iterate_items(segtype2, &seglib->cmd->segtypes) {
+               if (strcmp(segtype2->name, segtype->name))
+                       continue;
+               log_error("Duplicate segment type %s: "
+                         "unloading shared library %s",
+                         segtype->name, seglib->libname);
+               segtype->ops->destroy(segtype);
+               return 0;
+       }
+
+       dm_list_add(&seglib->cmd->segtypes, &segtype->list);
+
+       return 1;
+}
+
+static int _init_single_segtype(struct segtype_library *seglib)
+{
+       struct segment_type *(*init_segtype_fn) (struct cmd_context *);
+       struct segment_type *segtype;
+
+       if (!(init_segtype_fn = dlsym(seglib->lib, "init_segtype"))) {
+               log_error("Shared library %s does not contain segment type "
+                         "functions", seglib->libname);
+               return 0;
+       }
+
+       if (!(segtype = init_segtype_fn(seglib->cmd)))
+               return_0;
+
+       return lvm_register_segtype(seglib, segtype);
+}
+
 static int _init_segtypes(struct cmd_context *cmd)
 {
        struct segment_type *segtype;
 
 #ifdef HAVE_LIBDL
        const struct config_node *cn;
+       struct segtype_library seglib;
 #endif
 
        if (!(segtype = init_striped_segtype(cmd)))
@@ -854,9 +901,9 @@ static int _init_segtypes(struct cmd_context *cmd)
            (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_multiple_segtypes_fn) (struct segtype_library *);
+
+               seglib.cmd = cmd;
 
                for (cv = cn->v; cv; cv = cv->next) {
                        if (cv->type != CFG_STRING) {
@@ -864,32 +911,37 @@ static int _init_segtypes(struct cmd_context *cmd)
                                          "global/segment_libraries");
                                return 0;
                        }
-                       if (!(lib = load_shared_library(cmd, cv->v.str,
+                       seglib.libname = cv->v.str;
+                       if (!(seglib.lib = load_shared_library(cmd,
+                                                       seglib.libname,
                                                        "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 (!(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);
+                       if ((init_multiple_segtypes_fn =
+                           dlsym(seglib.lib, "init_multiple_segtypes"))) {
+                               if (dlsym(seglib.lib, "init_segtype"))
+                                       log_warn("WARNING: Shared lib %s has "
+                                                "conflicting init fns.  Using"
+                                                " init_multiple_segtypes().",
+                                                seglib.libname);
+                       } else
+                               init_multiple_segtypes_fn =
+                                   _init_single_segtype;
+                       if (!init_multiple_segtypes_fn(&seglib)) {
+                               struct dm_list *sgtl, *tmp;
+                               log_error("init_multiple_segtypes() failed: "
+                                         "Unloading shared library %s",
+                                         seglib.libname);
+                               dm_list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
+                                       segtype = dm_list_item(sgtl, struct segment_type);
+                                       if (segtype->library == seglib.lib) {
+                                               dm_list_del(&segtype->list);
+                                               segtype->ops->destroy(segtype);
+                                       }
+                               }
+                               dlclose(seglib.lib);
+                               return_0;
                        }
                }
        }
@@ -1154,8 +1206,18 @@ static void _destroy_segtypes(struct dm_list *segtypes)
                lib = segtype->library;
                segtype->ops->destroy(segtype);
 #ifdef HAVE_LIBDL
-               if (lib)
+               /*
+                * If no segtypes remain from this library, close it.
+                */
+               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 80f2215f858f6873c09a27672adada1e675bdfbd..a48a8bb17a3bd90922ee8b77395914716a1b7e5c 100644 (file)
@@ -47,13 +47,13 @@ struct dev_manager;
 #define segtype_is_virtual(segtype)    ((segtype)->flags & SEG_VIRTUAL ? 1 : 0)
 
 struct segment_type {
-       struct dm_list list;
-       struct cmd_context *cmd;
+       struct dm_list list;            /* Internal */
+       struct cmd_context *cmd;        /* lvm_register_segtype() sets this. */
        uint32_t flags;
        struct segtype_handler *ops;
        const char *name;
-       void *library;
-       void *private;
+       void *library;                  /* lvm_register_segtype() sets this. */
+       void *private;                  /* For the segtype handler to use. */
 };
 
 struct segtype_handler {
@@ -93,6 +93,10 @@ struct segtype_handler {
 struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
                                             const char *str);
 
+struct segtype_library;
+int lvm_register_segtype(struct segtype_library *seglib,
+                        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);
This page took 0.054108 seconds and 5 git commands to generate.