~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux-2.6.17/drivers/md/dm-hw-handler.c

Version: ~ [ 2.6.16 ] ~ [ 2.6.17 ] ~
Architecture: ~ [ ia64 ] ~ [ i386 ] ~ [ arm ] ~ [ ppc ] ~ [ sparc64 ] ~

  1 /*
  2  * Copyright (C) 2004 Red Hat, Inc. All rights reserved.
  3  *
  4  * This file is released under the GPL.
  5  *
  6  * Multipath hardware handler registration.
  7  */
  8 
  9 #include "dm.h"
 10 #include "dm-hw-handler.h"
 11 
 12 #include <linux/slab.h>
 13 
 14 struct hwh_internal {
 15         struct hw_handler_type hwht;
 16 
 17         struct list_head list;
 18         long use;
 19 };
 20 
 21 #define hwht_to_hwhi(__hwht) container_of((__hwht), struct hwh_internal, hwht)
 22 
 23 static LIST_HEAD(_hw_handlers);
 24 static DECLARE_RWSEM(_hwh_lock);
 25 
 26 static struct hwh_internal *__find_hw_handler_type(const char *name)
 27 {
 28         struct hwh_internal *hwhi;
 29 
 30         list_for_each_entry(hwhi, &_hw_handlers, list) {
 31                 if (!strcmp(name, hwhi->hwht.name))
 32                         return hwhi;
 33         }
 34 
 35         return NULL;
 36 }
 37 
 38 static struct hwh_internal *get_hw_handler(const char *name)
 39 {
 40         struct hwh_internal *hwhi;
 41 
 42         down_read(&_hwh_lock);
 43         hwhi = __find_hw_handler_type(name);
 44         if (hwhi) {
 45                 if ((hwhi->use == 0) && !try_module_get(hwhi->hwht.module))
 46                         hwhi = NULL;
 47                 else
 48                         hwhi->use++;
 49         }
 50         up_read(&_hwh_lock);
 51 
 52         return hwhi;
 53 }
 54 
 55 struct hw_handler_type *dm_get_hw_handler(const char *name)
 56 {
 57         struct hwh_internal *hwhi;
 58 
 59         if (!name)
 60                 return NULL;
 61 
 62         hwhi = get_hw_handler(name);
 63         if (!hwhi) {
 64                 request_module("dm-%s", name);
 65                 hwhi = get_hw_handler(name);
 66         }
 67 
 68         return hwhi ? &hwhi->hwht : NULL;
 69 }
 70 
 71 void dm_put_hw_handler(struct hw_handler_type *hwht)
 72 {
 73         struct hwh_internal *hwhi;
 74 
 75         if (!hwht)
 76                 return;
 77 
 78         down_read(&_hwh_lock);
 79         hwhi = __find_hw_handler_type(hwht->name);
 80         if (!hwhi)
 81                 goto out;
 82 
 83         if (--hwhi->use == 0)
 84                 module_put(hwhi->hwht.module);
 85 
 86         BUG_ON(hwhi->use < 0);
 87 
 88       out:
 89         up_read(&_hwh_lock);
 90 }
 91 
 92 static struct hwh_internal *_alloc_hw_handler(struct hw_handler_type *hwht)
 93 {
 94         struct hwh_internal *hwhi = kmalloc(sizeof(*hwhi), GFP_KERNEL);
 95 
 96         if (hwhi) {
 97                 memset(hwhi, 0, sizeof(*hwhi));
 98                 hwhi->hwht = *hwht;
 99         }
100 
101         return hwhi;
102 }
103 
104 int dm_register_hw_handler(struct hw_handler_type *hwht)
105 {
106         int r = 0;
107         struct hwh_internal *hwhi = _alloc_hw_handler(hwht);
108 
109         if (!hwhi)
110                 return -ENOMEM;
111 
112         down_write(&_hwh_lock);
113 
114         if (__find_hw_handler_type(hwht->name)) {
115                 kfree(hwhi);
116                 r = -EEXIST;
117         } else
118                 list_add(&hwhi->list, &_hw_handlers);
119 
120         up_write(&_hwh_lock);
121 
122         return r;
123 }
124 
125 int dm_unregister_hw_handler(struct hw_handler_type *hwht)
126 {
127         struct hwh_internal *hwhi;
128 
129         down_write(&_hwh_lock);
130 
131         hwhi = __find_hw_handler_type(hwht->name);
132         if (!hwhi) {
133                 up_write(&_hwh_lock);
134                 return -EINVAL;
135         }
136 
137         if (hwhi->use) {
138                 up_write(&_hwh_lock);
139                 return -ETXTBSY;
140         }
141 
142         list_del(&hwhi->list);
143 
144         up_write(&_hwh_lock);
145 
146         kfree(hwhi);
147 
148         return 0;
149 }
150 
151 unsigned dm_scsi_err_handler(struct hw_handler *hwh, struct bio *bio)
152 {
153 #if 0
154         int sense_key, asc, ascq;
155 
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;
162 
163                 switch (sense_key) {
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. */
175                         return MP_ERROR_IO;
176 
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 */
186                         return MP_FAIL_PATH;
187 
188                 case 0x06:      /* Unit attention - might want to decode */
189                         if (asc == 0x04 && ascq == 0x01)
190                                 /* "Unit in the process of
191                                  * becoming ready" */
192                                 return 0;
193                         return MP_FAIL_PATH;
194 
195                         /* FIXME: For Unit Not Ready we may want
196                          * to have a generic pg activation
197                          * feature (START_UNIT). */
198 
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 */
203                         return 0;
204                 }
205         }
206 #endif
207 
208         /* We got no idea how to decode the other kinds of errors ->
209          * assume generic error condition. */
210         return MP_FAIL_PATH;
211 }
212 
213 EXPORT_SYMBOL_GPL(dm_register_hw_handler);
214 EXPORT_SYMBOL_GPL(dm_unregister_hw_handler);
215 EXPORT_SYMBOL_GPL(dm_scsi_err_handler);
216 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.