diff options
Diffstat (limited to 'drivers/md/dm-log.c')
-rw-r--r-- | drivers/md/dm-log.c | 75 |
1 files changed, 16 insertions, 59 deletions
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 737961f275c1..be233bc4d917 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
@@ -16,40 +16,29 @@ | |||
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 | |||
26 | static LIST_HEAD(_log_types); | 19 | static LIST_HEAD(_log_types); |
27 | static DEFINE_SPINLOCK(_lock); | 20 | static DEFINE_SPINLOCK(_lock); |
28 | 21 | ||
29 | 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) |
30 | { | 23 | { |
31 | struct dm_dirty_log_internal *log_type; | 24 | struct dm_dirty_log_type *log_type; |
32 | 25 | ||
33 | list_for_each_entry(log_type, &_log_types, list) | 26 | list_for_each_entry(log_type, &_log_types, list) |
34 | if (!strcmp(name, log_type->type->name)) | 27 | if (!strcmp(name, log_type->name)) |
35 | return log_type; | 28 | return log_type; |
36 | 29 | ||
37 | return NULL; | 30 | return NULL; |
38 | } | 31 | } |
39 | 32 | ||
40 | 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) |
41 | { | 34 | { |
42 | struct dm_dirty_log_internal *log_type; | 35 | struct dm_dirty_log_type *log_type; |
43 | 36 | ||
44 | spin_lock(&_lock); | 37 | spin_lock(&_lock); |
45 | 38 | ||
46 | log_type = __find_dirty_log_type(name); | 39 | log_type = __find_dirty_log_type(name); |
47 | if (log_type) { | 40 | if (log_type && !try_module_get(log_type->module)) |
48 | if (!log_type->use && !try_module_get(log_type->type->module)) | 41 | log_type = NULL; |
49 | log_type = NULL; | ||
50 | else | ||
51 | log_type->use++; | ||
52 | } | ||
53 | 42 | ||
54 | spin_unlock(&_lock); | 43 | spin_unlock(&_lock); |
55 | 44 | ||
@@ -76,14 +65,14 @@ static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name) | |||
76 | 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) |
77 | { | 66 | { |
78 | char *p, *type_name_dup; | 67 | char *p, *type_name_dup; |
79 | struct dm_dirty_log_internal *log_type; | 68 | struct dm_dirty_log_type *log_type; |
80 | 69 | ||
81 | if (!type_name) | 70 | if (!type_name) |
82 | return NULL; | 71 | return NULL; |
83 | 72 | ||
84 | log_type = _get_dirty_log_type(type_name); | 73 | log_type = _get_dirty_log_type(type_name); |
85 | if (log_type) | 74 | if (log_type) |
86 | return log_type->type; | 75 | return log_type; |
87 | 76 | ||
88 | type_name_dup = kstrdup(type_name, GFP_KERNEL); | 77 | type_name_dup = kstrdup(type_name, GFP_KERNEL); |
89 | if (!type_name_dup) { | 78 | if (!type_name_dup) { |
@@ -105,56 +94,33 @@ static struct dm_dirty_log_type *get_type(const char *type_name) | |||
105 | 94 | ||
106 | kfree(type_name_dup); | 95 | kfree(type_name_dup); |
107 | 96 | ||
108 | return log_type ? log_type->type : NULL; | 97 | return log_type; |
109 | } | 98 | } |
110 | 99 | ||
111 | static void put_type(struct dm_dirty_log_type *type) | 100 | static void put_type(struct dm_dirty_log_type *type) |
112 | { | 101 | { |
113 | struct dm_dirty_log_internal *log_type; | ||
114 | |||
115 | if (!type) | 102 | if (!type) |
116 | return; | 103 | return; |
117 | 104 | ||
118 | spin_lock(&_lock); | 105 | spin_lock(&_lock); |
119 | log_type = __find_dirty_log_type(type->name); | 106 | if (!__find_dirty_log_type(type->name)) |
120 | if (!log_type) | ||
121 | goto out; | 107 | goto out; |
122 | 108 | ||
123 | if (!--log_type->use) | 109 | module_put(type->module); |
124 | module_put(type->module); | ||
125 | |||
126 | BUG_ON(log_type->use < 0); | ||
127 | 110 | ||
128 | out: | 111 | out: |
129 | spin_unlock(&_lock); | 112 | spin_unlock(&_lock); |
130 | } | 113 | } |
131 | 114 | ||
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 | |||
143 | 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) |
144 | { | 116 | { |
145 | struct dm_dirty_log_internal *log_type = _alloc_dirty_log_type(type); | ||
146 | int r = 0; | 117 | int r = 0; |
147 | 118 | ||
148 | if (!log_type) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | spin_lock(&_lock); | 119 | spin_lock(&_lock); |
152 | if (!__find_dirty_log_type(type->name)) | 120 | if (!__find_dirty_log_type(type->name)) |
153 | list_add(&log_type->list, &_log_types); | 121 | list_add(&type->list, &_log_types); |
154 | else { | 122 | else |
155 | kfree(log_type); | ||
156 | r = -EEXIST; | 123 | r = -EEXIST; |
157 | } | ||
158 | spin_unlock(&_lock); | 124 | spin_unlock(&_lock); |
159 | 125 | ||
160 | return r; | 126 | return r; |
@@ -163,25 +129,16 @@ EXPORT_SYMBOL(dm_dirty_log_type_register); | |||
163 | 129 | ||
164 | 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) |
165 | { | 131 | { |
166 | struct dm_dirty_log_internal *log_type; | ||
167 | |||
168 | spin_lock(&_lock); | 132 | spin_lock(&_lock); |
169 | 133 | ||
170 | log_type = __find_dirty_log_type(type->name); | 134 | if (!__find_dirty_log_type(type->name)) { |
171 | if (!log_type) { | ||
172 | spin_unlock(&_lock); | 135 | spin_unlock(&_lock); |
173 | return -EINVAL; | 136 | return -EINVAL; |
174 | } | 137 | } |
175 | 138 | ||
176 | if (log_type->use) { | 139 | list_del(&type->list); |
177 | spin_unlock(&_lock); | ||
178 | return -ETXTBSY; | ||
179 | } | ||
180 | |||
181 | list_del(&log_type->list); | ||
182 | 140 | ||
183 | spin_unlock(&_lock); | 141 | spin_unlock(&_lock); |
184 | kfree(log_type); | ||
185 | 142 | ||
186 | return 0; | 143 | return 0; |
187 | } | 144 | } |