Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/md/dm-path-selector.c
15109 views
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
14
#include "dm-path-selector.h"
15
16
#include <linux/slab.h>
17
18
struct ps_internal {
19
struct path_selector_type pst;
20
struct list_head list;
21
};
22
23
#define pst_to_psi(__pst) container_of((__pst), struct ps_internal, pst)
24
25
static LIST_HEAD(_path_selectors);
26
static DECLARE_RWSEM(_ps_lock);
27
28
static struct ps_internal *__find_path_selector_type(const char *name)
29
{
30
struct ps_internal *psi;
31
32
list_for_each_entry(psi, &_path_selectors, list) {
33
if (!strcmp(name, psi->pst.name))
34
return psi;
35
}
36
37
return NULL;
38
}
39
40
static struct ps_internal *get_path_selector(const char *name)
41
{
42
struct ps_internal *psi;
43
44
down_read(&_ps_lock);
45
psi = __find_path_selector_type(name);
46
if (psi && !try_module_get(psi->pst.module))
47
psi = NULL;
48
up_read(&_ps_lock);
49
50
return psi;
51
}
52
53
struct path_selector_type *dm_get_path_selector(const char *name)
54
{
55
struct ps_internal *psi;
56
57
if (!name)
58
return NULL;
59
60
psi = get_path_selector(name);
61
if (!psi) {
62
request_module("dm-%s", name);
63
psi = get_path_selector(name);
64
}
65
66
return psi ? &psi->pst : NULL;
67
}
68
69
void dm_put_path_selector(struct path_selector_type *pst)
70
{
71
struct ps_internal *psi;
72
73
if (!pst)
74
return;
75
76
down_read(&_ps_lock);
77
psi = __find_path_selector_type(pst->name);
78
if (!psi)
79
goto out;
80
81
module_put(psi->pst.module);
82
out:
83
up_read(&_ps_lock);
84
}
85
86
static struct ps_internal *_alloc_path_selector(struct path_selector_type *pst)
87
{
88
struct ps_internal *psi = kzalloc(sizeof(*psi), GFP_KERNEL);
89
90
if (psi)
91
psi->pst = *pst;
92
93
return psi;
94
}
95
96
int dm_register_path_selector(struct path_selector_type *pst)
97
{
98
int r = 0;
99
struct ps_internal *psi = _alloc_path_selector(pst);
100
101
if (!psi)
102
return -ENOMEM;
103
104
down_write(&_ps_lock);
105
106
if (__find_path_selector_type(pst->name)) {
107
kfree(psi);
108
r = -EEXIST;
109
} else
110
list_add(&psi->list, &_path_selectors);
111
112
up_write(&_ps_lock);
113
114
return r;
115
}
116
117
int dm_unregister_path_selector(struct path_selector_type *pst)
118
{
119
struct ps_internal *psi;
120
121
down_write(&_ps_lock);
122
123
psi = __find_path_selector_type(pst->name);
124
if (!psi) {
125
up_write(&_ps_lock);
126
return -EINVAL;
127
}
128
129
list_del(&psi->list);
130
131
up_write(&_ps_lock);
132
133
kfree(psi);
134
135
return 0;
136
}
137
138
EXPORT_SYMBOL_GPL(dm_register_path_selector);
139
EXPORT_SYMBOL_GPL(dm_unregister_path_selector);
140
141