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 19static LIST_HEAD(_exception_store_types); 20static DEFINE_SPINLOCK(_lock); 21 22static 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 33static 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 */ 72static 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 103static 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 110int 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} 123EXPORT_SYMBOL(dm_exception_store_type_register); 124 125int 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} 140EXPORT_SYMBOL(dm_exception_store_type_unregister); 141 142static int set_chunk_size(struct dm_exception_store *store, 143 const char *chunk_size_arg, char **error) 144{ 145 unsigned chunk_size; 146 147 if (kstrtouint(chunk_size_arg, 10, &chunk_size)) { 148 *error = "Invalid chunk size"; 149 return -EINVAL; 150 } 151 152 if (!chunk_size) { 153 store->chunk_size = store->chunk_mask = store->chunk_shift = 0; 154 return 0; 155 } 156 157 return dm_exception_store_set_chunk_size(store, chunk_size, error); 158} 159 160int dm_exception_store_set_chunk_size(struct dm_exception_store *store, 161 unsigned chunk_size, 162 char **error) 163{ 164 /* Check chunk_size is a power of 2 */ 165 if (!is_power_of_2(chunk_size)) { 166 *error = "Chunk size is not a power of 2"; 167 return -EINVAL; 168 } 169 170 /* Validate the chunk size against the device block size */ 171 if (chunk_size % 172 (bdev_logical_block_size(dm_snap_cow(store->snap)->bdev) >> 9) || 173 chunk_size % 174 (bdev_logical_block_size(dm_snap_origin(store->snap)->bdev) >> 9)) { 175 *error = "Chunk size is not a multiple of device blocksize"; 176 return -EINVAL; 177 } 178 179 if (chunk_size > INT_MAX >> SECTOR_SHIFT) { 180 *error = "Chunk size is too high"; 181 return -EINVAL; 182 } 183 184 store->chunk_size = chunk_size; 185 store->chunk_mask = chunk_size - 1; 186 store->chunk_shift = ffs(chunk_size) - 1; 187 188 return 0; 189} 190 191int dm_exception_store_create(struct dm_target *ti, int argc, char **argv, 192 struct dm_snapshot *snap, 193 unsigned *args_used, 194 struct dm_exception_store **store) 195{ 196 int r = 0; 197 struct dm_exception_store_type *type = NULL; 198 struct dm_exception_store *tmp_store; 199 char persistent; 200 201 if (argc < 2) { 202 ti->error = "Insufficient exception store arguments"; 203 return -EINVAL; 204 } 205 206 tmp_store = kmalloc(sizeof(*tmp_store), GFP_KERNEL); 207 if (!tmp_store) { 208 ti->error = "Exception store allocation failed"; 209 return -ENOMEM; 210 } 211 212 persistent = toupper(*argv[0]); 213 if (persistent == 'P') 214 type = get_type("P"); 215 else if (persistent == 'N') 216 type = get_type("N"); 217 else { 218 ti->error = "Persistent flag is not P or N"; 219 r = -EINVAL; 220 goto bad_type; 221 } 222 223 if (!type) { 224 ti->error = "Exception store type not recognised"; 225 r = -EINVAL; 226 goto bad_type; 227 } 228 229 tmp_store->type = type; 230 tmp_store->snap = snap; 231 232 r = set_chunk_size(tmp_store, argv[1], &ti->error); 233 if (r) 234 goto bad; 235 236 r = type->ctr(tmp_store, 0, NULL); 237 if (r) { 238 ti->error = "Exception store type constructor failed"; 239 goto bad; 240 } 241 242 *args_used = 2; 243 *store = tmp_store; 244 return 0; 245 246bad: 247 put_type(type); 248bad_type: 249 kfree(tmp_store); 250 return r; 251} 252EXPORT_SYMBOL(dm_exception_store_create); 253 254void dm_exception_store_destroy(struct dm_exception_store *store) 255{ 256 store->type->dtr(store); 257 put_type(store->type); 258 kfree(store); 259} 260EXPORT_SYMBOL(dm_exception_store_destroy); 261 262int dm_exception_store_init(void) 263{ 264 int r; 265 266 r = dm_transient_snapshot_init(); 267 if (r) { 268 DMERR("Unable to register transient exception store type."); 269 goto transient_fail; 270 } 271 272 r = dm_persistent_snapshot_init(); 273 if (r) { 274 DMERR("Unable to register persistent exception store type"); 275 goto persistent_fail; 276 } 277 278 return 0; 279 280persistent_fail: 281 dm_transient_snapshot_exit(); 282transient_fail: 283 return r; 284} 285 286void dm_exception_store_exit(void) 287{ 288 dm_persistent_snapshot_exit(); 289 dm_transient_snapshot_exit(); 290} 291