1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
3*4882a593Smuzhiyun * Copyright (C) 2006-2008 Red Hat GmbH
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * This file is released under the GPL.
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include "dm-exception-store.h"
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #include <linux/ctype.h>
11*4882a593Smuzhiyun #include <linux/mm.h>
12*4882a593Smuzhiyun #include <linux/pagemap.h>
13*4882a593Smuzhiyun #include <linux/vmalloc.h>
14*4882a593Smuzhiyun #include <linux/module.h>
15*4882a593Smuzhiyun #include <linux/slab.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define DM_MSG_PREFIX "snapshot exception stores"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun static LIST_HEAD(_exception_store_types);
20*4882a593Smuzhiyun static DEFINE_SPINLOCK(_lock);
21*4882a593Smuzhiyun
__find_exception_store_type(const char * name)22*4882a593Smuzhiyun static struct dm_exception_store_type *__find_exception_store_type(const char *name)
23*4882a593Smuzhiyun {
24*4882a593Smuzhiyun struct dm_exception_store_type *type;
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun list_for_each_entry(type, &_exception_store_types, list)
27*4882a593Smuzhiyun if (!strcmp(name, type->name))
28*4882a593Smuzhiyun return type;
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun return NULL;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun
_get_exception_store_type(const char * name)33*4882a593Smuzhiyun static struct dm_exception_store_type *_get_exception_store_type(const char *name)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun struct dm_exception_store_type *type;
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun spin_lock(&_lock);
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun type = __find_exception_store_type(name);
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun if (type && !try_module_get(type->module))
42*4882a593Smuzhiyun type = NULL;
43*4882a593Smuzhiyun
44*4882a593Smuzhiyun spin_unlock(&_lock);
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun return type;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun /*
50*4882a593Smuzhiyun * get_type
51*4882a593Smuzhiyun * @type_name
52*4882a593Smuzhiyun *
53*4882a593Smuzhiyun * Attempt to retrieve the dm_exception_store_type by name. If not already
54*4882a593Smuzhiyun * available, attempt to load the appropriate module.
55*4882a593Smuzhiyun *
56*4882a593Smuzhiyun * Exstore modules are named "dm-exstore-" followed by the 'type_name'.
57*4882a593Smuzhiyun * Modules may contain multiple types.
58*4882a593Smuzhiyun * This function will first try the module "dm-exstore-<type_name>",
59*4882a593Smuzhiyun * then truncate 'type_name' on the last '-' and try again.
60*4882a593Smuzhiyun *
61*4882a593Smuzhiyun * For example, if type_name was "clustered-shared", it would search
62*4882a593Smuzhiyun * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'.
63*4882a593Smuzhiyun *
64*4882a593Smuzhiyun * 'dm-exception-store-<type_name>' is too long of a name in my
65*4882a593Smuzhiyun * opinion, which is why I've chosen to have the files
66*4882a593Smuzhiyun * containing exception store implementations be 'dm-exstore-<type_name>'.
67*4882a593Smuzhiyun * If you want your module to be autoloaded, you will follow this
68*4882a593Smuzhiyun * naming convention.
69*4882a593Smuzhiyun *
70*4882a593Smuzhiyun * Returns: dm_exception_store_type* on success, NULL on failure
71*4882a593Smuzhiyun */
get_type(const char * type_name)72*4882a593Smuzhiyun static struct dm_exception_store_type *get_type(const char *type_name)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun char *p, *type_name_dup;
75*4882a593Smuzhiyun struct dm_exception_store_type *type;
76*4882a593Smuzhiyun
77*4882a593Smuzhiyun type = _get_exception_store_type(type_name);
78*4882a593Smuzhiyun if (type)
79*4882a593Smuzhiyun return type;
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun type_name_dup = kstrdup(type_name, GFP_KERNEL);
82*4882a593Smuzhiyun if (!type_name_dup) {
83*4882a593Smuzhiyun DMERR("No memory left to attempt load for \"%s\"", type_name);
84*4882a593Smuzhiyun return NULL;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun while (request_module("dm-exstore-%s", type_name_dup) ||
88*4882a593Smuzhiyun !(type = _get_exception_store_type(type_name))) {
89*4882a593Smuzhiyun p = strrchr(type_name_dup, '-');
90*4882a593Smuzhiyun if (!p)
91*4882a593Smuzhiyun break;
92*4882a593Smuzhiyun p[0] = '\0';
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun if (!type)
96*4882a593Smuzhiyun DMWARN("Module for exstore type \"%s\" not found.", type_name);
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun kfree(type_name_dup);
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun return type;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
put_type(struct dm_exception_store_type * type)103*4882a593Smuzhiyun static void put_type(struct dm_exception_store_type *type)
104*4882a593Smuzhiyun {
105*4882a593Smuzhiyun spin_lock(&_lock);
106*4882a593Smuzhiyun module_put(type->module);
107*4882a593Smuzhiyun spin_unlock(&_lock);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
dm_exception_store_type_register(struct dm_exception_store_type * type)110*4882a593Smuzhiyun int dm_exception_store_type_register(struct dm_exception_store_type *type)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun int r = 0;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun spin_lock(&_lock);
115*4882a593Smuzhiyun if (!__find_exception_store_type(type->name))
116*4882a593Smuzhiyun list_add(&type->list, &_exception_store_types);
117*4882a593Smuzhiyun else
118*4882a593Smuzhiyun r = -EEXIST;
119*4882a593Smuzhiyun spin_unlock(&_lock);
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun return r;
122*4882a593Smuzhiyun }
123*4882a593Smuzhiyun EXPORT_SYMBOL(dm_exception_store_type_register);
124*4882a593Smuzhiyun
dm_exception_store_type_unregister(struct dm_exception_store_type * type)125*4882a593Smuzhiyun int dm_exception_store_type_unregister(struct dm_exception_store_type *type)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun spin_lock(&_lock);
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun if (!__find_exception_store_type(type->name)) {
130*4882a593Smuzhiyun spin_unlock(&_lock);
131*4882a593Smuzhiyun return -EINVAL;
132*4882a593Smuzhiyun }
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun list_del(&type->list);
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun spin_unlock(&_lock);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun return 0;
139*4882a593Smuzhiyun }
140*4882a593Smuzhiyun EXPORT_SYMBOL(dm_exception_store_type_unregister);
141*4882a593Smuzhiyun
set_chunk_size(struct dm_exception_store * store,const char * chunk_size_arg,char ** error)142*4882a593Smuzhiyun static int set_chunk_size(struct dm_exception_store *store,
143*4882a593Smuzhiyun const char *chunk_size_arg, char **error)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun unsigned chunk_size;
146*4882a593Smuzhiyun
147*4882a593Smuzhiyun if (kstrtouint(chunk_size_arg, 10, &chunk_size)) {
148*4882a593Smuzhiyun *error = "Invalid chunk size";
149*4882a593Smuzhiyun return -EINVAL;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (!chunk_size) {
153*4882a593Smuzhiyun store->chunk_size = store->chunk_mask = store->chunk_shift = 0;
154*4882a593Smuzhiyun return 0;
155*4882a593Smuzhiyun }
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun return dm_exception_store_set_chunk_size(store, chunk_size, error);
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
dm_exception_store_set_chunk_size(struct dm_exception_store * store,unsigned chunk_size,char ** error)160*4882a593Smuzhiyun int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
161*4882a593Smuzhiyun unsigned chunk_size,
162*4882a593Smuzhiyun char **error)
163*4882a593Smuzhiyun {
164*4882a593Smuzhiyun /* Check chunk_size is a power of 2 */
165*4882a593Smuzhiyun if (!is_power_of_2(chunk_size)) {
166*4882a593Smuzhiyun *error = "Chunk size is not a power of 2";
167*4882a593Smuzhiyun return -EINVAL;
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun
170*4882a593Smuzhiyun /* Validate the chunk size against the device block size */
171*4882a593Smuzhiyun if (chunk_size %
172*4882a593Smuzhiyun (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) ||
173*4882a593Smuzhiyun chunk_size %
174*4882a593Smuzhiyun (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) {
175*4882a593Smuzhiyun *error = "Chunk size is not a multiple of device blocksize";
176*4882a593Smuzhiyun return -EINVAL;
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (chunk_size > INT_MAX >> SECTOR_SHIFT) {
180*4882a593Smuzhiyun *error = "Chunk size is too high";
181*4882a593Smuzhiyun return -EINVAL;
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun store->chunk_size = chunk_size;
185*4882a593Smuzhiyun store->chunk_mask = chunk_size - 1;
186*4882a593Smuzhiyun store->chunk_shift = __ffs(chunk_size);
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun return 0;
189*4882a593Smuzhiyun }
190*4882a593Smuzhiyun
dm_exception_store_create(struct dm_target * ti,int argc,char ** argv,struct dm_snapshot * snap,unsigned * args_used,struct dm_exception_store ** store)191*4882a593Smuzhiyun int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
192*4882a593Smuzhiyun struct dm_snapshot *snap,
193*4882a593Smuzhiyun unsigned *args_used,
194*4882a593Smuzhiyun struct dm_exception_store **store)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun int r = 0;
197*4882a593Smuzhiyun struct dm_exception_store_type *type = NULL;
198*4882a593Smuzhiyun struct dm_exception_store *tmp_store;
199*4882a593Smuzhiyun char persistent;
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun if (argc < 2) {
202*4882a593Smuzhiyun ti->error = "Insufficient exception store arguments";
203*4882a593Smuzhiyun return -EINVAL;
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun tmp_store = kzalloc(sizeof(*tmp_store), GFP_KERNEL);
207*4882a593Smuzhiyun if (!tmp_store) {
208*4882a593Smuzhiyun ti->error = "Exception store allocation failed";
209*4882a593Smuzhiyun return -ENOMEM;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun persistent = toupper(*argv[0]);
213*4882a593Smuzhiyun if (persistent == 'P')
214*4882a593Smuzhiyun type = get_type("P");
215*4882a593Smuzhiyun else if (persistent == 'N')
216*4882a593Smuzhiyun type = get_type("N");
217*4882a593Smuzhiyun else {
218*4882a593Smuzhiyun ti->error = "Exception store type is not P or N";
219*4882a593Smuzhiyun r = -EINVAL;
220*4882a593Smuzhiyun goto bad_type;
221*4882a593Smuzhiyun }
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun if (!type) {
224*4882a593Smuzhiyun ti->error = "Exception store type not recognised";
225*4882a593Smuzhiyun r = -EINVAL;
226*4882a593Smuzhiyun goto bad_type;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun tmp_store->type = type;
230*4882a593Smuzhiyun tmp_store->snap = snap;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun r = set_chunk_size(tmp_store, argv[1], &ti->error);
233*4882a593Smuzhiyun if (r)
234*4882a593Smuzhiyun goto bad;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun r = type->ctr(tmp_store, (strlen(argv[0]) > 1 ? &argv[0][1] : NULL));
237*4882a593Smuzhiyun if (r) {
238*4882a593Smuzhiyun ti->error = "Exception store type constructor failed";
239*4882a593Smuzhiyun goto bad;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun *args_used = 2;
243*4882a593Smuzhiyun *store = tmp_store;
244*4882a593Smuzhiyun return 0;
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun bad:
247*4882a593Smuzhiyun put_type(type);
248*4882a593Smuzhiyun bad_type:
249*4882a593Smuzhiyun kfree(tmp_store);
250*4882a593Smuzhiyun return r;
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun EXPORT_SYMBOL(dm_exception_store_create);
253*4882a593Smuzhiyun
dm_exception_store_destroy(struct dm_exception_store * store)254*4882a593Smuzhiyun void dm_exception_store_destroy(struct dm_exception_store *store)
255*4882a593Smuzhiyun {
256*4882a593Smuzhiyun store->type->dtr(store);
257*4882a593Smuzhiyun put_type(store->type);
258*4882a593Smuzhiyun kfree(store);
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun EXPORT_SYMBOL(dm_exception_store_destroy);
261*4882a593Smuzhiyun
dm_exception_store_init(void)262*4882a593Smuzhiyun int dm_exception_store_init(void)
263*4882a593Smuzhiyun {
264*4882a593Smuzhiyun int r;
265*4882a593Smuzhiyun
266*4882a593Smuzhiyun r = dm_transient_snapshot_init();
267*4882a593Smuzhiyun if (r) {
268*4882a593Smuzhiyun DMERR("Unable to register transient exception store type.");
269*4882a593Smuzhiyun goto transient_fail;
270*4882a593Smuzhiyun }
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun r = dm_persistent_snapshot_init();
273*4882a593Smuzhiyun if (r) {
274*4882a593Smuzhiyun DMERR("Unable to register persistent exception store type");
275*4882a593Smuzhiyun goto persistent_fail;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun return 0;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun persistent_fail:
281*4882a593Smuzhiyun dm_transient_snapshot_exit();
282*4882a593Smuzhiyun transient_fail:
283*4882a593Smuzhiyun return r;
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun
dm_exception_store_exit(void)286*4882a593Smuzhiyun void dm_exception_store_exit(void)
287*4882a593Smuzhiyun {
288*4882a593Smuzhiyun dm_persistent_snapshot_exit();
289*4882a593Smuzhiyun dm_transient_snapshot_exit();
290*4882a593Smuzhiyun }
291