]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.31/patches.suse/dm-mpath-queue-length-load-balancing
Move xen patchset to new version's subdir.
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.31 / patches.suse / dm-mpath-queue-length-load-balancing
CommitLineData
00e5a55c
BS
1From: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
2Subject: dm-mpath: add queue-length dynamic load balancer
3References: FATE#303862,FATE#302108
4
5This patch adds a dynamic load balancer, dm-queue-length, which
6balances the number of in-flight I/Os.
7
8The code is based on the patch posted by Stefan Bader:
9https://www.redhat.com/archives/dm-devel/2005-October/msg00050.html
10
11
12Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
13Signed-off-by: Kiyoshi Ueda <k-ueda@ct.jp.nec.com>
14Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
15Signed-off-by: Hannes Reinecke <hare@suse.de>
16
17Index: 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 \
31Index: 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");