diff options
| author | Jonathan Brassow <jbrassow@redhat.com> | 2008-04-24 16:43:41 -0400 |
|---|---|---|
| committer | Alasdair G Kergon <agk@redhat.com> | 2008-04-25 08:26:48 -0400 |
| commit | 2a23aa1ddb1f0c9eef2c929c89565c387f6bf68b (patch) | |
| tree | dc029b4230dc1282363a16d8a9d9126f1c9d7ffe | |
| parent | b8206bc3de0b0665d47655d270c18ea46aff5372 (diff) | |
dm log: make module use tracking internal
Remove internal module reference fields from the interface.
Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
| -rw-r--r-- | drivers/md/dm-log.c | 123 | ||||
| -rw-r--r-- | drivers/md/dm-log.h | 2 |
2 files changed, 94 insertions, 31 deletions
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 82df73f67a0d..e6b6a9d5fdd2 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
| @@ -16,34 +16,51 @@ | |||
| 16 | 16 | ||
| 17 | #define DM_MSG_PREFIX "dirty region log" | 17 | #define DM_MSG_PREFIX "dirty region log" |
| 18 | 18 | ||
| 19 | struct dm_dirty_log_internal { | ||
| 20 | struct dm_dirty_log_type *type; | ||
| 21 | |||
| 22 | struct list_head list; | ||
| 23 | long use; | ||
| 24 | }; | ||
| 25 | |||
| 19 | static LIST_HEAD(_log_types); | 26 | static LIST_HEAD(_log_types); |
| 20 | static DEFINE_SPINLOCK(_lock); | 27 | static DEFINE_SPINLOCK(_lock); |
| 21 | 28 | ||
| 22 | static struct dm_dirty_log_type *_get_type(const char *type_name) | 29 | static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name) |
| 23 | { | 30 | { |
| 24 | struct dm_dirty_log_type *type; | 31 | struct dm_dirty_log_internal *log_type; |
| 32 | |||
| 33 | list_for_each_entry(log_type, &_log_types, list) | ||
| 34 | if (!strcmp(name, log_type->type->name)) | ||
| 35 | return log_type; | ||
| 36 | |||
| 37 | return NULL; | ||
| 38 | } | ||
| 39 | |||
| 40 | static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name) | ||
| 41 | { | ||
| 42 | struct dm_dirty_log_internal *log_type; | ||
| 25 | 43 | ||
| 26 | spin_lock(&_lock); | 44 | spin_lock(&_lock); |
| 27 | list_for_each_entry (type, &_log_types, list) | 45 | |
| 28 | if (!strcmp(type_name, type->name)) { | 46 | log_type = __find_dirty_log_type(name); |
| 29 | if (!type->use_count && !try_module_get(type->module)){ | 47 | if (log_type) { |
| 30 | spin_unlock(&_lock); | 48 | if (!log_type->use && !try_module_get(log_type->type->module)) |
| 31 | return NULL; | 49 | log_type = NULL; |
| 32 | } | 50 | else |
| 33 | type->use_count++; | 51 | log_type->use++; |
| 34 | spin_unlock(&_lock); | 52 | } |
| 35 | return type; | ||
| 36 | } | ||
| 37 | 53 | ||
| 38 | spin_unlock(&_lock); | 54 | spin_unlock(&_lock); |
| 39 | return NULL; | 55 | |
| 56 | return log_type; | ||
| 40 | } | 57 | } |
| 41 | 58 | ||
| 42 | /* | 59 | /* |
| 43 | * get_type | 60 | * get_type |
| 44 | * @type_name | 61 | * @type_name |
| 45 | * | 62 | * |
| 46 | * Attempt to retrieve the dirty_log_type by name. If not already | 63 | * Attempt to retrieve the dm_dirty_log_type by name. If not already |
| 47 | * available, attempt to load the appropriate module. | 64 | * available, attempt to load the appropriate module. |
| 48 | * | 65 | * |
| 49 | * Log modules are named "dm-log-" followed by the 'type_name'. | 66 | * Log modules are named "dm-log-" followed by the 'type_name'. |
| @@ -59,11 +76,14 @@ static struct dm_dirty_log_type *_get_type(const char *type_name) | |||
| 59 | static struct dm_dirty_log_type *get_type(const char *type_name) | 76 | static struct dm_dirty_log_type *get_type(const char *type_name) |
| 60 | { | 77 | { |
| 61 | char *p, *type_name_dup; | 78 | char *p, *type_name_dup; |
| 62 | struct dm_dirty_log_type *type; | 79 | struct dm_dirty_log_internal *log_type; |
| 63 | 80 | ||
| 64 | type = _get_type(type_name); | 81 | if (!type_name) |
| 65 | if (type) | 82 | return NULL; |
| 66 | return type; | 83 | |
| 84 | log_type = _get_dirty_log_type(type_name); | ||
| 85 | if (log_type) | ||
| 86 | return log_type->type; | ||
| 67 | 87 | ||
| 68 | type_name_dup = kstrdup(type_name, GFP_KERNEL); | 88 | type_name_dup = kstrdup(type_name, GFP_KERNEL); |
| 69 | if (!type_name_dup) { | 89 | if (!type_name_dup) { |
| @@ -73,50 +93,95 @@ static struct dm_dirty_log_type *get_type(const char *type_name) | |||
| 73 | } | 93 | } |
| 74 | 94 | ||
| 75 | while (request_module("dm-log-%s", type_name_dup) || | 95 | while (request_module("dm-log-%s", type_name_dup) || |
| 76 | !(type = _get_type(type_name))) { | 96 | !(log_type = _get_dirty_log_type(type_name))) { |
| 77 | p = strrchr(type_name_dup, '-'); | 97 | p = strrchr(type_name_dup, '-'); |
| 78 | if (!p) | 98 | if (!p) |
| 79 | break; | 99 | break; |
| 80 | p[0] = '\0'; | 100 | p[0] = '\0'; |
| 81 | } | 101 | } |
| 82 | 102 | ||
| 83 | if (!type) | 103 | if (!log_type) |
| 84 | DMWARN("Module for logging type \"%s\" not found.", type_name); | 104 | DMWARN("Module for logging type \"%s\" not found.", type_name); |
| 85 | 105 | ||
| 86 | kfree(type_name_dup); | 106 | kfree(type_name_dup); |
| 87 | 107 | ||
| 88 | return type; | 108 | return log_type ? log_type->type : NULL; |
| 89 | } | 109 | } |
| 90 | 110 | ||
| 91 | static void put_type(struct dm_dirty_log_type *type) | 111 | static void put_type(struct dm_dirty_log_type *type) |
| 92 | { | 112 | { |
| 113 | struct dm_dirty_log_internal *log_type; | ||
| 114 | |||
| 115 | if (!type) | ||
| 116 | return; | ||
| 117 | |||
| 93 | spin_lock(&_lock); | 118 | spin_lock(&_lock); |
| 94 | if (!--type->use_count) | 119 | log_type = __find_dirty_log_type(type->name); |
| 120 | if (!log_type) | ||
| 121 | goto out; | ||
| 122 | |||
| 123 | if (!--log_type->use) | ||
| 95 | module_put(type->module); | 124 | module_put(type->module); |
| 125 | |||
| 126 | BUG_ON(log_type->use < 0); | ||
| 127 | |||
| 128 | out: | ||
| 96 | spin_unlock(&_lock); | 129 | spin_unlock(&_lock); |
| 97 | } | 130 | } |
| 98 | 131 | ||
| 132 | static struct dm_dirty_log_internal *_alloc_dirty_log_type(struct dm_dirty_log_type *type) | ||
| 133 | { | ||
| 134 | struct dm_dirty_log_internal *log_type = kzalloc(sizeof(*log_type), | ||
| 135 | GFP_KERNEL); | ||
| 136 | |||
| 137 | if (log_type) | ||
| 138 | log_type->type = type; | ||
| 139 | |||
| 140 | return log_type; | ||
| 141 | } | ||
| 142 | |||
| 99 | int dm_dirty_log_type_register(struct dm_dirty_log_type *type) | 143 | int dm_dirty_log_type_register(struct dm_dirty_log_type *type) |
| 100 | { | 144 | { |
| 145 | struct dm_dirty_log_internal *log_type = _alloc_dirty_log_type(type); | ||
| 146 | int r = 0; | ||
| 147 | |||
| 148 | if (!log_type) | ||
| 149 | return -ENOMEM; | ||
| 150 | |||
| 101 | spin_lock(&_lock); | 151 | spin_lock(&_lock); |
| 102 | type->use_count = 0; | 152 | if (!__find_dirty_log_type(type->name)) |
| 103 | list_add(&type->list, &_log_types); | 153 | list_add(&log_type->list, &_log_types); |
| 154 | else { | ||
| 155 | kfree(log_type); | ||
| 156 | r = -EEXIST; | ||
| 157 | } | ||
| 104 | spin_unlock(&_lock); | 158 | spin_unlock(&_lock); |
| 105 | 159 | ||
| 106 | return 0; | 160 | return r; |
| 107 | } | 161 | } |
| 108 | EXPORT_SYMBOL(dm_dirty_log_type_register); | 162 | EXPORT_SYMBOL(dm_dirty_log_type_register); |
| 109 | 163 | ||
| 110 | int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type) | 164 | int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type) |
| 111 | { | 165 | { |
| 166 | struct dm_dirty_log_internal *log_type; | ||
| 167 | |||
| 112 | spin_lock(&_lock); | 168 | spin_lock(&_lock); |
| 113 | 169 | ||
| 114 | if (type->use_count) | 170 | log_type = __find_dirty_log_type(type->name); |
| 115 | DMWARN("Attempt to unregister a log type that is still in use"); | 171 | if (!log_type) { |
| 116 | else | 172 | spin_unlock(&_lock); |
| 117 | list_del(&type->list); | 173 | return -EINVAL; |
| 174 | } | ||
| 175 | |||
| 176 | if (log_type->use) { | ||
| 177 | spin_unlock(&_lock); | ||
| 178 | return -ETXTBSY; | ||
| 179 | } | ||
| 180 | |||
| 181 | list_del(&log_type->list); | ||
| 118 | 182 | ||
| 119 | spin_unlock(&_lock); | 183 | spin_unlock(&_lock); |
| 184 | kfree(log_type); | ||
| 120 | 185 | ||
| 121 | return 0; | 186 | return 0; |
| 122 | } | 187 | } |
diff --git a/drivers/md/dm-log.h b/drivers/md/dm-log.h index 2da48a857cb9..600c5fb2daad 100644 --- a/drivers/md/dm-log.h +++ b/drivers/md/dm-log.h | |||
| @@ -25,10 +25,8 @@ struct dm_dirty_log { | |||
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | struct dm_dirty_log_type { | 27 | struct dm_dirty_log_type { |
| 28 | struct list_head list; | ||
| 29 | const char *name; | 28 | const char *name; |
| 30 | struct module *module; | 29 | struct module *module; |
| 31 | unsigned use_count; | ||
| 32 | 30 | ||
| 33 | int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti, | 31 | int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti, |
| 34 | unsigned argc, char **argv); | 32 | unsigned argc, char **argv); |
