0001
0002
0003
0004
0005
0006
0007
0008 #include "dm-exception-store.h"
0009
0010 #include <linux/ctype.h>
0011 #include <linux/mm.h>
0012 #include <linux/pagemap.h>
0013 #include <linux/vmalloc.h>
0014 #include <linux/module.h>
0015 #include <linux/slab.h>
0016
0017 #define DM_MSG_PREFIX "snapshot exception stores"
0018
0019 static LIST_HEAD(_exception_store_types);
0020 static DEFINE_SPINLOCK(_lock);
0021
0022 static struct dm_exception_store_type *__find_exception_store_type(const char *name)
0023 {
0024 struct dm_exception_store_type *type;
0025
0026 list_for_each_entry(type, &_exception_store_types, list)
0027 if (!strcmp(name, type->name))
0028 return type;
0029
0030 return NULL;
0031 }
0032
0033 static struct dm_exception_store_type *_get_exception_store_type(const char *name)
0034 {
0035 struct dm_exception_store_type *type;
0036
0037 spin_lock(&_lock);
0038
0039 type = __find_exception_store_type(name);
0040
0041 if (type && !try_module_get(type->module))
0042 type = NULL;
0043
0044 spin_unlock(&_lock);
0045
0046 return type;
0047 }
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 static struct dm_exception_store_type *get_type(const char *type_name)
0073 {
0074 char *p, *type_name_dup;
0075 struct dm_exception_store_type *type;
0076
0077 type = _get_exception_store_type(type_name);
0078 if (type)
0079 return type;
0080
0081 type_name_dup = kstrdup(type_name, GFP_KERNEL);
0082 if (!type_name_dup) {
0083 DMERR("No memory left to attempt load for \"%s\"", type_name);
0084 return NULL;
0085 }
0086
0087 while (request_module("dm-exstore-%s", type_name_dup) ||
0088 !(type = _get_exception_store_type(type_name))) {
0089 p = strrchr(type_name_dup, '-');
0090 if (!p)
0091 break;
0092 p[0] = '\0';
0093 }
0094
0095 if (!type)
0096 DMWARN("Module for exstore type \"%s\" not found.", type_name);
0097
0098 kfree(type_name_dup);
0099
0100 return type;
0101 }
0102
0103 static void put_type(struct dm_exception_store_type *type)
0104 {
0105 spin_lock(&_lock);
0106 module_put(type->module);
0107 spin_unlock(&_lock);
0108 }
0109
0110 int dm_exception_store_type_register(struct dm_exception_store_type *type)
0111 {
0112 int r = 0;
0113
0114 spin_lock(&_lock);
0115 if (!__find_exception_store_type(type->name))
0116 list_add(&type->list, &_exception_store_types);
0117 else
0118 r = -EEXIST;
0119 spin_unlock(&_lock);
0120
0121 return r;
0122 }
0123 EXPORT_SYMBOL(dm_exception_store_type_register);
0124
0125 int dm_exception_store_type_unregister(struct dm_exception_store_type *type)
0126 {
0127 spin_lock(&_lock);
0128
0129 if (!__find_exception_store_type(type->name)) {
0130 spin_unlock(&_lock);
0131 return -EINVAL;
0132 }
0133
0134 list_del(&type->list);
0135
0136 spin_unlock(&_lock);
0137
0138 return 0;
0139 }
0140 EXPORT_SYMBOL(dm_exception_store_type_unregister);
0141
0142 static int set_chunk_size(struct dm_exception_store *store,
0143 const char *chunk_size_arg, char **error)
0144 {
0145 unsigned chunk_size;
0146
0147 if (kstrtouint(chunk_size_arg, 10, &chunk_size)) {
0148 *error = "Invalid chunk size";
0149 return -EINVAL;
0150 }
0151
0152 if (!chunk_size) {
0153 store->chunk_size = store->chunk_mask = store->chunk_shift = 0;
0154 return 0;
0155 }
0156
0157 return dm_exception_store_set_chunk_size(store, chunk_size, error);
0158 }
0159
0160 int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
0161 unsigned chunk_size,
0162 char **error)
0163 {
0164
0165 if (!is_power_of_2(chunk_size)) {
0166 *error = "Chunk size is not a power of 2";
0167 return -EINVAL;
0168 }
0169
0170
0171 if (chunk_size %
0172 (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) ||
0173 chunk_size %
0174 (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) {
0175 *error = "Chunk size is not a multiple of device blocksize";
0176 return -EINVAL;
0177 }
0178
0179 if (chunk_size > INT_MAX >> SECTOR_SHIFT) {
0180 *error = "Chunk size is too high";
0181 return -EINVAL;
0182 }
0183
0184 store->chunk_size = chunk_size;
0185 store->chunk_mask = chunk_size - 1;
0186 store->chunk_shift = __ffs(chunk_size);
0187
0188 return 0;
0189 }
0190
0191 int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
0192 struct dm_snapshot *snap,
0193 unsigned *args_used,
0194 struct dm_exception_store **store)
0195 {
0196 int r = 0;
0197 struct dm_exception_store_type *type = NULL;
0198 struct dm_exception_store *tmp_store;
0199 char persistent;
0200
0201 if (argc < 2) {
0202 ti->error = "Insufficient exception store arguments";
0203 return -EINVAL;
0204 }
0205
0206 tmp_store = kzalloc(sizeof(*tmp_store), GFP_KERNEL);
0207 if (!tmp_store) {
0208 ti->error = "Exception store allocation failed";
0209 return -ENOMEM;
0210 }
0211
0212 persistent = toupper(*argv[0]);
0213 if (persistent == 'P')
0214 type = get_type("P");
0215 else if (persistent == 'N')
0216 type = get_type("N");
0217 else {
0218 ti->error = "Exception store type is not P or N";
0219 r = -EINVAL;
0220 goto bad_type;
0221 }
0222
0223 if (!type) {
0224 ti->error = "Exception store type not recognised";
0225 r = -EINVAL;
0226 goto bad_type;
0227 }
0228
0229 tmp_store->type = type;
0230 tmp_store->snap = snap;
0231
0232 r = set_chunk_size(tmp_store, argv[1], &ti->error);
0233 if (r)
0234 goto bad;
0235
0236 r = type->ctr(tmp_store, (strlen(argv[0]) > 1 ? &argv[0][1] : NULL));
0237 if (r) {
0238 ti->error = "Exception store type constructor failed";
0239 goto bad;
0240 }
0241
0242 *args_used = 2;
0243 *store = tmp_store;
0244 return 0;
0245
0246 bad:
0247 put_type(type);
0248 bad_type:
0249 kfree(tmp_store);
0250 return r;
0251 }
0252 EXPORT_SYMBOL(dm_exception_store_create);
0253
0254 void dm_exception_store_destroy(struct dm_exception_store *store)
0255 {
0256 store->type->dtr(store);
0257 put_type(store->type);
0258 kfree(store);
0259 }
0260 EXPORT_SYMBOL(dm_exception_store_destroy);
0261
0262 int dm_exception_store_init(void)
0263 {
0264 int r;
0265
0266 r = dm_transient_snapshot_init();
0267 if (r) {
0268 DMERR("Unable to register transient exception store type.");
0269 goto transient_fail;
0270 }
0271
0272 r = dm_persistent_snapshot_init();
0273 if (r) {
0274 DMERR("Unable to register persistent exception store type");
0275 goto persistent_fail;
0276 }
0277
0278 return 0;
0279
0280 persistent_fail:
0281 dm_transient_snapshot_exit();
0282 transient_fail:
0283 return r;
0284 }
0285
0286 void dm_exception_store_exit(void)
0287 {
0288 dm_persistent_snapshot_exit();
0289 dm_transient_snapshot_exit();
0290 }