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