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