The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/drivers/md/dm-exception-store.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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) - 1;
  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 = 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 
  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 }

Cache object: 8876f479e53ac695e55d3b06e8d7ac7a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.