dm exception store: move cow 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                               chunk_t chunk_size, chunk_t chunk_mask,
142                               chunk_t chunk_shift, struct dm_dev *cow,
143                               struct dm_exception_store **store)
144 {
145         int r = 0;
146         struct dm_exception_store_type *type;
147         struct dm_exception_store *tmp_store;
148
149         tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL);
150         if (!tmp_store)
151                 return -ENOMEM;
152
153         type = get_type(type_name);
154         if (!type) {
155                 kfree(tmp_store);
156                 return -EINVAL;
157         }
158
159         tmp_store->type = type;
160         tmp_store->ti = ti;
161
162         tmp_store->chunk_size = chunk_size;
163         tmp_store->chunk_mask = chunk_mask;
164         tmp_store->chunk_shift = chunk_shift;
165
166         tmp_store->cow = cow;
167
168         r = type->ctr(tmp_store, 0, NULL);
169         if (r) {
170                 put_type(type);
171                 kfree(tmp_store);
172                 return r;
173         }
174
175         *store = tmp_store;
176         return 0;
177 }
178 EXPORT_SYMBOL(dm_exception_store_create);
179
180 void dm_exception_store_destroy(struct dm_exception_store *store)
181 {
182         store->type->dtr(store);
183         put_type(store->type);
184         kfree(store);
185 }
186 EXPORT_SYMBOL(dm_exception_store_destroy);
187
188 int dm_exception_store_init(void)
189 {
190         int r;
191
192         r = dm_transient_snapshot_init();
193         if (r) {
194                 DMERR("Unable to register transient exception store type.");
195                 goto transient_fail;
196         }
197
198         r = dm_persistent_snapshot_init();
199         if (r) {
200                 DMERR("Unable to register persistent exception store type");
201                 goto persistent_fail;
202         }
203
204         return 0;
205
206 persistent_fail:
207         dm_persistent_snapshot_exit();
208 transient_fail:
209         return r;
210 }
211
212 void dm_exception_store_exit(void)
213 {
214         dm_persistent_snapshot_exit();
215         dm_transient_snapshot_exit();
216 }