]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/patches/suse-2.6.27.25/patches.suse/dm-mpath-queue-length-load-balancing
Updated xen patches taken from suse.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.suse / dm-mpath-queue-length-load-balancing
1 From: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
2 Subject: dm-mpath: add queue-length dynamic load balancer
3 References: FATE#303862,FATE#302108
4
5 This patch adds a dynamic load balancer, dm-queue-length, which
6 balances the number of in-flight I/Os.
7
8 The code is based on the patch posted by Stefan Bader:
9 https://www.redhat.com/archives/dm-devel/2005-October/msg00050.html
10
11
12 Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
13 Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
14 Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
15 Signed-off-by: Hannes Reinecke <hare@suse.de>
16
17 Index: linux-2.6.27/drivers/md/Makefile
18 ===================================================================
19 --- linux-2.6.27.orig/drivers/md/Makefile
20 +++ linux-2.6.27/drivers/md/Makefile
21 @@ -32,7 +32,8 @@ obj-$(CONFIG_BLK_DEV_MD) += md-mod.o
22 obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o
23 obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
24 obj-$(CONFIG_DM_DELAY) += dm-delay.o
25 -obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o dm-least-pending.o
26 +obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o \
27 + dm-least-pending.o dm-queue-length.o
28 obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
29 obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-regions.o dm-log.o
30 obj-$(CONFIG_DM_RAID45) += dm-raid45.o dm-log.o dm-memcache.o \
31 Index: linux-2.6.27/drivers/md/dm-queue-length.c
32 ===================================================================
33 --- /dev/null
34 +++ linux-2.6.27/drivers/md/dm-queue-length.c
35 @@ -0,0 +1,257 @@
36 +/*
37 + * Copyright (C) 2004-2005 IBM Corp. All Rights Reserved.
38 + * Copyright (C) 2006-2008 NEC Corporation.
39 + *
40 + * dm-queue-length.c
41 + *
42 + * Module Author: Stefan Bader, IBM
43 + * Modified by: Kiyoshi Ueda, NEC
44 + *
45 + * This file is released under the GPL.
46 + *
47 + * Load balancing path selector.
48 + */
49 +
50 +#include "dm.h"
51 +#include "dm-path-selector.h"
52 +
53 +#include <linux/slab.h>
54 +#include <linux/ctype.h>
55 +#include <linux/errno.h>
56 +#include <linux/module.h>
57 +#include <asm/atomic.h>
58 +
59 +#define DM_MSG_PREFIX "multipath queue-length"
60 +#define QL_MIN_IO 128
61 +#define QL_VERSION "0.1.0"
62 +
63 +struct selector {
64 + struct list_head valid_paths;
65 + struct list_head failed_paths;
66 +};
67 +
68 +struct path_info {
69 + struct list_head list;
70 + struct dm_path *path;
71 + unsigned int repeat_count;
72 + atomic_t qlen;
73 +};
74 +
75 +static struct selector *alloc_selector(void)
76 +{
77 + struct selector *s = kzalloc(sizeof(*s), GFP_KERNEL);
78 +
79 + if (s) {
80 + INIT_LIST_HEAD(&s->valid_paths);
81 + INIT_LIST_HEAD(&s->failed_paths);
82 + }
83 +
84 + return s;
85 +}
86 +
87 +static int ql_create(struct path_selector *ps, unsigned argc, char **argv)
88 +{
89 + struct selector *s = alloc_selector();
90 +
91 + if (!s)
92 + return -ENOMEM;
93 +
94 + ps->context = s;
95 +
96 + return 0;
97 +}
98 +
99 +static void ql_free_paths(struct list_head *paths)
100 +{
101 + struct path_info *cpi, *npi;
102 +
103 + list_for_each_entry_safe(cpi, npi, paths, list) {
104 + list_del(&cpi->list);
105 + cpi->path->pscontext = NULL;
106 + kfree(cpi);
107 + }
108 +}
109 +
110 +static void ql_destroy(struct path_selector *ps)
111 +{
112 + struct selector *s = (struct selector *) ps->context;
113 +
114 + ql_free_paths(&s->valid_paths);
115 + ql_free_paths(&s->failed_paths);
116 + kfree(s);
117 + ps->context = NULL;
118 +}
119 +
120 +static int ql_add_path(struct path_selector *ps, struct dm_path *path,
121 + int argc, char **argv, char **error)
122 +{
123 + struct selector *s = (struct selector *) ps->context;
124 + struct path_info *pi;
125 + unsigned int repeat_count = QL_MIN_IO;
126 +
127 + /* Parse the arguments */
128 + if (argc > 1) {
129 + *error = "queue-length ps: incorrect number of arguments";
130 + return -EINVAL;
131 + }
132 +
133 + /* First path argument is number of I/Os before switching path. */
134 + if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
135 + *error = "queue-length ps: invalid repeat count";
136 + return -EINVAL;
137 + }
138 +
139 + /* Allocate the path information structure */
140 + pi = kmalloc(sizeof(*pi), GFP_KERNEL);
141 + if (!pi) {
142 + *error = "queue-length ps: Error allocating path information";
143 + return -ENOMEM;
144 + }
145 +
146 + pi->path = path;
147 + pi->repeat_count = repeat_count;
148 + atomic_set(&pi->qlen, 0);
149 + path->pscontext = pi;
150 +
151 + list_add_tail(&pi->list, &s->valid_paths);
152 +
153 + return 0;
154 +}
155 +
156 +static void ql_fail_path(struct path_selector *ps, struct dm_path *path)
157 +{
158 + struct selector *s = (struct selector *) ps->context;
159 + struct path_info *pi = path->pscontext;
160 +
161 + list_move(&pi->list, &s->failed_paths);
162 +}
163 +
164 +static int ql_reinstate_path(struct path_selector *ps, struct dm_path *path)
165 +{
166 + struct selector *s = (struct selector *) ps->context;
167 + struct path_info *pi = path->pscontext;
168 +
169 + list_move_tail(&pi->list, &s->valid_paths);
170 +
171 + return 0;
172 +}
173 +
174 +static inline int ql_compare_qlen(struct path_info *pi1, struct path_info *pi2)
175 +{
176 + return atomic_read(&pi1->qlen) - atomic_read(&pi2->qlen);
177 +}
178 +
179 +static struct dm_path *ql_select_path(struct path_selector *ps,
180 + unsigned *repeat_count)
181 +{
182 + struct selector *s = (struct selector *) ps->context;
183 + struct path_info *cpi = NULL, *spi = NULL;
184 +
185 + if (list_empty(&s->valid_paths))
186 + return NULL;
187 +
188 + /* Change preferred (first in list) path to evenly balance. */
189 + list_move_tail(s->valid_paths.next, &s->valid_paths);
190 +
191 + list_for_each_entry(cpi, &s->valid_paths, list) {
192 + if (!spi)
193 + spi = cpi;
194 + else if (ql_compare_qlen(cpi, spi) < 0)
195 + spi = cpi;
196 + }
197 +
198 + if (spi)
199 + *repeat_count = spi->repeat_count;
200 +
201 + return spi ? spi->path : NULL;
202 +}
203 +
204 +static int ql_start_io(struct path_selector *ps, struct dm_path *path)
205 +{
206 + struct path_info *pi = path->pscontext;
207 +
208 + atomic_inc(&pi->qlen);
209 +
210 + return 0;
211 +}
212 +
213 +static int ql_end_io(struct path_selector *ps, struct dm_path *path)
214 +{
215 + struct path_info *pi = path->pscontext;
216 +
217 + atomic_dec(&pi->qlen);
218 +
219 + return 0;
220 +}
221 +
222 +static int ql_status(struct path_selector *ps, struct dm_path *path,
223 + status_type_t type, char *result, unsigned int maxlen)
224 +{
225 + int sz = 0;
226 + struct path_info *pi;
227 +
228 + /* When called with (path == NULL), return selector status/args. */
229 + if (!path)
230 + DMEMIT("0 ");
231 + else {
232 + pi = path->pscontext;
233 +
234 + switch (type) {
235 + case STATUSTYPE_INFO:
236 + DMEMIT("%u ", atomic_read(&pi->qlen));
237 + break;
238 + case STATUSTYPE_TABLE:
239 + DMEMIT("%u ", pi->repeat_count);
240 + break;
241 + }
242 + }
243 +
244 + return sz;
245 +}
246 +
247 +static struct path_selector_type ql_ps = {
248 + .name = "queue-length",
249 + .module = THIS_MODULE,
250 + .table_args = 1,
251 + .info_args = 1,
252 + .create = ql_create,
253 + .destroy = ql_destroy,
254 + .status = ql_status,
255 + .add_path = ql_add_path,
256 + .fail_path = ql_fail_path,
257 + .reinstate_path = ql_reinstate_path,
258 + .select_path = ql_select_path,
259 + .start_io = ql_start_io,
260 + .end_io = ql_end_io,
261 +};
262 +
263 +static int __init dm_ql_init(void)
264 +{
265 + int r = dm_register_path_selector(&ql_ps);
266 +
267 + if (r < 0)
268 + DMERR("register failed %d", r);
269 +
270 + DMINFO("version " QL_VERSION " loaded");
271 +
272 + return r;
273 +}
274 +
275 +static void __exit dm_ql_exit(void)
276 +{
277 + int r = dm_unregister_path_selector(&ql_ps);
278 +
279 + if (r < 0)
280 + DMERR("unregister failed %d", r);
281 +}
282 +
283 +module_init(dm_ql_init);
284 +module_exit(dm_ql_exit);
285 +
286 +MODULE_AUTHOR("Stefan Bader <Stefan.Bader at de.ibm.com>");
287 +MODULE_DESCRIPTION(
288 + "(C) Copyright IBM Corp. 2004,2005 All Rights Reserved.\n"
289 + DM_NAME " load balancing path selector (dm-queue-length.c version "
290 + QL_VERSION ")"
291 +);
292 +MODULE_LICENSE("GPL");