1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

Permit several segment types to be registered by a single shared object.

This commit is contained in:
Alasdair Kergon 2009-07-08 12:36:01 +00:00
parent 3d425215a8
commit dd1d42d5d0
3 changed files with 98 additions and 31 deletions

View File

@ -1,5 +1,6 @@
Version 2.02.49 - 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. Update the man pages to document size units uniformly.
Allow commandline sizes to be specified in terms of bytes and sectors. 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. Update 'md_chunk_alignment' to use stripe-width to align PV data area.

View File

@ -806,12 +806,59 @@ int init_lvmcache_orphans(struct cmd_context *cmd)
return 1; 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) static int _init_segtypes(struct cmd_context *cmd)
{ {
struct segment_type *segtype; struct segment_type *segtype;
#ifdef HAVE_LIBDL #ifdef HAVE_LIBDL
const struct config_node *cn; const struct config_node *cn;
struct segtype_library seglib;
#endif #endif
if (!(segtype = init_striped_segtype(cmd))) 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"))) { (cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
struct config_value *cv; struct config_value *cv;
struct segment_type *(*init_segtype_fn) (struct cmd_context *); int (*init_multiple_segtypes_fn) (struct segtype_library *);
void *lib;
struct segment_type *segtype2; seglib.cmd = cmd;
for (cv = cn->v; cv; cv = cv->next) { for (cv = cn->v; cv; cv = cv->next) {
if (cv->type != CFG_STRING) { if (cv->type != CFG_STRING) {
@ -864,32 +911,37 @@ static int _init_segtypes(struct cmd_context *cmd)
"global/segment_libraries"); "global/segment_libraries");
return 0; 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))) "segment type", 0)))
return_0; return_0;
if (!(init_segtype_fn = dlsym(lib, "init_segtype"))) { if ((init_multiple_segtypes_fn =
log_error("Shared library %s does not contain " dlsym(seglib.lib, "init_multiple_segtypes"))) {
"segment type functions", cv->v.str); if (dlsym(seglib.lib, "init_segtype"))
dlclose(lib); log_warn("WARNING: Shared lib %s has "
return 0; "conflicting init fns. Using"
} " init_multiple_segtypes().",
seglib.libname);
} else
init_multiple_segtypes_fn =
_init_single_segtype;
if (!(segtype = init_segtype_fn(cmd))) if (!init_multiple_segtypes_fn(&seglib)) {
return 0; struct dm_list *sgtl, *tmp;
segtype->library = lib; log_error("init_multiple_segtypes() failed: "
dm_list_add(&cmd->segtypes, &segtype->list); "Unloading shared library %s",
seglib.libname);
dm_list_iterate_items(segtype2, &cmd->segtypes) { dm_list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
if ((segtype == segtype2) || segtype = dm_list_item(sgtl, struct segment_type);
strcmp(segtype2->name, segtype->name)) if (segtype->library == seglib.lib) {
continue;
log_error("Duplicate segment type %s: "
"unloading shared library %s",
segtype->name, cv->v.str);
dm_list_del(&segtype->list); dm_list_del(&segtype->list);
segtype->ops->destroy(segtype); segtype->ops->destroy(segtype);
dlclose(lib); }
}
dlclose(seglib.lib);
return_0;
} }
} }
} }
@ -1154,8 +1206,18 @@ static void _destroy_segtypes(struct dm_list *segtypes)
lib = segtype->library; lib = segtype->library;
segtype->ops->destroy(segtype); segtype->ops->destroy(segtype);
#ifdef HAVE_LIBDL #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); dlclose(lib);
skip_dlclose:
;
}
#endif #endif
} }
} }

View File

@ -47,13 +47,13 @@ struct dev_manager;
#define segtype_is_virtual(segtype) ((segtype)->flags & SEG_VIRTUAL ? 1 : 0) #define segtype_is_virtual(segtype) ((segtype)->flags & SEG_VIRTUAL ? 1 : 0)
struct segment_type { struct segment_type {
struct dm_list list; struct dm_list list; /* Internal */
struct cmd_context *cmd; struct cmd_context *cmd; /* lvm_register_segtype() sets this. */
uint32_t flags; uint32_t flags;
struct segtype_handler *ops; struct segtype_handler *ops;
const char *name; const char *name;
void *library; void *library; /* lvm_register_segtype() sets this. */
void *private; void *private; /* For the segtype handler to use. */
}; };
struct segtype_handler { struct segtype_handler {
@ -93,6 +93,10 @@ struct segtype_handler {
struct segment_type *get_segtype_from_string(struct cmd_context *cmd, struct segment_type *get_segtype_from_string(struct cmd_context *cmd,
const char *str); 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_striped_segtype(struct cmd_context *cmd);
struct segment_type *init_zero_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); struct segment_type *init_error_segtype(struct cmd_context *cmd);