cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dm-cache-policy.c (3698B)


      1/*
      2 * Copyright (C) 2012 Red Hat. All rights reserved.
      3 *
      4 * This file is released under the GPL.
      5 */
      6
      7#include "dm-cache-policy-internal.h"
      8#include "dm.h"
      9
     10#include <linux/module.h>
     11#include <linux/slab.h>
     12
     13/*----------------------------------------------------------------*/
     14
     15#define DM_MSG_PREFIX "cache-policy"
     16
     17static DEFINE_SPINLOCK(register_lock);
     18static LIST_HEAD(register_list);
     19
     20static struct dm_cache_policy_type *__find_policy(const char *name)
     21{
     22	struct dm_cache_policy_type *t;
     23
     24	list_for_each_entry(t, &register_list, list)
     25		if (!strcmp(t->name, name))
     26			return t;
     27
     28	return NULL;
     29}
     30
     31static struct dm_cache_policy_type *__get_policy_once(const char *name)
     32{
     33	struct dm_cache_policy_type *t = __find_policy(name);
     34
     35	if (t && !try_module_get(t->owner)) {
     36		DMWARN("couldn't get module %s", name);
     37		t = ERR_PTR(-EINVAL);
     38	}
     39
     40	return t;
     41}
     42
     43static struct dm_cache_policy_type *get_policy_once(const char *name)
     44{
     45	struct dm_cache_policy_type *t;
     46
     47	spin_lock(&register_lock);
     48	t = __get_policy_once(name);
     49	spin_unlock(&register_lock);
     50
     51	return t;
     52}
     53
     54static struct dm_cache_policy_type *get_policy(const char *name)
     55{
     56	struct dm_cache_policy_type *t;
     57
     58	t = get_policy_once(name);
     59	if (IS_ERR(t))
     60		return NULL;
     61
     62	if (t)
     63		return t;
     64
     65	request_module("dm-cache-%s", name);
     66
     67	t = get_policy_once(name);
     68	if (IS_ERR(t))
     69		return NULL;
     70
     71	return t;
     72}
     73
     74static void put_policy(struct dm_cache_policy_type *t)
     75{
     76	module_put(t->owner);
     77}
     78
     79int dm_cache_policy_register(struct dm_cache_policy_type *type)
     80{
     81	int r;
     82
     83	/* One size fits all for now */
     84	if (type->hint_size != 0 && type->hint_size != 4) {
     85		DMWARN("hint size must be 0 or 4 but %llu supplied.", (unsigned long long) type->hint_size);
     86		return -EINVAL;
     87	}
     88
     89	spin_lock(&register_lock);
     90	if (__find_policy(type->name)) {
     91		DMWARN("attempt to register policy under duplicate name %s", type->name);
     92		r = -EINVAL;
     93	} else {
     94		list_add(&type->list, &register_list);
     95		r = 0;
     96	}
     97	spin_unlock(&register_lock);
     98
     99	return r;
    100}
    101EXPORT_SYMBOL_GPL(dm_cache_policy_register);
    102
    103void dm_cache_policy_unregister(struct dm_cache_policy_type *type)
    104{
    105	spin_lock(&register_lock);
    106	list_del_init(&type->list);
    107	spin_unlock(&register_lock);
    108}
    109EXPORT_SYMBOL_GPL(dm_cache_policy_unregister);
    110
    111struct dm_cache_policy *dm_cache_policy_create(const char *name,
    112					       dm_cblock_t cache_size,
    113					       sector_t origin_size,
    114					       sector_t cache_block_size)
    115{
    116	struct dm_cache_policy *p = NULL;
    117	struct dm_cache_policy_type *type;
    118
    119	type = get_policy(name);
    120	if (!type) {
    121		DMWARN("unknown policy type");
    122		return ERR_PTR(-EINVAL);
    123	}
    124
    125	p = type->create(cache_size, origin_size, cache_block_size);
    126	if (!p) {
    127		put_policy(type);
    128		return ERR_PTR(-ENOMEM);
    129	}
    130	p->private = type;
    131
    132	return p;
    133}
    134EXPORT_SYMBOL_GPL(dm_cache_policy_create);
    135
    136void dm_cache_policy_destroy(struct dm_cache_policy *p)
    137{
    138	struct dm_cache_policy_type *t = p->private;
    139
    140	p->destroy(p);
    141	put_policy(t);
    142}
    143EXPORT_SYMBOL_GPL(dm_cache_policy_destroy);
    144
    145const char *dm_cache_policy_get_name(struct dm_cache_policy *p)
    146{
    147	struct dm_cache_policy_type *t = p->private;
    148
    149	/* if t->real is set then an alias was used (e.g. "default") */
    150	if (t->real)
    151		return t->real->name;
    152
    153	return t->name;
    154}
    155EXPORT_SYMBOL_GPL(dm_cache_policy_get_name);
    156
    157const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p)
    158{
    159	struct dm_cache_policy_type *t = p->private;
    160
    161	return t->version;
    162}
    163EXPORT_SYMBOL_GPL(dm_cache_policy_get_version);
    164
    165size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p)
    166{
    167	struct dm_cache_policy_type *t = p->private;
    168
    169	return t->hint_size;
    170}
    171EXPORT_SYMBOL_GPL(dm_cache_policy_get_hint_size);
    172
    173/*----------------------------------------------------------------*/