/[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 - (hide annotations) (download) (as text)
Sat Jun 11 23:16:54 2005 UTC (15 years, 2 months ago) by dsd
File MIME type: text/x-diff
File size: 13719 byte(s)
Import historical releases
1 dsd 2 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