]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.suse/dm-mpath-leastpending-path-update
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / dm-mpath-leastpending-path-update
CommitLineData
2cb7cef9
BS
1Subject: Update least-pending-IO dynamic load balancer
2From: Hannes Reinecke <hare@suse.de>
3Date: Wed Jan 7 09:26:30 2009 +0100:
4References: bnc#444199
5
6Attached patch provides "Least pending IO" dynamic load balancing policy for
7bio based device mapper multipath. This load balancing policy considers the
8number of unserviced requests pending on a path and selects the path with least
9count for pending service request.
10
11We find this policy more useful especially when the SAN environment has
12heterogeneous components. Ex, when there is one 8GB HBA and one 2GB HBA
13connected to the same server, 8GB HBA could be utilized better with this
14algorithm.
15
16This patch includes the update as posted in the bugzilla,
17based on the review comments received in the dm-devel mailing list.
18
19Signed-off-by: Sakshi Chaitanya Veni <vsakshi@hp.com>
20Signed-off-by: Vijayakumar Balasubramanian <vijayakumar@hp.com>
21Signed-off-by: Senthil Kumar V <senthil-kumar.veluswamy@hp.com>
22Signed-off-by: Hannes Reinecke <hare@suse.de>
23
24diff --git a/drivers/md/Makefile b/drivers/md/Makefile
25index 42c35fb..24cfd6a 100644
26--- a/drivers/md/Makefile
27+++ b/drivers/md/Makefile
28@@ -32,7 +32,7 @@ obj-$(CONFIG_BLK_DEV_MD) += md-mod.o
29 obj-$(CONFIG_BLK_DEV_DM) += dm-mod.o
30 obj-$(CONFIG_DM_CRYPT) += dm-crypt.o
31 obj-$(CONFIG_DM_DELAY) += dm-delay.o
32-obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o
33+obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o dm-round-robin.o dm-least-pending.o
34 obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o
35 obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-regions.o dm-log.o
36 obj-$(CONFIG_DM_RAID45) += dm-raid45.o dm-log.o dm-memcache.o \
37diff --git a/drivers/md/dm-least-pending.c b/drivers/md/dm-least-pending.c
38new file mode 100644
39index 0000000..a7aea6d
40--- /dev/null
41+++ b/drivers/md/dm-least-pending.c
42@@ -0,0 +1,256 @@
43+/*
44+ * (C) Copyright 2008 Hewlett-Packard Development Company, L.P
45+ *
46+ * This file is released under the GPL.
47+ */
48+
49+#include "dm-path-selector.h"
50+
51+#include <linux/slab.h>
52+
53+#define DM_MSG_PREFIX "multipath least-pending"
54+
55+/*-----------------------------------------------------------------
56+* Path-handling code, paths are held in lists
57+*---------------------------------------------------------------*/
58+struct path_info {
59+ struct list_head list;
60+ struct dm_path *path;
61+ unsigned repeat_count;
62+ atomic_t io_count;
63+};
64+
65+static void free_paths(struct list_head *paths)
66+{
67+ struct path_info *pi, *next;
68+
69+ list_for_each_entry_safe(pi, next, paths, list) {
70+ list_del(&pi->list);
71+ kfree(pi);
72+ }
73+}
74+
75+/*-----------------------------------------------------------------
76+ * Least-pending selector
77+ *---------------------------------------------------------------*/
78+
79+#define LPP_MIN_IO 1
80+
81+struct selector {
82+ struct list_head valid_paths;
83+ struct list_head invalid_paths;
84+};
85+
86+static struct selector *alloc_selector(void)
87+{
88+ struct selector *s = kmalloc(sizeof(*s), GFP_KERNEL);
89+
90+ if (s) {
91+ INIT_LIST_HEAD(&s->valid_paths);
92+ INIT_LIST_HEAD(&s->invalid_paths);
93+ }
94+
95+ return s;
96+}
97+
98+static int lpp_create(struct path_selector *ps, unsigned argc, char **argv)
99+{
100+ struct selector *s;
101+
102+ s = alloc_selector();
103+ if (!s)
104+ return -ENOMEM;
105+
106+ ps->context = s;
107+ return 0;
108+}
109+
110+static void lpp_destroy(struct path_selector *ps)
111+{
112+ struct selector *s = ps->context;
113+
114+ free_paths(&s->valid_paths);
115+ free_paths(&s->invalid_paths);
116+ kfree(s);
117+ ps->context = NULL;
118+}
119+
120+static int lpp_status(struct path_selector *ps, struct dm_path *path,
121+ status_type_t type, char *result, unsigned int maxlen)
122+{
123+ struct path_info *pi;
124+ int sz = 0;
125+
126+ if (!path)
127+ switch (type) {
128+ case STATUSTYPE_INFO:
129+ DMEMIT("1 ");
130+ break;
131+ case STATUSTYPE_TABLE:
132+ DMEMIT("0 ");
133+ break;
134+ }
135+ else {
136+ pi = path->pscontext;
137+ switch (type) {
138+ case STATUSTYPE_INFO:
139+ DMEMIT("%u:%u ", pi->repeat_count,
140+ atomic_read(&pi->io_count));
141+ break;
142+ case STATUSTYPE_TABLE:
143+ break;
144+ }
145+ }
146+
147+ return sz;
148+}
149+
150+/*
151+ * Called during initialisation to register each path with an
152+ * optional repeat_count.
153+ */
154+static int lpp_add_path(struct path_selector *ps, struct dm_path *path,
155+ int argc, char **argv, char **error)
156+{
157+ struct selector *s = ps->context;
158+ struct path_info *pi;
159+ unsigned repeat_count = LPP_MIN_IO;
160+
161+ if (argc > 1) {
162+ *error = "least-pending ps: incorrect number of arguments";
163+ return -EINVAL;
164+ }
165+
166+ /* First path argument is number of I/Os before switching path */
167+ if ((argc == 1) && (sscanf(argv[0], "%u", &repeat_count) != 1)) {
168+ *error = "least-pending ps: invalid repeat count";
169+ return -EINVAL;
170+ }
171+
172+ /* allocate the path */
173+ pi = kmalloc(sizeof(*pi), GFP_KERNEL);
174+ if (!pi) {
175+ *error = "least-pending ps: Error allocating path context";
176+ return -ENOMEM;
177+ }
178+
179+ pi->path = path;
180+ pi->repeat_count = repeat_count;
181+ atomic_set(&pi->io_count, 0);
182+
183+ path->pscontext = pi;
184+
185+ list_add(&pi->list, &s->valid_paths);
186+
187+ return 0;
188+}
189+
190+static void lpp_fail_path(struct path_selector *ps, struct dm_path *p)
191+{
192+ struct selector *s = ps->context;
193+ struct path_info *pi = p->pscontext;
194+
195+ if (!pi)
196+ return;
197+
198+ atomic_set(&pi->io_count, 0);
199+
200+ list_move(&pi->list, &s->invalid_paths);
201+}
202+
203+static int lpp_reinstate_path(struct path_selector *ps, struct dm_path *p)
204+{
205+ struct selector *s = ps->context;
206+ struct path_info *pi = p->pscontext;
207+
208+ if (!pi)
209+ return 1;
210+
211+ list_move(&pi->list, &s->valid_paths);
212+
213+ return 0;
214+}
215+
216+static struct dm_path *lpp_select_path(struct path_selector *ps,
217+ unsigned *repeat_count)
218+{
219+ struct selector *s = ps->context;
220+ struct path_info *pi, *next, *least_io_path = NULL;
221+ struct list_head *paths;
222+
223+ if (list_empty(&s->valid_paths))
224+ return NULL;
225+
226+ paths = &s->valid_paths;
227+
228+ list_for_each_entry_safe(pi, next, paths, list) {
229+ if (!least_io_path || atomic_read(&least_io_path->io_count) < atomic_read(&pi->io_count))
230+ least_io_path = pi;
231+ if (!atomic_read(&least_io_path->io_count))
232+ break;
233+ }
234+
235+ if (!least_io_path)
236+ return NULL;
237+
238+ atomic_inc(&least_io_path->io_count);
239+ *repeat_count = pi->repeat_count;
240+
241+ return least_io_path->path;
242+}
243+
244+static int lpp_end_io(struct path_selector *ps, struct dm_path *path)
245+{
246+ struct path_info *pi = NULL;
247+
248+ pi = path->pscontext;
249+ if (!pi)
250+ return 1;
251+
252+ atomic_dec(&pi->io_count);
253+
254+ return 0;
255+}
256+
257+static struct path_selector_type lpp_ps = {
258+ .name = "least-pending",
259+ .module = THIS_MODULE,
260+ .table_args = 0,
261+ .info_args = 1,
262+ .create = lpp_create,
263+ .destroy = lpp_destroy,
264+ .status = lpp_status,
265+ .add_path = lpp_add_path,
266+ .fail_path = lpp_fail_path,
267+ .reinstate_path = lpp_reinstate_path,
268+ .select_path = lpp_select_path,
269+ .end_io = lpp_end_io,
270+};
271+
272+static int __init dm_lpp_init(void)
273+{
274+ int r = dm_register_path_selector(&lpp_ps);
275+
276+ if (r < 0)
277+ DMERR("register failed %d", r);
278+
279+ DMINFO("version 1.0.0 loaded");
280+
281+ return r;
282+}
283+
284+static void __exit dm_lpp_exit(void)
285+{
286+ int r = dm_unregister_path_selector(&lpp_ps);
287+
288+ if (r < 0)
289+ DMERR("unregister failed %d", r);
290+}
291+
292+module_init(dm_lpp_init);
293+module_exit(dm_lpp_exit);
294+
295+MODULE_DESCRIPTION(DM_NAME " least-pending multipath path selector");
296+MODULE_AUTHOR("Sakshi Chaitanya Veni <vsakshi@hp.com>");
297+MODULE_LICENSE("GPL");
298+