2 * Copyright (C) 2003 Sistina Software.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
5 * Module Author: Heinz Mauelshagen
7 * This file is released under the GPL.
9 * Round-robin path selector.
13 #include "dm-path-selector.h"
15 #include <linux/slab.h>
17 /*-----------------------------------------------------------------
18 * Path-handling code, paths are held in lists
19 *---------------------------------------------------------------*/
21 struct list_head list
;
23 unsigned repeat_count
;
26 static void free_paths(struct list_head
*paths
)
28 struct path_info
*pi
, *next
;
30 list_for_each_entry_safe(pi
, next
, paths
, list
) {
36 /*-----------------------------------------------------------------
37 * Round-robin selector
38 *---------------------------------------------------------------*/
40 #define RR_MIN_IO 1000
43 struct list_head valid_paths
;
44 struct list_head invalid_paths
;
47 static struct selector
*alloc_selector(void)
49 struct selector
*s
= kmalloc(sizeof(*s
), GFP_KERNEL
);
52 INIT_LIST_HEAD(&s
->valid_paths
);
53 INIT_LIST_HEAD(&s
->invalid_paths
);
59 static int rr_create(struct path_selector
*ps
, unsigned argc
, char **argv
)
71 static void rr_destroy(struct path_selector
*ps
)
73 struct selector
*s
= (struct selector
*) ps
->context
;
75 free_paths(&s
->valid_paths
);
76 free_paths(&s
->invalid_paths
);
81 static int rr_status(struct path_selector
*ps
, struct path
*path
,
82 status_type_t type
, char *result
, unsigned int maxlen
)
93 case STATUSTYPE_TABLE
:
95 DMEMIT("%u ", pi
->repeat_count
);
104 * Called during initialisation to register each path with an
105 * optional repeat_count.
107 static int rr_add_path(struct path_selector
*ps
, struct path
*path
,
108 int argc
, char **argv
, char **error
)
110 struct selector
*s
= (struct selector
*) ps
->context
;
111 struct path_info
*pi
;
112 unsigned repeat_count
= RR_MIN_IO
;
115 *error
= "round-robin ps: incorrect number of arguments";
119 /* First path argument is number of I/Os before switching path */
120 if ((argc
== 1) && (sscanf(argv
[0], "%u", &repeat_count
) != 1)) {
121 *error
= "round-robin ps: invalid repeat count";
125 /* allocate the path */
126 pi
= kmalloc(sizeof(*pi
), GFP_KERNEL
);
128 *error
= "round-robin ps: Error allocating path context";
133 pi
->repeat_count
= repeat_count
;
135 path
->pscontext
= pi
;
137 list_add(&pi
->list
, &s
->valid_paths
);
142 static void rr_fail_path(struct path_selector
*ps
, struct path
*p
)
144 struct selector
*s
= (struct selector
*) ps
->context
;
145 struct path_info
*pi
= p
->pscontext
;
147 list_move(&pi
->list
, &s
->invalid_paths
);
150 static int rr_reinstate_path(struct path_selector
*ps
, struct path
*p
)
152 struct selector
*s
= (struct selector
*) ps
->context
;
153 struct path_info
*pi
= p
->pscontext
;
155 list_move(&pi
->list
, &s
->valid_paths
);
160 static struct path
*rr_select_path(struct path_selector
*ps
,
161 unsigned *repeat_count
)
163 struct selector
*s
= (struct selector
*) ps
->context
;
164 struct path_info
*pi
= NULL
;
166 if (!list_empty(&s
->valid_paths
)) {
167 pi
= list_entry(s
->valid_paths
.next
, struct path_info
, list
);
168 list_move_tail(&pi
->list
, &s
->valid_paths
);
169 *repeat_count
= pi
->repeat_count
;
172 return pi
? pi
->path
: NULL
;
175 static struct path_selector_type rr_ps
= {
176 .name
= "round-robin",
177 .module
= THIS_MODULE
,
181 .destroy
= rr_destroy
,
183 .add_path
= rr_add_path
,
184 .fail_path
= rr_fail_path
,
185 .reinstate_path
= rr_reinstate_path
,
186 .select_path
= rr_select_path
,
189 static int __init
dm_rr_init(void)
191 int r
= dm_register_path_selector(&rr_ps
);
194 DMERR("round-robin: register failed %d", r
);
196 DMINFO("dm-round-robin version 1.0.0 loaded");
201 static void __exit
dm_rr_exit(void)
203 int r
= dm_unregister_path_selector(&rr_ps
);
206 DMERR("round-robin: unregister failed %d", r
);
209 module_init(dm_rr_init
);
210 module_exit(dm_rr_exit
);
212 MODULE_DESCRIPTION(DM_NAME
" round-robin multipath path selector");
213 MODULE_AUTHOR("Sistina Software <dm-devel@redhat.com>");
214 MODULE_LICENSE("GPL");