dm exception store: move dm_target pointer
[linux-2.6] / drivers / md / dm-exception-store.c
1 /*
2  * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
3  * Copyright (C) 2006-2008 Red Hat GmbH
4  *
5  * This file is released under the GPL.
6  */
7
8 #include "dm-exception-store.h"
9
10 #include <linux/mm.h>
11 #include <linux/pagemap.h>
12 #include <linux/vmalloc.h>
13 #include <linux/slab.h>
14
15 #define DM_MSG_PREFIX "snapshot exception stores"
16
17 static LIST_HEAD(_exception_store_types);
18 static DEFINE_SPINLOCK(_lock);
19
20 static struct dm_exception_store_type *__find_exception_store_type(const char *name)
21 {
22         struct dm_exception_store_type *type;
23
24         list_for_each_entry(type, &_exception_store_types, list)
25                 if (!strcmp(name, type->name))
26                         return type;
27
28         return NULL;
29 }
30
31 static struct dm_exception_store_type *_get_exception_store_type(const char *name)
32 {
33         struct dm_exception_store_type *type;
34
35         spin_lock(&_lock);
36
37         type = __find_exception_store_type(name);
38
39         if (type && !try_module_get(type->module))
40                 type = NULL;
41
42         spin_unlock(&_lock);
43
44         return type;
45 }
46
47 /*
48  * get_type
49  * @type_name
50  *
51  * Attempt to retrieve the dm_exception_store_type by name.  If not already
52  * available, attempt to load the appropriate module.
53  *
54  * Exstore modules are named "dm-exstore-" followed by the 'type_name'.
55  * Modules may contain multiple types.
56  * This function will first try the module "dm-exstore-<type_name>",
57  * then truncate 'type_name' on the last '-' and try again.
58  *
59  * For example, if type_name was "clustered-shared", it would search
60  * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'.
61  *
62  * 'dm-exception-store-<type_name>' is too long of a name in my
63  * opinion, which is why I've chosen to have the files
64  * containing exception store implementations be 'dm-exstore-<type_name>'.
65  * If you want your module to be autoloaded, you will follow this
66  * naming convention.
67  *
68  * Returns: dm_exception_store_type* on success, NULL on failure
69  */
70 static struct dm_exception_store_type *get_type(const char *type_name)
71 {
72         char *p, *type_name_dup;
73         struct dm_exception_store_type *type;
74
75         type = _get_exception_store_type(type_name);
76         if (type)
77                 return type;
78
79         type_name_dup = kstrdup(type_name, GFP_KERNEL);
80         if (!type_name_dup) {
81                 DMERR("No memory left to attempt load for \"%s\"", type_name);
82                 return NULL;
83         }
84
85         while (request_module("dm-exstore-%s", type_name_dup) ||
86                !(type = _get_exception_store_type(type_name))) {
87                 p = strrchr(type_name_dup, '-');
88                 if (!p)
89                         break;
90                 p[0] = '\0';
91         }
92
93         if (!type)
94                 DMWARN("Module for exstore type \"%s\" not found.", type_name);
95
96         kfree(type_name_dup);
97
98         return type;
99 }
100
101 static void put_type(struct dm_exception_store_type *type)
102 {
103         spin_lock(&_lock);
104         module_put(type->module);
105         spin_unlock(&_lock);
106 }
107
108 int dm_exception_store_type_register(struct dm_exception_store_type *type)
109 {
110         int r = 0;
111
112         spin_lock(&_lock);
113         if (!__find_exception_store_type(type->name))
114                 list_add(&type->list, &_exception_store_types);
115         else
116                 r = -EEXIST;
117         spin_unlock(&_lock);
118
119         return r;
120 }
121 EXPORT_SYMBOL(dm_exception_store_type_register);
122
123 int dm_exception_store_type_unregister(struct dm_exception_store_type *type)
124 {
125         spin_lock(&_lock);
126
127         if (!__find_exception_store_type(type->name)) {
128                 spin_unlock(&_lock);
129                 return -EINVAL;
130         }
131
132         list_del(&type->list);
133
134         spin_unlock(&_lock);
135
136         return 0;
137 }
138 EXPORT_SYMBOL(dm_exception_store_type_unregister);
139
140 int dm_exception_store_create(const char *type_name, struct dm_target *ti,
141                               struct dm_exception_store **store)
142 {
143         int r = 0;
144         struct dm_exception_store_type *type;
145         struct dm_exception_store *tmp_store;
146
147         tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL);
148         if (!tmp_store)
149                 return -ENOMEM;
150
151         type = get_type(type_name);
152         if (!type) {
153                 kfree(tmp_store);
154                 return -EINVAL;
155         }
156
157         tmp_store->type = type;
158         tmp_store->ti = ti;
159
160         r = type->ctr(tmp_store, 0, NULL);
161         if (r) {
162                 put_type(type);
163                 kfree(tmp_store);
164                 return r;
165         }
166
167         *store = tmp_store;
168         return 0;
169 }
170 EXPORT_SYMBOL(dm_exception_store_create);
171
172 void dm_exception_store_destroy(struct dm_exception_store *store)
173 {
174         store->type->dtr(store);
175         put_type(store->type);
176         kfree(store);
177 }
178 EXPORT_SYMBOL(dm_exception_store_destroy);
179
180 int dm_exception_store_init(void)
181 {
182         int r;
183
184         r = dm_transient_snapshot_init();
185         if (r) {
186                 DMERR("Unable to register transient exception store type.");
187                 goto transient_fail;
188         }
189
190         r = dm_persistent_snapshot_init();
191         if (r) {
192                 DMERR("Unable to register persistent exception store type");
193                 goto persistent_fail;
194         }
195
196         return 0;
197
198 persistent_fail:
199         dm_persistent_snapshot_exit();
200 transient_fail:
201         return r;
202 }
203
204 void dm_exception_store_exit(void)
205 {
206         dm_persistent_snapshot_exit();
207         dm_transient_snapshot_exit();
208 }