aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-log.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-log.c')
-rw-r--r--drivers/md/dm-log.c75
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
19struct dm_dirty_log_internal {
20 struct dm_dirty_log_type *type;
21
22 struct list_head list;
23 long use;
24};
25
26static LIST_HEAD(_log_types); 19static LIST_HEAD(_log_types);
27static DEFINE_SPINLOCK(_lock); 20static DEFINE_SPINLOCK(_lock);
28 21
29static struct dm_dirty_log_internal *__find_dirty_log_type(const char *name) 22static 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
40static struct dm_dirty_log_internal *_get_dirty_log_type(const char *name) 33static 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)
76static struct dm_dirty_log_type *get_type(const char *type_name) 65static 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
111static void put_type(struct dm_dirty_log_type *type) 100static 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
128out: 111out:
129 spin_unlock(&_lock); 112 spin_unlock(&_lock);
130} 113}
131 114
132static 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
143int dm_dirty_log_type_register(struct dm_dirty_log_type *type) 115int 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
164int dm_dirty_log_type_unregister(struct dm_dirty_log_type *type) 130int 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}