/[linux-patches]/genpatches-2.6/historical/2.6.10/4307_dm-mp-hw.patch
Gentoo

Contents of /genpatches-2.6/historical/2.6.10/4307_dm-mp-hw.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download) (as text)
Sat Jun 11 23:16:54 2005 UTC (15 years ago) by dsd
File MIME type: text/x-diff
File size: 13719 byte(s)
Import historical releases
1 Add hardware handler framework (udm1).
2 --- diff/drivers/md/Makefile 2004-11-10 15:11:11.000000000 +0000
3 +++ source/drivers/md/Makefile 2004-11-10 15:11:22.000000000 +0000
4 @@ -4,7 +4,7 @@
5
6 dm-mod-objs := dm.o dm-table.o dm-target.o dm-linear.o dm-stripe.o \
7 dm-ioctl.o dm-io.o kcopyd.o
8 -dm-multipath-objs := dm-path-selector.o dm-mpath.o
9 +dm-multipath-objs := dm-hw-handler.o dm-path-selector.o dm-mpath.o
10 dm-snapshot-objs := dm-snap.o dm-exception-store.o
11 dm-mirror-objs := dm-log.o dm-raid1.o
12 raid6-objs := raid6main.o raid6algos.o raid6recov.o raid6tables.o \
13 --- diff/drivers/md/dm-mpath.c 2004-11-10 15:08:19.000000000 +0000
14 +++ source/drivers/md/dm-mpath.c 2004-11-10 15:11:22.000000000 +0000
15 @@ -7,6 +7,7 @@
16
17 #include "dm.h"
18 #include "dm-path-selector.h"
19 +#include "dm-hw-handler.h"
20 #include "dm-bio-list.h"
21 #include "dm-bio-record.h"
22
23 @@ -52,8 +53,11 @@
24 struct list_head list;
25 struct dm_target *ti;
26
27 + struct hw_handler hw_handler;
28 +
29 unsigned nr_priority_groups;
30 struct list_head priority_groups;
31 + unsigned pg_init_required; /* pg_init needs calling? */
32 unsigned queue_io; /* Must we queue all I/O? */
33 unsigned queue_if_no_path; /* Queue I/O if last path fails? */
34
35 @@ -174,21 +178,36 @@
36 static void free_multipath(struct multipath *m)
37 {
38 struct priority_group *pg, *tmp;
39 + struct hw_handler *hwh = &m->hw_handler;
40
41 list_for_each_entry_safe (pg, tmp, &m->priority_groups, list) {
42 list_del(&pg->list);
43 free_priority_group(pg, m->ti);
44 }
45
46 + if (hwh->type) {
47 + hwh->type->dtr(hwh);
48 + dm_put_hw_handler(hwh->type);
49 + }
50 +
51 mempool_destroy(m->mpio_pool);
52 kfree(m);
53 }
54
55 static void __switch_pg(struct multipath *m, struct pgpath *pgpath)
56 {
57 + struct hw_handler *hwh = &m->hw_handler;
58 +
59 m->current_pg = pgpath->pg;
60
61 - m->queue_io = 0;
62 + /* Must we initialise the PG first, and queue I/O till it's ready? */
63 + if (hwh->type && hwh->type->pg_init) {
64 + m->pg_init_required = 1;
65 + m->queue_io = 1;
66 + } else {
67 + m->pg_init_required = 0;
68 + m->queue_io = 0;
69 + }
70 }
71
72 static void __choose_pgpath(struct multipath *m)
73 @@ -254,7 +273,7 @@
74 /* queue for the daemon to resubmit */
75 bio_list_add(&m->queued_ios, bio);
76 m->queue_size++;
77 - if (!m->queue_io)
78 + if (m->pg_init_required || !m->queue_io)
79 schedule_work(&m->process_queued_ios);
80 }
81
82 @@ -320,8 +339,9 @@
83 static void process_queued_ios(void *data)
84 {
85 struct multipath *m = (struct multipath *) data;
86 + struct hw_handler *hwh = &m->hw_handler;
87 struct pgpath *pgpath;
88 - unsigned must_queue = 0;
89 + unsigned init_required, must_queue = 0;
90 unsigned long flags;
91
92 spin_lock_irqsave(&m->lock, flags);
93 @@ -334,8 +354,15 @@
94 if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
95 must_queue = 1;
96
97 + init_required = m->pg_init_required;
98 + if (init_required)
99 + m->pg_init_required = 0;
100 +
101 spin_unlock_irqrestore(&m->lock, flags);
102
103 + if (init_required)
104 + hwh->type->pg_init(hwh, pgpath->pg->bypassed, &pgpath->path);
105 +
106 if (!must_queue)
107 dispatch_queued_ios(m);
108 }
109 @@ -354,6 +381,7 @@
110 /*-----------------------------------------------------------------
111 * Constructor/argument parsing:
112 * <num multipath feature args> [<arg>]*
113 + * <num hw_handler args> [hw_handler [<arg>]*]
114 * <num priority groups> [<selector> <num paths> <num selector args>
115 * [<path> [<arg>]* ]+ ]+
116 *---------------------------------------------------------------*/
117 @@ -520,6 +548,43 @@
118 return NULL;
119 }
120
121 +static int parse_hw_handler(struct arg_set *as, struct multipath *m,
122 + struct dm_target *ti)
123 +{
124 + int r;
125 + struct hw_handler_type *hwht;
126 + unsigned hw_argc;
127 +
128 + static struct param _params[] = {
129 + {0, 1024, ESTR("invalid number of hardware handler args")},
130 + };
131 +
132 + r = read_param(_params, shift(as), &hw_argc, &ti->error);
133 + if (r)
134 + return -EINVAL;
135 +
136 + if (!hw_argc)
137 + return 0;
138 +
139 + hwht = dm_get_hw_handler(shift(as));
140 + if (!hwht) {
141 + ti->error = ESTR("unknown hardware handler type");
142 + return -EINVAL;
143 + }
144 +
145 + r = hwht->ctr(&m->hw_handler, hw_argc - 1, as->argv);
146 + if (r) {
147 + dm_put_hw_handler(hwht);
148 + ti->error = ESTR("hardware handler constructor failed");
149 + return r;
150 + }
151 +
152 + m->hw_handler.type = hwht;
153 + consume(as, hw_argc - 1);
154 +
155 + return 0;
156 +}
157 +
158 static int parse_features(struct arg_set *as, struct multipath *m,
159 struct dm_target *ti)
160 {
161 @@ -570,6 +635,10 @@
162 if (r)
163 goto bad;
164
165 + r = parse_hw_handler(&as, m, ti);
166 + if (r)
167 + goto bad;
168 +
169 r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error);
170 if (r)
171 goto bad;
172 @@ -752,9 +821,41 @@
173 return -EINVAL;
174 }
175
176 +/*
177 + * pg_init must call this when it has completed its initialisation
178 + */
179 +void dm_pg_init_complete(struct path *path, unsigned err_flags)
180 +{
181 + struct pgpath *pgpath = path_to_pgpath(path);
182 + struct priority_group *pg = pgpath->pg;
183 + struct multipath *m = pg->m;
184 + unsigned long flags;
185 +
186 + /* We insist on failing the path if the PG is already bypassed. */
187 + if (err_flags && pg->bypassed)
188 + err_flags |= MP_FAIL_PATH;
189 +
190 + if (err_flags & MP_FAIL_PATH)
191 + fail_path(pgpath);
192 +
193 + if (err_flags & MP_BYPASS_PG)
194 + bypass_pg(m, pg, 1);
195 +
196 + spin_lock_irqsave(&m->lock, flags);
197 + if (!err_flags)
198 + m->queue_io = 0;
199 + else {
200 + m->current_pgpath = NULL;
201 + m->current_pg = NULL;
202 + }
203 + schedule_work(&m->process_queued_ios);
204 + spin_unlock_irqrestore(&m->lock, flags);
205 +}
206 +
207 static int do_end_io(struct multipath *m, struct bio *bio,
208 int error, struct mpath_io *mpio)
209 {
210 + struct hw_handler *hwh = &m->hw_handler;
211 unsigned err_flags = MP_FAIL_PATH; /* Default behavior */
212
213 if (error) {
214 @@ -765,6 +866,9 @@
215 }
216 spin_unlock(&m->lock);
217
218 + if (hwh->type && hwh->type->err)
219 + err_flags = hwh->type->err(hwh, bio);
220 +
221 if (err_flags & MP_FAIL_PATH)
222 fail_path(mpio->pgpath);
223
224 @@ -821,10 +925,12 @@
225 /*
226 * Info string has the following format:
227 * num_multipath_feature_args [multipath_feature_args]*
228 + * num_handler_status_args [handler_status_args]*
229 * num_groups [A|D|E num_paths num_selector_args [path_dev A|F fail_count [selector_args]* ]+ ]+
230 *
231 * Table string has the following format (identical to the constructor string):
232 * num_feature_args [features_args]*
233 + * num_handler_args hw_handler [hw_handler_args]*
234 * num_groups [priority selector-name num_paths num_selector_args [path_dev [selector_args]* ]+ ]+
235 */
236 static int multipath_status(struct dm_target *ti, status_type_t type,
237 @@ -833,6 +939,7 @@
238 int sz = 0;
239 unsigned long flags;
240 struct multipath *m = (struct multipath *) ti->private;
241 + struct hw_handler *hwh = &m->hw_handler;
242 struct priority_group *pg;
243 struct pgpath *p;
244 char buffer[32];
245 @@ -848,6 +955,13 @@
246 DMEMIT("0 ");
247 spin_unlock_irqrestore(&m->lock, flags);
248
249 + if (hwh->type && hwh->type->status)
250 + sz += hwh->type->status(hwh, type, result + sz, maxlen - sz);
251 + else if (!hwh->type || type == STATUSTYPE_INFO)
252 + DMEMIT("0 ");
253 + else
254 + DMEMIT("1 %s ", hwh->type->name);
255 +
256 DMEMIT("%u ", m->nr_priority_groups);
257
258 switch (type) {
259 --- diff/drivers/md/dm-hw-handler.c 1970-01-01 01:00:00.000000000 +0100
260 +++ source/drivers/md/dm-hw-handler.c 2004-11-10 15:11:22.000000000 +0000
261 @@ -0,0 +1,216 @@
262 +/*
263 + * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
264 + *
265 + * This file is released under the GPL.
266 + *
267 + * Multipath hardware handler registration.
268 + */
269 +
270 +#include "dm.h"
271 +#include "dm-hw-handler.h"
272 +
273 +#include <linux/slab.h>
274 +
275 +struct hwh_internal {
276 + struct hw_handler_type hwht;
277 +
278 + struct list_head list;
279 + long use;
280 +};
281 +
282 +#define hwht_to_hwhi(__hwht) container_of((__hwht), struct hwh_internal, hwht)
283 +
284 +static LIST_HEAD(_hw_handlers);
285 +static DECLARE_RWSEM(_hwh_lock);
286 +
287 +struct hwh_internal *__find_hw_handler_type(const char *name)
288 +{
289 + struct hwh_internal *hwhi;
290 +
291 + list_for_each_entry(hwhi, &_hw_handlers, list) {
292 + if (!strcmp(name, hwhi->hwht.name))
293 + return hwhi;
294 + }
295 +
296 + return NULL;
297 +}
298 +
299 +static struct hwh_internal *get_hw_handler(const char *name)
300 +{
301 + struct hwh_internal *hwhi;
302 +
303 + down_read(&_hwh_lock);
304 + hwhi = __find_hw_handler_type(name);
305 + if (hwhi) {
306 + if ((hwhi->use == 0) && !try_module_get(hwhi->hwht.module))
307 + hwhi = NULL;
308 + else
309 + hwhi->use++;
310 + }
311 + up_read(&_hwh_lock);
312 +
313 + return hwhi;
314 +}
315 +
316 +struct hw_handler_type *dm_get_hw_handler(const char *name)
317 +{
318 + struct hwh_internal *hwhi;
319 +
320 + if (!name)
321 + return NULL;
322 +
323 + hwhi = get_hw_handler(name);
324 + if (!hwhi) {
325 + request_module("dm-%s", name);
326 + hwhi = get_hw_handler(name);
327 + }
328 +
329 + return hwhi ? &hwhi->hwht : NULL;
330 +}
331 +
332 +void dm_put_hw_handler(struct hw_handler_type *hwht)
333 +{
334 + struct hwh_internal *hwhi;
335 +
336 + if (!hwht)
337 + return;
338 +
339 + down_read(&_hwh_lock);
340 + hwhi = __find_hw_handler_type(hwht->name);
341 + if (!hwhi)
342 + goto out;
343 +
344 + if (--hwhi->use == 0)
345 + module_put(hwhi->hwht.module);
346 +
347 + if (hwhi->use < 0)
348 + BUG();
349 +
350 + out:
351 + up_read(&_hwh_lock);
352 +}
353 +
354 +static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht)
355 +{
356 + struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL);
357 +
358 + if (hwhi) {
359 + memset(hwhi, 0, sizeof(*hwhi));
360 + hwhi->hwht = *hwht;
361 + }
362 +
363 + return hwhi;
364 +}
365 +
366 +int dm_register_hw_handler(struct hw_handler_type *hwht)
367 +{
368 + int r = 0;
369 + struct hwh_internal *hwhi = _alloc_hw_handler(hwht);
370 +
371 + if (!hwhi)
372 + return -ENOMEM;
373 +
374 + down_write(&_hwh_lock);
375 +
376 + if (__find_hw_handler_type(hwht->name)) {
377 + kfree(hwhi);
378 + r = -EEXIST;
379 + } else
380 + list_add(&hwhi->list, &_hw_handlers);
381 +
382 + up_write(&_hwh_lock);
383 +
384 + return r;
385 +}
386 +
387 +int dm_unregister_hw_handler(struct hw_handler_type *hwht)
388 +{
389 + struct hwh_internal *hwhi;
390 +
391 + down_write(&_hwh_lock);
392 +
393 + hwhi = __find_hw_handler_type(hwht->name);
394 + if (!hwhi) {
395 + up_write(&_hwh_lock);
396 + return -EINVAL;
397 + }
398 +
399 + if (hwhi->use) {
400 + up_write(&_hwh_lock);
401 + return -ETXTBSY;
402 + }
403 +
404 + list_del(&hwhi->list);
405 +
406 + up_write(&_hwh_lock);
407 +
408 + kfree(hwhi);
409 +
410 + return 0;
411 +}
412 +
413 +unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio)
414 +{
415 + int sense_key, asc, ascq;
416 +
417 +#if 0
418 + if (bio->bi_error & BIO_SENSE) {
419 + /* FIXME: This is just an initial guess. */
420 + /* key / asc / ascq */
421 + sense_key = (bio->bi_error >> 16) & 0xff;
422 + asc = (bio->bi_error >> 8) & 0xff;
423 + ascq = bio->bi_error & 0xff;
424 +
425 + switch (sense_key) {
426 + /* This block as a whole comes from the device.
427 + * So no point retrying on another path. */
428 + case 0x03: /* Medium error */
429 + case 0x05: /* Illegal request */
430 + case 0x07: /* Data protect */
431 + case 0x08: /* Blank check */
432 + case 0x0a: /* copy aborted */
433 + case 0x0c: /* obsolete - no clue ;-) */
434 + case 0x0d: /* volume overflow */
435 + case 0x0e: /* data miscompare */
436 + case 0x0f: /* reserved - no idea either. */
437 + return MP_ERROR_IO;
438 +
439 + /* For these errors it's unclear whether they
440 + * come from the device or the controller.
441 + * So just lets try a different path, and if
442 + * it eventually succeeds, user-space will clear
443 + * the paths again... */
444 + case 0x02: /* Not ready */
445 + case 0x04: /* Hardware error */
446 + case 0x09: /* vendor specific */
447 + case 0x0b: /* Aborted command */
448 + return MP_FAIL_PATH;
449 +
450 + case 0x06: /* Unit attention - might want to decode */
451 + if (asc == 0x04 && ascq == 0x01)
452 + /* "Unit in the process of
453 + * becoming ready" */
454 + return 0;
455 + return MP_FAIL_PATH;
456 +
457 + /* FIXME: For Unit Not Ready we may want
458 + * to have a generic pg activation
459 + * feature (START_UNIT). */
460 +
461 + /* Should these two ever end up in the
462 + * error path? I don't think so. */
463 + case 0x00: /* No sense */
464 + case 0x01: /* Recovered error */
465 + return 0;
466 + }
467 + }
468 +#endif
469 +
470 + /* We got no idea how to decode the other kinds of errors ->
471 + * assume generic error condition. */
472 + return MP_FAIL_PATH;
473 +}
474 +
475 +EXPORT_SYMBOL(dm_register_hw_handler);
476 +EXPORT_SYMBOL(dm_unregister_hw_handler);
477 +EXPORT_SYMBOL(dm_scsi_err_handler);
478 --- diff/drivers/md/dm-hw-handler.h 1970-01-01 01:00:00.000000000 +0100
479 +++ source/drivers/md/dm-hw-handler.h 2004-11-10 15:11:22.000000000 +0000
480 @@ -0,0 +1,68 @@
481 +/*
482 + * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
483 + *
484 + * This file is released under the GPL.
485 + *
486 + * Multipath hardware handler registration.
487 + */
488 +
489 +#ifndef DM_HW_HANDLER_H
490 +#define DM_HW_HANDLER_H
491 +
492 +#include <linux/device-mapper.h>
493 +
494 +#include "dm-mpath.h"
495 +
496 +struct hw_handler_type;
497 +struct hw_handler {
498 + struct hw_handler_type *type;
499 + void *context;
500 +};
501 +
502 +/*
503 + * Constructs a hardware handler object, takes custom arguments
504 + */
505 +typedef int (*hwh_ctr_fn) (struct hw_handler *hwh, unsigned arc, char **argv);
506 +typedef void (*hwh_dtr_fn) (struct hw_handler *hwh);
507 +
508 +typedef void (*hwh_pg_init_fn) (struct hw_handler *hwh, unsigned bypassed,
509 + struct path *path);
510 +typedef unsigned (*hwh_err_fn) (struct hw_handler *hwh, struct bio *bio);
511 +typedef int (*hwh_status_fn) (struct hw_handler *hwh,
512 + status_type_t type,
513 + char *result, unsigned int maxlen);
514 +
515 +/* Information about a hardware handler type */
516 +struct hw_handler_type {
517 + char *name;
518 + struct module *module;
519 +
520 + hwh_ctr_fn ctr;
521 + hwh_dtr_fn dtr;
522 +
523 + hwh_pg_init_fn pg_init;
524 + hwh_err_fn err;
525 + hwh_status_fn status;
526 +};
527 +
528 +/* Register a hardware handler */
529 +int dm_register_hw_handler(struct hw_handler_type *type);
530 +
531 +/* Unregister a hardware handler */
532 +int dm_unregister_hw_handler(struct hw_handler_type *type);
533 +
534 +/* Returns a registered hardware handler type */
535 +struct hw_handler_type *dm_get_hw_handler(const char *name);
536 +
537 +/* Releases a hardware handler */
538 +void dm_put_hw_handler(struct hw_handler_type *hwht);
539 +
540 +/* Default hwh_err_fn */
541 +unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio);
542 +
543 +/* Error flags for hwh_err_fn and dm_pg_init_complete */
544 +#define MP_FAIL_PATH 1
545 +#define MP_BYPASS_PG 2
546 +#define MP_ERROR_IO 4 /* Don't retry this I/O */
547 +
548 +#endif

  ViewVC Help
Powered by ViewVC 1.1.20