2 * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
4 * This file is released under the GPL.
6 * Multipath hardware handler registration.
10 #include "dm-hw-handler.h"
12 #include <linux/slab.h>
15 struct hw_handler_type hwht
;
17 struct list_head list
;
21 #define hwht_to_hwhi(__hwht) container_of((__hwht), struct hwh_internal, hwht)
23 static LIST_HEAD(_hw_handlers
);
24 static DECLARE_RWSEM(_hwh_lock
);
26 static struct hwh_internal
*__find_hw_handler_type(const char *name
)
28 struct hwh_internal
*hwhi
;
30 list_for_each_entry(hwhi
, &_hw_handlers
, list
) {
31 if (!strcmp(name
, hwhi
->hwht
.name
))
38 static struct hwh_internal
*get_hw_handler(const char *name
)
40 struct hwh_internal
*hwhi
;
42 down_read(&_hwh_lock
);
43 hwhi
= __find_hw_handler_type(name
);
45 if ((hwhi
->use
== 0) && !try_module_get(hwhi
->hwht
.module
))
55 struct hw_handler_type
*dm_get_hw_handler(const char *name
)
57 struct hwh_internal
*hwhi
;
62 hwhi
= get_hw_handler(name
);
64 request_module("dm-%s", name
);
65 hwhi
= get_hw_handler(name
);
68 return hwhi
? &hwhi
->hwht
: NULL
;
71 void dm_put_hw_handler(struct hw_handler_type
*hwht
)
73 struct hwh_internal
*hwhi
;
78 down_read(&_hwh_lock
);
79 hwhi
= __find_hw_handler_type(hwht
->name
);
84 module_put(hwhi
->hwht
.module
);
86 BUG_ON(hwhi
->use
< 0);
92 static struct hwh_internal
*_alloc_hw_handler(struct hw_handler_type
*hwht
)
94 struct hwh_internal
*hwhi
= kmalloc(sizeof(*hwhi
), GFP_KERNEL
);
97 memset(hwhi
, 0, sizeof(*hwhi
));
104 int dm_register_hw_handler(struct hw_handler_type
*hwht
)
107 struct hwh_internal
*hwhi
= _alloc_hw_handler(hwht
);
112 down_write(&_hwh_lock
);
114 if (__find_hw_handler_type(hwht
->name
)) {
118 list_add(&hwhi
->list
, &_hw_handlers
);
120 up_write(&_hwh_lock
);
125 int dm_unregister_hw_handler(struct hw_handler_type
*hwht
)
127 struct hwh_internal
*hwhi
;
129 down_write(&_hwh_lock
);
131 hwhi
= __find_hw_handler_type(hwht
->name
);
133 up_write(&_hwh_lock
);
138 up_write(&_hwh_lock
);
142 list_del(&hwhi
->list
);
144 up_write(&_hwh_lock
);
151 unsigned dm_scsi_err_handler(struct hw_handler
*hwh
, struct bio
*bio
)
154 int sense_key
, asc
, ascq
;
156 if (bio
->bi_error
& BIO_SENSE
) {
157 /* FIXME: This is just an initial guess. */
158 /* key / asc / ascq */
159 sense_key
= (bio
->bi_error
>> 16) & 0xff;
160 asc
= (bio
->bi_error
>> 8) & 0xff;
161 ascq
= bio
->bi_error
& 0xff;
164 /* This block as a whole comes from the device.
165 * So no point retrying on another path. */
166 case 0x03: /* Medium error */
167 case 0x05: /* Illegal request */
168 case 0x07: /* Data protect */
169 case 0x08: /* Blank check */
170 case 0x0a: /* copy aborted */
171 case 0x0c: /* obsolete - no clue ;-) */
172 case 0x0d: /* volume overflow */
173 case 0x0e: /* data miscompare */
174 case 0x0f: /* reserved - no idea either. */
177 /* For these errors it's unclear whether they
178 * come from the device or the controller.
179 * So just lets try a different path, and if
180 * it eventually succeeds, user-space will clear
181 * the paths again... */
182 case 0x02: /* Not ready */
183 case 0x04: /* Hardware error */
184 case 0x09: /* vendor specific */
185 case 0x0b: /* Aborted command */
188 case 0x06: /* Unit attention - might want to decode */
189 if (asc
== 0x04 && ascq
== 0x01)
190 /* "Unit in the process of
195 /* FIXME: For Unit Not Ready we may want
196 * to have a generic pg activation
197 * feature (START_UNIT). */
199 /* Should these two ever end up in the
200 * error path? I don't think so. */
201 case 0x00: /* No sense */
202 case 0x01: /* Recovered error */
208 /* We got no idea how to decode the other kinds of errors ->
209 * assume generic error condition. */
213 EXPORT_SYMBOL_GPL(dm_register_hw_handler
);
214 EXPORT_SYMBOL_GPL(dm_unregister_hw_handler
);
215 EXPORT_SYMBOL_GPL(dm_scsi_err_handler
);