xref: /OK3568_Linux_fs/kernel/drivers/md/dm-exception-store.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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