root/drivers/md/dm-exception-store.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. __find_exception_store_type
  2. _get_exception_store_type
  3. get_type
  4. put_type
  5. dm_exception_store_type_register
  6. dm_exception_store_type_unregister
  7. set_chunk_size
  8. dm_exception_store_set_chunk_size
  9. dm_exception_store_create
  10. dm_exception_store_destroy
  11. dm_exception_store_init
  12. dm_exception_store_exit

   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 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 
 160 int 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);
 187 
 188         return 0;
 189 }
 190 
 191 int 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 = kzalloc(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 = "Exception store type 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, (strlen(argv[0]) > 1 ? &argv[0][1] : 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 
 246 bad:
 247         put_type(type);
 248 bad_type:
 249         kfree(tmp_store);
 250         return r;
 251 }
 252 EXPORT_SYMBOL(dm_exception_store_create);
 253 
 254 void dm_exception_store_destroy(struct dm_exception_store *store)
 255 {
 256         store->type->dtr(store);
 257         put_type(store->type);
 258         kfree(store);
 259 }
 260 EXPORT_SYMBOL(dm_exception_store_destroy);
 261 
 262 int 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 
 280 persistent_fail:
 281         dm_transient_snapshot_exit();
 282 transient_fail:
 283         return r;
 284 }
 285 
 286 void dm_exception_store_exit(void)
 287 {
 288         dm_persistent_snapshot_exit();
 289         dm_transient_snapshot_exit();
 290 }

/* [<][>][^][v][top][bottom][index][help] */