diff options
-rw-r--r-- | drivers/md/dm-log.c | 58 | ||||
-rw-r--r-- | include/linux/dm-dirty-log.h | 3 |
2 files changed, 17 insertions, 44 deletions
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 094c8f0e0097..be233bc4d917 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
@@ -16,34 +16,28 @@ | |||
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 | }; | ||
24 | |||
25 | static LIST_HEAD(_log_types); | 19 | static LIST_HEAD(_log_types); |
26 | static DEFINE_SPINLOCK(_lock); | 20 | static DEFINE_SPINLOCK(_lock); |
27 | 21 | ||
28 | static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name) | 22 | static struct dm_dirty_log_type *__find_dirty_log_type(const char *name) |
29 | { | 23 | { |
30 | struct dm_dirty_log_internal *log_type; | 24 | struct dm_dirty_log_type *log_type; |
31 | 25 | ||
32 | list_for_each_entry(log_type, &_log_types, list) | 26 | list_for_each_entry(log_type, &_log_types, list) |
33 | if (!strcmp(name, log_type->type->name)) | 27 | if (!strcmp(name, log_type->name)) |
34 | return log_type; | 28 | return log_type; |
35 | 29 | ||
36 | return NULL; | 30 | return NULL; |
37 | } | 31 | } |
38 | 32 | ||
39 | static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name) | 33 | static struct dm_dirty_log_type *_get_dirty_log_type(const char *name) |
40 | { | 34 | { |
41 | struct dm_dirty_log_internal *log_type; | 35 | struct dm_dirty_log_type *log_type; |
42 | 36 | ||
43 | spin_lock(&_lock); | 37 | spin_lock(&_lock); |
44 | 38 | ||
45 | log_type = __find_dirty_log_type(name); | 39 | log_type = __find_dirty_log_type(name); |
46 | if (log_type && !try_module_get(log_type->type->module)) | 40 | if (log_type && !try_module_get(log_type->module)) |
47 | log_type = NULL; | 41 | log_type = NULL; |
48 | 42 | ||
49 | spin_unlock(&_lock); | 43 | spin_unlock(&_lock); |
@@ -71,14 +65,14 @@ static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name) | |||
71 | static struct dm_dirty_log_type *get_type(const char *type_name) | 65 | static struct dm_dirty_log_type *get_type(const char *type_name) |
72 | { | 66 | { |
73 | char *p, *type_name_dup; | 67 | char *p, *type_name_dup; |
74 | struct dm_dirty_log_internal *log_type; | 68 | struct dm_dirty_log_type *log_type; |
75 | 69 | ||
76 | if (!type_name) | 70 | if (!type_name) |
77 | return NULL; | 71 | return NULL; |
78 | 72 | ||
79 | log_type = _get_dirty_log_type(type_name); | 73 | log_type = _get_dirty_log_type(type_name); |
80 | if (log_type) | 74 | if (log_type) |
81 | return log_type->type; | 75 | return log_type; |
82 | 76 | ||
83 | type_name_dup = kstrdup(type_name, GFP_KERNEL); | 77 | type_name_dup = kstrdup(type_name, GFP_KERNEL); |
84 | if (!type_name_dup) { | 78 | if (!type_name_dup) { |
@@ -100,19 +94,16 @@ static struct dm_dirty_log_type *get_type(const char *type_name) | |||
100 | 94 | ||
101 | kfree(type_name_dup); | 95 | kfree(type_name_dup); |
102 | 96 | ||
103 | return log_type ? log_type->type : NULL; | 97 | return log_type; |
104 | } | 98 | } |
105 | 99 | ||
106 | static void put_type(struct dm_dirty_log_type *type) | 100 | static void put_type(struct dm_dirty_log_type *type) |
107 | { | 101 | { |
108 | struct dm_dirty_log_internal *log_type; | ||
109 | |||
110 | if (!type) | 102 | if (!type) |
111 | return; | 103 | return; |
112 | 104 | ||
113 | spin_lock(&_lock); | 105 | spin_lock(&_lock); |
114 | log_type = __find_dirty_log_type(type->name); | 106 | if (!__find_dirty_log_type(type->name)) |
115 | if (!log_type) | ||
116 | goto out; | 107 | goto out; |
117 | 108 | ||
118 | module_put(type->module); | 109 | module_put(type->module); |
@@ -121,32 +112,15 @@ out: | |||
121 | spin_unlock(&_lock); | 112 | spin_unlock(&_lock); |
122 | } | 113 | } |
123 | 114 | ||
124 | static struct dm_dirty_log_internal *_alloc_dirty_log_type(struct dm_dirty_log_type *type) | ||
125 | { | ||
126 | struct dm_dirty_log_internal *log_type = kzalloc(sizeof(*log_type), | ||
127 | GFP_KERNEL); | ||
128 | |||
129 | if (log_type) | ||
130 | log_type->type = type; | ||
131 | |||
132 | return log_type; | ||
133 | } | ||
134 | |||
135 | int dm_dirty_log_type_register(struct dm_dirty_log_type *type) | 115 | int dm_dirty_log_type_register(struct dm_dirty_log_type *type) |
136 | { | 116 | { |
137 | struct dm_dirty_log_internal *log_type = _alloc_dirty_log_type(type); | ||
138 | int r = 0; | 117 | int r = 0; |
139 | 118 | ||
140 | if (!log_type) | ||
141 | return -ENOMEM; | ||
142 | |||
143 | spin_lock(&_lock); | 119 | spin_lock(&_lock); |
144 | if (!__find_dirty_log_type(type->name)) | 120 | if (!__find_dirty_log_type(type->name)) |
145 | list_add(&log_type->list, &_log_types); | 121 | list_add(&type->list, &_log_types); |
146 | else { | 122 | else |
147 | kfree(log_type); | ||
148 | r = -EEXIST; | 123 | r = -EEXIST; |
149 | } | ||
150 | spin_unlock(&_lock); | 124 | spin_unlock(&_lock); |
151 | 125 | ||
152 | return r; | 126 | return r; |
@@ -155,20 +129,16 @@ EXPORT_SYMBOL(dm_dirty_log_type_register); | |||
155 | 129 | ||
156 | int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type) | 130 | int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type) |
157 | { | 131 | { |
158 | struct dm_dirty_log_internal *log_type; | ||
159 | |||
160 | spin_lock(&_lock); | 132 | spin_lock(&_lock); |
161 | 133 | ||
162 | log_type = __find_dirty_log_type(type->name); | 134 | if (!__find_dirty_log_type(type->name)) { |
163 | if (!log_type) { | ||
164 | spin_unlock(&_lock); | 135 | spin_unlock(&_lock); |
165 | return -EINVAL; | 136 | return -EINVAL; |
166 | } | 137 | } |
167 | 138 | ||
168 | list_del(&log_type->list); | 139 | list_del(&type->list); |
169 | 140 | ||
170 | spin_unlock(&_lock); | 141 | spin_unlock(&_lock); |
171 | kfree(log_type); | ||
172 | 142 | ||
173 | return 0; | 143 | return 0; |
174 | } | 144 | } |
diff --git a/include/linux/dm-dirty-log.h b/include/linux/dm-dirty-log.h index 600c5fb2daad..727602b686d4 100644 --- a/include/linux/dm-dirty-log.h +++ b/include/linux/dm-dirty-log.h | |||
@@ -28,6 +28,9 @@ struct dm_dirty_log_type { | |||
28 | const char *name; | 28 | const char *name; |
29 | struct module *module; | 29 | struct module *module; |
30 | 30 | ||
31 | /* For internal device-mapper use */ | ||
32 | struct list_head list; | ||
33 | |||
31 | int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti, | 34 | int (*ctr)(struct dm_dirty_log *log, struct dm_target *ti, |
32 | unsigned argc, char **argv); | 35 | unsigned argc, char **argv); |
33 | void (*dtr)(struct dm_dirty_log *log); | 36 | void (*dtr)(struct dm_dirty_log *log); |