dm-exception-store.c revision 0cea9c78270cdf1d2ad74ce0e083d5555a0842e8
11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
34db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon * Copyright (C) 2006-2008 Red Hat GmbH
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This file is released under the GPL.
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8aea53d92f70eeb00ae480e399a997dd55fd5055dJonathan Brassow#include "dm-exception-store.h"
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mm.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pagemap.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vmalloc.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
154db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon#define DM_MSG_PREFIX "snapshot exception stores"
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
17493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic LIST_HEAD(_exception_store_types);
18493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic DEFINE_SPINLOCK(_lock);
19493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
20493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *__find_exception_store_type(const char *name)
21493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{
22493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	struct dm_exception_store_type *type;
23493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
24493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	list_for_each_entry(type, &_exception_store_types, list)
25493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		if (!strcmp(name, type->name))
26493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow			return type;
27493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
28493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	return NULL;
29493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow}
30493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
31493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *_get_exception_store_type(const char *name)
32493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{
33493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	struct dm_exception_store_type *type;
34493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
35493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	spin_lock(&_lock);
36493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
37493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	type = __find_exception_store_type(name);
38493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
39493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (type && !try_module_get(type->module))
40493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		type = NULL;
41493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
42493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	spin_unlock(&_lock);
43493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
44493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	return type;
45493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow}
46493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
47493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow/*
48493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * get_type
49493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * @type_name
50493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow *
51493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Attempt to retrieve the dm_exception_store_type by name.  If not already
52493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * available, attempt to load the appropriate module.
53493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow *
54493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Exstore modules are named "dm-exstore-" followed by the 'type_name'.
55493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Modules may contain multiple types.
56493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * This function will first try the module "dm-exstore-<type_name>",
57493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * then truncate 'type_name' on the last '-' and try again.
58493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow *
59493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * For example, if type_name was "clustered-shared", it would search
60493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'.
61493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow *
62493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * 'dm-exception-store-<type_name>' is too long of a name in my
63493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * opinion, which is why I've chosen to have the files
64493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * containing exception store implementations be 'dm-exstore-<type_name>'.
65493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * If you want your module to be autoloaded, you will follow this
66493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * naming convention.
67493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow *
68493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow * Returns: dm_exception_store_type* on success, NULL on failure
69493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow */
70493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic struct dm_exception_store_type *get_type(const char *type_name)
71493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{
72493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	char *p, *type_name_dup;
73493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	struct dm_exception_store_type *type;
74493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
75493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	type = _get_exception_store_type(type_name);
76493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (type)
77493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		return type;
78493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
79493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	type_name_dup = kstrdup(type_name, GFP_KERNEL);
80493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (!type_name_dup) {
81493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		DMERR("No memory left to attempt load for \"%s\"", type_name);
82493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		return NULL;
83493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	}
84493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
85493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	while (request_module("dm-exstore-%s", type_name_dup) ||
86493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	       !(type = _get_exception_store_type(type_name))) {
87493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		p = strrchr(type_name_dup, '-');
88493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		if (!p)
89493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow			break;
90493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		p[0] = '\0';
91493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	}
92493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
93493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (!type)
94493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		DMWARN("Module for exstore type \"%s\" not found.", type_name);
95493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
96493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	kfree(type_name_dup);
97493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
98493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	return type;
99493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow}
100493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
101493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowstatic void put_type(struct dm_exception_store_type *type)
102493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{
103493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	spin_lock(&_lock);
104493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	module_put(type->module);
105493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	spin_unlock(&_lock);
106493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow}
107493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
108493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowint dm_exception_store_type_register(struct dm_exception_store_type *type)
109493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{
110493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	int r = 0;
111493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
112493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	spin_lock(&_lock);
113493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (!__find_exception_store_type(type->name))
114493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		list_add(&type->list, &_exception_store_types);
115493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	else
116493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		r = -EEXIST;
117493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	spin_unlock(&_lock);
118493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
119493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	return r;
120493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow}
121493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_type_register);
122493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
123493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowint dm_exception_store_type_unregister(struct dm_exception_store_type *type)
124493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{
125493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	spin_lock(&_lock);
126493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
127493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (!__find_exception_store_type(type->name)) {
128493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		spin_unlock(&_lock);
129493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		return -EINVAL;
130493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	}
131493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
132493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	list_del(&type->list);
133493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
134493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	spin_unlock(&_lock);
135493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
136493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	return 0;
137493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow}
138493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_type_unregister);
139493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
1400cea9c78270cdf1d2ad74ce0e083d5555a0842e8Jonathan Brassowint dm_exception_store_create(const char *type_name, struct dm_target *ti,
141493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow			      struct dm_exception_store **store)
142493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{
143493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	int r = 0;
144493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	struct dm_exception_store_type *type;
145493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	struct dm_exception_store *tmp_store;
146493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
147493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL);
148493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (!tmp_store)
149493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		return -ENOMEM;
150493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
151493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	type = get_type(type_name);
152493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (!type) {
153493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		kfree(tmp_store);
154493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		return -EINVAL;
155493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	}
156493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
157493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	tmp_store->type = type;
1580cea9c78270cdf1d2ad74ce0e083d5555a0842e8Jonathan Brassow	tmp_store->ti = ti;
159493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
160493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	r = type->ctr(tmp_store, 0, NULL);
161493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	if (r) {
162493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		put_type(type);
163493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		kfree(tmp_store);
164493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow		return r;
165493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	}
166493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
167493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	*store = tmp_store;
168493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	return 0;
169493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow}
170493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_create);
171493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
172493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassowvoid dm_exception_store_destroy(struct dm_exception_store *store)
173493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow{
174493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	store->type->dtr(store);
175493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	put_type(store->type);
176493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow	kfree(store);
177493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow}
178493df71c6420b211a68ae82b889c1e8a5fe701beJonathan BrassowEXPORT_SYMBOL(dm_exception_store_destroy);
179493df71c6420b211a68ae82b889c1e8a5fe701beJonathan Brassow
1804db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonint dm_exception_store_init(void)
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int r;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1844db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon	r = dm_transient_snapshot_init();
1854db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon	if (r) {
1864db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon		DMERR("Unable to register transient exception store type.");
1874db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon		goto transient_fail;
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1904db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon	r = dm_persistent_snapshot_init();
1914db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon	if (r) {
1924db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon		DMERR("Unable to register persistent exception store type");
1934db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon		goto persistent_fail;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1984db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonpersistent_fail:
1994db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon	dm_persistent_snapshot_exit();
2004db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergontransient_fail:
2014db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon	return r;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2044db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergonvoid dm_exception_store_exit(void)
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2064db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon	dm_persistent_snapshot_exit();
2074db6bfe02bdc7dc5048f46dd682a94801d029adcAlasdair G Kergon	dm_transient_snapshot_exit();
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
209