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-path-selector.c (2499B)


      1/*
      2 * Copyright (C) 2003 Sistina Software.
      3 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
      4 *
      5 * Module Author: Heinz Mauelshagen
      6 *
      7 * This file is released under the GPL.
      8 *
      9 * Path selector registration.
     10 */
     11
     12#include <linux/device-mapper.h>
     13#include <linux/module.h>
     14
     15#include "dm-path-selector.h"
     16
     17#include <linux/slab.h>
     18
     19struct ps_internal {
     20	struct path_selector_type pst;
     21	struct list_head list;
     22};
     23
     24#define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)
     25
     26static LIST_HEAD(_path_selectors);
     27static DECLARE_RWSEM(_ps_lock);
     28
     29static struct ps_internal *__find_path_selector_type(const char *name)
     30{
     31	struct ps_internal *psi;
     32
     33	list_for_each_entry(psi, &_path_selectors, list) {
     34		if (!strcmp(name, psi->pst.name))
     35			return psi;
     36	}
     37
     38	return NULL;
     39}
     40
     41static struct ps_internal *get_path_selector(const char *name)
     42{
     43	struct ps_internal *psi;
     44
     45	down_read(&_ps_lock);
     46	psi = __find_path_selector_type(name);
     47	if (psi && !try_module_get(psi->pst.module))
     48		psi = NULL;
     49	up_read(&_ps_lock);
     50
     51	return psi;
     52}
     53
     54struct path_selector_type *dm_get_path_selector(const char *name)
     55{
     56	struct ps_internal *psi;
     57
     58	if (!name)
     59		return NULL;
     60
     61	psi = get_path_selector(name);
     62	if (!psi) {
     63		request_module("dm-%s", name);
     64		psi = get_path_selector(name);
     65	}
     66
     67	return psi ? &psi->pst : NULL;
     68}
     69
     70void dm_put_path_selector(struct path_selector_type *pst)
     71{
     72	struct ps_internal *psi;
     73
     74	if (!pst)
     75		return;
     76
     77	down_read(&_ps_lock);
     78	psi = __find_path_selector_type(pst->name);
     79	if (!psi)
     80		goto out;
     81
     82	module_put(psi->pst.module);
     83out:
     84	up_read(&_ps_lock);
     85}
     86
     87static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)
     88{
     89	struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL);
     90
     91	if (psi)
     92		psi->pst = *pst;
     93
     94	return psi;
     95}
     96
     97int dm_register_path_selector(struct path_selector_type *pst)
     98{
     99	int r = 0;
    100	struct ps_internal *psi = _alloc_path_selector(pst);
    101
    102	if (!psi)
    103		return -ENOMEM;
    104
    105	down_write(&_ps_lock);
    106
    107	if (__find_path_selector_type(pst->name)) {
    108		kfree(psi);
    109		r = -EEXIST;
    110	} else
    111		list_add(&psi->list, &_path_selectors);
    112
    113	up_write(&_ps_lock);
    114
    115	return r;
    116}
    117
    118int dm_unregister_path_selector(struct path_selector_type *pst)
    119{
    120	struct ps_internal *psi;
    121
    122	down_write(&_ps_lock);
    123
    124	psi = __find_path_selector_type(pst->name);
    125	if (!psi) {
    126		up_write(&_ps_lock);
    127		return -EINVAL;
    128	}
    129
    130	list_del(&psi->list);
    131
    132	up_write(&_ps_lock);
    133
    134	kfree(psi);
    135
    136	return 0;
    137}
    138
    139EXPORT_SYMBOL_GPL(dm_register_path_selector);
    140EXPORT_SYMBOL_GPL(dm_unregister_path_selector);