diff options
author | Jonathan Brassow <jbrassow@redhat.com> | 2008-02-08 03:11:19 +0100 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2008-02-08 03:11:19 +0100 |
commit | fb8b284806124bef250196007d7373ea3fe26194 (patch) | |
tree | 8e34cc38a2c5a0e8e7a937c53421cf7f76466a00 /drivers/md/dm-log.c | |
parent | dm: move deferred bio flushing to workqueue (diff) | |
download | linux-fb8b284806124bef250196007d7373ea3fe26194.tar.xz linux-fb8b284806124bef250196007d7373ea3fe26194.zip |
dm log: auto load modules
If the log type is not recognised, attempt to load the module
'dm-log-<type>.ko'.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to '')
-rw-r--r-- | drivers/md/dm-log.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 072ee4353eab..2a74b2142f50 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c @@ -41,7 +41,7 @@ int dm_unregister_dirty_log_type(struct dirty_log_type *type) return 0; } -static struct dirty_log_type *get_type(const char *type_name) +static struct dirty_log_type *_get_type(const char *type_name) { struct dirty_log_type *type; @@ -61,6 +61,55 @@ static struct dirty_log_type *get_type(const char *type_name) return NULL; } +/* + * get_type + * @type_name + * + * Attempt to retrieve the dirty_log_type by name. If not already + * available, attempt to load the appropriate module. + * + * Log modules are named "dm-log-" followed by the 'type_name'. + * Modules may contain multiple types. + * This function will first try the module "dm-log-<type_name>", + * then truncate 'type_name' on the last '-' and try again. + * + * For example, if type_name was "clustered-disk", it would search + * 'dm-log-clustered-disk' then 'dm-log-clustered'. + * + * Returns: dirty_log_type* on success, NULL on failure + */ +static struct dirty_log_type *get_type(const char *type_name) +{ + char *p, *type_name_dup; + struct dirty_log_type *type; + + type = _get_type(type_name); + if (type) + return type; + + type_name_dup = kstrdup(type_name, GFP_KERNEL); + if (!type_name_dup) { + DMWARN("No memory left to attempt log module load for \"%s\"", + type_name); + return NULL; + } + + while (request_module("dm-log-%s", type_name_dup) || + !(type = _get_type(type_name))) { + p = strrchr(type_name_dup, '-'); + if (!p) + break; + p[0] = '\0'; + } + + if (!type) + DMWARN("Module for logging type \"%s\" not found.", type_name); + + kfree(type_name_dup); + + return type; +} + static void put_type(struct dirty_log_type *type) { spin_lock(&_lock); |