Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
md
dm-round-robin.c
Go to the documentation of this file.
1
/*
2
* Copyright (C) 2003 Sistina Software.
3
* Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
4
*
5
* Module Author: Heinz Mauelshagen
6
*
7
* This file is released under the GPL.
8
*
9
* Round-robin path selector.
10
*/
11
12
#include <
linux/device-mapper.h
>
13
14
#include "
dm-path-selector.h
"
15
16
#include <linux/slab.h>
17
#include <linux/module.h>
18
19
#define DM_MSG_PREFIX "multipath round-robin"
20
21
/*-----------------------------------------------------------------
22
* Path-handling code, paths are held in lists
23
*---------------------------------------------------------------*/
24
struct
path_info
{
25
struct
list_head
list;
26
struct
dm_path
*
path
;
27
unsigned
repeat_count
;
28
};
29
30
static
void
free_paths(
struct
list_head
*paths)
31
{
32
struct
path_info
*pi, *
next
;
33
34
list_for_each_entry_safe
(pi, next, paths,
list
) {
35
list_del
(&pi->
list
);
36
kfree
(pi);
37
}
38
}
39
40
/*-----------------------------------------------------------------
41
* Round-robin selector
42
*---------------------------------------------------------------*/
43
44
#define RR_MIN_IO 1000
45
46
struct
selector
{
47
struct
list_head
valid_paths;
48
struct
list_head
invalid_paths
;
49
};
50
51
static
struct
selector
*alloc_selector(
void
)
52
{
53
struct
selector
*
s
=
kmalloc
(
sizeof
(*s),
GFP_KERNEL
);
54
55
if
(s) {
56
INIT_LIST_HEAD(&s->
valid_paths
);
57
INIT_LIST_HEAD(&s->
invalid_paths
);
58
}
59
60
return
s
;
61
}
62
63
static
int
rr_create(
struct
path_selector
*
ps
,
unsigned
argc
,
char
**argv)
64
{
65
struct
selector
*
s
;
66
67
s = alloc_selector();
68
if
(!s)
69
return
-
ENOMEM
;
70
71
ps->
context
=
s
;
72
return
0;
73
}
74
75
static
void
rr_destroy(
struct
path_selector
*ps)
76
{
77
struct
selector
*s = (
struct
selector
*) ps->
context
;
78
79
free_paths(&s->
valid_paths
);
80
free_paths(&s->
invalid_paths
);
81
kfree
(s);
82
ps->
context
=
NULL
;
83
}
84
85
static
int
rr_status(
struct
path_selector
*ps,
struct
dm_path
*
path
,
86
status_type_t
type
,
char
*
result
,
unsigned
int
maxlen)
87
{
88
struct
path_info
*pi;
89
int
sz = 0;
90
91
if
(!path)
92
DMEMIT
(
"0 "
);
93
else
{
94
switch
(type) {
95
case
STATUSTYPE_INFO
:
96
break
;
97
case
STATUSTYPE_TABLE
:
98
pi = path->
pscontext
;
99
DMEMIT
(
"%u "
, pi->
repeat_count
);
100
break
;
101
}
102
}
103
104
return
sz;
105
}
106
107
/*
108
* Called during initialisation to register each path with an
109
* optional repeat_count.
110
*/
111
static
int
rr_add_path(
struct
path_selector
*ps,
struct
dm_path
*path,
112
int
argc,
char
**argv,
char
**
error
)
113
{
114
struct
selector
*s = (
struct
selector
*) ps->
context
;
115
struct
path_info
*pi;
116
unsigned
repeat_count =
RR_MIN_IO
;
117
char
dummy
;
118
119
if
(argc > 1) {
120
*error =
"round-robin ps: incorrect number of arguments"
;
121
return
-
EINVAL
;
122
}
123
124
/* First path argument is number of I/Os before switching path */
125
if
((argc == 1) && (
sscanf
(argv[0],
"%u%c"
, &repeat_count, &
dummy
) != 1)) {
126
*error =
"round-robin ps: invalid repeat count"
;
127
return
-
EINVAL
;
128
}
129
130
/* allocate the path */
131
pi =
kmalloc
(
sizeof
(*pi),
GFP_KERNEL
);
132
if
(!pi) {
133
*error =
"round-robin ps: Error allocating path context"
;
134
return
-
ENOMEM
;
135
}
136
137
pi->
path
=
path
;
138
pi->
repeat_count
= repeat_count;
139
140
path->
pscontext
= pi;
141
142
list_add_tail
(&pi->
list
, &s->
valid_paths
);
143
144
return
0;
145
}
146
147
static
void
rr_fail_path(
struct
path_selector
*ps,
struct
dm_path
*
p
)
148
{
149
struct
selector
*s = (
struct
selector
*) ps->
context
;
150
struct
path_info
*pi = p->
pscontext
;
151
152
list_move(&pi->
list
, &s->
invalid_paths
);
153
}
154
155
static
int
rr_reinstate_path(
struct
path_selector
*ps,
struct
dm_path
*p)
156
{
157
struct
selector
*s = (
struct
selector
*) ps->
context
;
158
struct
path_info
*pi = p->
pscontext
;
159
160
list_move(&pi->
list
, &s->
valid_paths
);
161
162
return
0;
163
}
164
165
static
struct
dm_path
*rr_select_path(
struct
path_selector
*ps,
166
unsigned
*repeat_count,
size_t
nr_bytes)
167
{
168
struct
selector
*s = (
struct
selector
*) ps->
context
;
169
struct
path_info
*pi =
NULL
;
170
171
if
(!list_empty(&s->
valid_paths
)) {
172
pi =
list_entry
(s->
valid_paths
.next,
struct
path_info
,
list
);
173
list_move_tail(&pi->
list
, &s->
valid_paths
);
174
*repeat_count = pi->
repeat_count
;
175
}
176
177
return
pi ? pi->
path
:
NULL
;
178
}
179
180
static
struct
path_selector_type
rr_ps = {
181
.name =
"round-robin"
,
182
.module =
THIS_MODULE
,
183
.table_args = 1,
184
.info_args = 0,
185
.create = rr_create,
186
.destroy = rr_destroy,
187
.status = rr_status,
188
.add_path = rr_add_path,
189
.fail_path = rr_fail_path,
190
.reinstate_path = rr_reinstate_path,
191
.select_path = rr_select_path,
192
};
193
194
static
int
__init
dm_rr_init(
void
)
195
{
196
int
r
=
dm_register_path_selector
(&rr_ps);
197
198
if
(r < 0)
199
DMERR
(
"register failed %d"
, r);
200
201
DMINFO
(
"version 1.0.0 loaded"
);
202
203
return
r
;
204
}
205
206
static
void
__exit
dm_rr_exit(
void
)
207
{
208
int
r =
dm_unregister_path_selector
(&rr_ps);
209
210
if
(r < 0)
211
DMERR
(
"unregister failed %d"
, r);
212
}
213
214
module_init
(dm_rr_init);
215
module_exit
(dm_rr_exit);
216
217
MODULE_DESCRIPTION
(
DM_NAME
" round-robin multipath path selector"
);
218
MODULE_AUTHOR
(
"Sistina Software <
[email protected]
>"
);
219
MODULE_LICENSE
(
"GPL"
);
Generated on Thu Jan 10 2013 13:43:48 for Linux Kernel by
1.8.2