0001
0002
0003
0004
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, ®ister_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(®ister_lock);
0048 t = __get_policy_once(name);
0049 spin_unlock(®ister_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
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(®ister_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, ®ister_list);
0095 r = 0;
0096 }
0097 spin_unlock(®ister_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(®ister_lock);
0106 list_del_init(&type->list);
0107 spin_unlock(®ister_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
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