Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2001-2002 Sistina Software (UK) Limited.
0003  * Copyright (C) 2006-2008 Red Hat GmbH
0004  *
0005  * This file is released under the GPL.
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  * get_type
0051  * @type_name
0052  *
0053  * Attempt to retrieve the dm_exception_store_type by name.  If not already
0054  * available, attempt to load the appropriate module.
0055  *
0056  * Exstore modules are named "dm-exstore-" followed by the 'type_name'.
0057  * Modules may contain multiple types.
0058  * This function will first try the module "dm-exstore-<type_name>",
0059  * then truncate 'type_name' on the last '-' and try again.
0060  *
0061  * For example, if type_name was "clustered-shared", it would search
0062  * 'dm-exstore-clustered-shared' then 'dm-exstore-clustered'.
0063  *
0064  * 'dm-exception-store-<type_name>' is too long of a name in my
0065  * opinion, which is why I've chosen to have the files
0066  * containing exception store implementations be 'dm-exstore-<type_name>'.
0067  * If you want your module to be autoloaded, you will follow this
0068  * naming convention.
0069  *
0070  * Returns: dm_exception_store_type* on success, NULL on failure
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     /* Check chunk_size is a power of 2 */
0165     if (!is_power_of_2(chunk_size)) {
0166         *error = "Chunk size is not a power of 2";
0167         return -EINVAL;
0168     }
0169 
0170     /* Validate the chunk size against the device block size */
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 }