Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2012 Red Hat. All rights reserved.
0003  *
0004  * This file is released under the GPL.
0005  */
0006 
0007 #include "dm-cache-policy-internal.h"
0008 #include "dm.h"
0009 
0010 #include <linux/module.h>
0011 #include <linux/slab.h>
0012 
0013 /*----------------------------------------------------------------*/
0014 
0015 #define DM_MSG_PREFIX "cache-policy"
0016 
0017 static DEFINE_SPINLOCK(register_lock);
0018 static LIST_HEAD(register_list);
0019 
0020 static struct dm_cache_policy_type *__find_policy(const char *name)
0021 {
0022     struct dm_cache_policy_type *t;
0023 
0024     list_for_each_entry(t, &register_list, list)
0025         if (!strcmp(t->name, name))
0026             return t;
0027 
0028     return NULL;
0029 }
0030 
0031 static struct dm_cache_policy_type *__get_policy_once(const char *name)
0032 {
0033     struct dm_cache_policy_type *t = __find_policy(name);
0034 
0035     if (t && !try_module_get(t->owner)) {
0036         DMWARN("couldn't get module %s", name);
0037         t = ERR_PTR(-EINVAL);
0038     }
0039 
0040     return t;
0041 }
0042 
0043 static struct dm_cache_policy_type *get_policy_once(const char *name)
0044 {
0045     struct dm_cache_policy_type *t;
0046 
0047     spin_lock(&register_lock);
0048     t = __get_policy_once(name);
0049     spin_unlock(&register_lock);
0050 
0051     return t;
0052 }
0053 
0054 static struct dm_cache_policy_type *get_policy(const char *name)
0055 {
0056     struct dm_cache_policy_type *t;
0057 
0058     t = get_policy_once(name);
0059     if (IS_ERR(t))
0060         return NULL;
0061 
0062     if (t)
0063         return t;
0064 
0065     request_module("dm-cache-%s", name);
0066 
0067     t = get_policy_once(name);
0068     if (IS_ERR(t))
0069         return NULL;
0070 
0071     return t;
0072 }
0073 
0074 static void put_policy(struct dm_cache_policy_type *t)
0075 {
0076     module_put(t->owner);
0077 }
0078 
0079 int dm_cache_policy_register(struct dm_cache_policy_type *type)
0080 {
0081     int r;
0082 
0083     /* One size fits all for now */
0084     if (type->hint_size != 0 && type->hint_size != 4) {
0085         DMWARN("hint size must be 0 or 4 but %llu supplied.", (unsigned long long) type->hint_size);
0086         return -EINVAL;
0087     }
0088 
0089     spin_lock(&register_lock);
0090     if (__find_policy(type->name)) {
0091         DMWARN("attempt to register policy under duplicate name %s", type->name);
0092         r = -EINVAL;
0093     } else {
0094         list_add(&type->list, &register_list);
0095         r = 0;
0096     }
0097     spin_unlock(&register_lock);
0098 
0099     return r;
0100 }
0101 EXPORT_SYMBOL_GPL(dm_cache_policy_register);
0102 
0103 void dm_cache_policy_unregister(struct dm_cache_policy_type *type)
0104 {
0105     spin_lock(&register_lock);
0106     list_del_init(&type->list);
0107     spin_unlock(&register_lock);
0108 }
0109 EXPORT_SYMBOL_GPL(dm_cache_policy_unregister);
0110 
0111 struct dm_cache_policy *dm_cache_policy_create(const char *name,
0112                            dm_cblock_t cache_size,
0113                            sector_t origin_size,
0114                            sector_t cache_block_size)
0115 {
0116     struct dm_cache_policy *p = NULL;
0117     struct dm_cache_policy_type *type;
0118 
0119     type = get_policy(name);
0120     if (!type) {
0121         DMWARN("unknown policy type");
0122         return ERR_PTR(-EINVAL);
0123     }
0124 
0125     p = type->create(cache_size, origin_size, cache_block_size);
0126     if (!p) {
0127         put_policy(type);
0128         return ERR_PTR(-ENOMEM);
0129     }
0130     p->private = type;
0131 
0132     return p;
0133 }
0134 EXPORT_SYMBOL_GPL(dm_cache_policy_create);
0135 
0136 void dm_cache_policy_destroy(struct dm_cache_policy *p)
0137 {
0138     struct dm_cache_policy_type *t = p->private;
0139 
0140     p->destroy(p);
0141     put_policy(t);
0142 }
0143 EXPORT_SYMBOL_GPL(dm_cache_policy_destroy);
0144 
0145 const char *dm_cache_policy_get_name(struct dm_cache_policy *p)
0146 {
0147     struct dm_cache_policy_type *t = p->private;
0148 
0149     /* if t->real is set then an alias was used (e.g. "default") */
0150     if (t->real)
0151         return t->real->name;
0152 
0153     return t->name;
0154 }
0155 EXPORT_SYMBOL_GPL(dm_cache_policy_get_name);
0156 
0157 const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p)
0158 {
0159     struct dm_cache_policy_type *t = p->private;
0160 
0161     return t->version;
0162 }
0163 EXPORT_SYMBOL_GPL(dm_cache_policy_get_version);
0164 
0165 size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p)
0166 {
0167     struct dm_cache_policy_type *t = p->private;
0168 
0169     return t->hint_size;
0170 }
0171 EXPORT_SYMBOL_GPL(dm_cache_policy_get_hint_size);
0172 
0173 /*----------------------------------------------------------------*/