diff options
-rw-r--r-- | drivers/scsi/raid_class.c | 96 | ||||
-rw-r--r-- | include/linux/raid_class.h | 32 |
2 files changed, 98 insertions, 30 deletions
diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index f1ea5027865f..a9f99c68556f 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c | |||
@@ -1,5 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * RAID Attributes | 2 | * raid_class.c - implementation of a simple raid visualisation class |
3 | * | ||
4 | * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com> | ||
5 | * | ||
6 | * This file is licensed under GPLv2 | ||
7 | * | ||
8 | * This class is designed to allow raid attributes to be visualised and | ||
9 | * manipulated in a form independent of the underlying raid. Ultimately this | ||
10 | * should work for both hardware and software raids. | ||
3 | */ | 11 | */ |
4 | #include <linux/init.h> | 12 | #include <linux/init.h> |
5 | #include <linux/module.h> | 13 | #include <linux/module.h> |
@@ -22,7 +30,7 @@ struct raid_internal { | |||
22 | 30 | ||
23 | struct raid_component { | 31 | struct raid_component { |
24 | struct list_head node; | 32 | struct list_head node; |
25 | struct device *dev; | 33 | struct class_device cdev; |
26 | int num; | 34 | int num; |
27 | }; | 35 | }; |
28 | 36 | ||
@@ -72,11 +80,10 @@ static int raid_setup(struct transport_container *tc, struct device *dev, | |||
72 | 80 | ||
73 | BUG_ON(class_get_devdata(cdev)); | 81 | BUG_ON(class_get_devdata(cdev)); |
74 | 82 | ||
75 | rd = kmalloc(sizeof(*rd), GFP_KERNEL); | 83 | rd = kzalloc(sizeof(*rd), GFP_KERNEL); |
76 | if (!rd) | 84 | if (!rd) |
77 | return -ENOMEM; | 85 | return -ENOMEM; |
78 | 86 | ||
79 | memset(rd, 0, sizeof(*rd)); | ||
80 | INIT_LIST_HEAD(&rd->component_list); | 87 | INIT_LIST_HEAD(&rd->component_list); |
81 | class_set_devdata(cdev, rd); | 88 | class_set_devdata(cdev, rd); |
82 | 89 | ||
@@ -88,15 +95,15 @@ static int raid_remove(struct transport_container *tc, struct device *dev, | |||
88 | { | 95 | { |
89 | struct raid_data *rd = class_get_devdata(cdev); | 96 | struct raid_data *rd = class_get_devdata(cdev); |
90 | struct raid_component *rc, *next; | 97 | struct raid_component *rc, *next; |
98 | dev_printk(KERN_ERR, dev, "RAID REMOVE\n"); | ||
91 | class_set_devdata(cdev, NULL); | 99 | class_set_devdata(cdev, NULL); |
92 | list_for_each_entry_safe(rc, next, &rd->component_list, node) { | 100 | list_for_each_entry_safe(rc, next, &rd->component_list, node) { |
93 | char buf[40]; | ||
94 | snprintf(buf, sizeof(buf), "component-%d", rc->num); | ||
95 | list_del(&rc->node); | 101 | list_del(&rc->node); |
96 | sysfs_remove_link(&cdev->kobj, buf); | 102 | dev_printk(KERN_ERR, rc->cdev.dev, "RAID COMPONENT REMOVE\n"); |
97 | kfree(rc); | 103 | class_device_unregister(&rc->cdev); |
98 | } | 104 | } |
99 | kfree(class_get_devdata(cdev)); | 105 | dev_printk(KERN_ERR, dev, "RAID REMOVE DONE\n"); |
106 | kfree(rd); | ||
100 | return 0; | 107 | return 0; |
101 | } | 108 | } |
102 | 109 | ||
@@ -110,10 +117,11 @@ static struct { | |||
110 | enum raid_state value; | 117 | enum raid_state value; |
111 | char *name; | 118 | char *name; |
112 | } raid_states[] = { | 119 | } raid_states[] = { |
113 | { RAID_ACTIVE, "active" }, | 120 | { RAID_STATE_UNKNOWN, "unknown" }, |
114 | { RAID_DEGRADED, "degraded" }, | 121 | { RAID_STATE_ACTIVE, "active" }, |
115 | { RAID_RESYNCING, "resyncing" }, | 122 | { RAID_STATE_DEGRADED, "degraded" }, |
116 | { RAID_OFFLINE, "offline" }, | 123 | { RAID_STATE_RESYNCING, "resyncing" }, |
124 | { RAID_STATE_OFFLINE, "offline" }, | ||
117 | }; | 125 | }; |
118 | 126 | ||
119 | static const char *raid_state_name(enum raid_state state) | 127 | static const char *raid_state_name(enum raid_state state) |
@@ -130,6 +138,33 @@ static const char *raid_state_name(enum raid_state state) | |||
130 | return name; | 138 | return name; |
131 | } | 139 | } |
132 | 140 | ||
141 | static struct { | ||
142 | enum raid_level value; | ||
143 | char *name; | ||
144 | } raid_levels[] = { | ||
145 | { RAID_LEVEL_UNKNOWN, "unknown" }, | ||
146 | { RAID_LEVEL_LINEAR, "linear" }, | ||
147 | { RAID_LEVEL_0, "raid0" }, | ||
148 | { RAID_LEVEL_1, "raid1" }, | ||
149 | { RAID_LEVEL_3, "raid3" }, | ||
150 | { RAID_LEVEL_4, "raid4" }, | ||
151 | { RAID_LEVEL_5, "raid5" }, | ||
152 | { RAID_LEVEL_6, "raid6" }, | ||
153 | }; | ||
154 | |||
155 | static const char *raid_level_name(enum raid_level level) | ||
156 | { | ||
157 | int i; | ||
158 | char *name = NULL; | ||
159 | |||
160 | for (i = 0; i < sizeof(raid_levels)/sizeof(raid_levels[0]); i++) { | ||
161 | if (raid_levels[i].value == level) { | ||
162 | name = raid_levels[i].name; | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | return name; | ||
167 | } | ||
133 | 168 | ||
134 | #define raid_attr_show_internal(attr, fmt, var, code) \ | 169 | #define raid_attr_show_internal(attr, fmt, var, code) \ |
135 | static ssize_t raid_show_##attr(struct class_device *cdev, char *buf) \ | 170 | static ssize_t raid_show_##attr(struct class_device *cdev, char *buf) \ |
@@ -159,11 +194,22 @@ static CLASS_DEVICE_ATTR(attr, S_IRUGO, raid_show_##attr, NULL) | |||
159 | 194 | ||
160 | #define raid_attr_ro(attr) raid_attr_ro_internal(attr, ) | 195 | #define raid_attr_ro(attr) raid_attr_ro_internal(attr, ) |
161 | #define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr)) | 196 | #define raid_attr_ro_fn(attr) raid_attr_ro_internal(attr, ATTR_CODE(attr)) |
162 | #define raid_attr_ro_state(attr) raid_attr_ro_states(attr, attr, ATTR_CODE(attr)) | 197 | #define raid_attr_ro_state(attr) raid_attr_ro_states(attr, attr, ) |
198 | #define raid_attr_ro_state_fn(attr) raid_attr_ro_states(attr, attr, ATTR_CODE(attr)) | ||
199 | |||
163 | 200 | ||
164 | raid_attr_ro(level); | 201 | raid_attr_ro_state(level); |
165 | raid_attr_ro_fn(resync); | 202 | raid_attr_ro_fn(resync); |
166 | raid_attr_ro_state(state); | 203 | raid_attr_ro_state_fn(state); |
204 | |||
205 | static void raid_component_release(struct class_device *cdev) | ||
206 | { | ||
207 | struct raid_component *rc = container_of(cdev, struct raid_component, | ||
208 | cdev); | ||
209 | dev_printk(KERN_ERR, rc->cdev.dev, "COMPONENT RELEASE\n"); | ||
210 | put_device(rc->cdev.dev); | ||
211 | kfree(rc); | ||
212 | } | ||
167 | 213 | ||
168 | void raid_component_add(struct raid_template *r,struct device *raid_dev, | 214 | void raid_component_add(struct raid_template *r,struct device *raid_dev, |
169 | struct device *component_dev) | 215 | struct device *component_dev) |
@@ -173,34 +219,36 @@ void raid_component_add(struct raid_template *r,struct device *raid_dev, | |||
173 | raid_dev); | 219 | raid_dev); |
174 | struct raid_component *rc; | 220 | struct raid_component *rc; |
175 | struct raid_data *rd = class_get_devdata(cdev); | 221 | struct raid_data *rd = class_get_devdata(cdev); |
176 | char buf[40]; | ||
177 | 222 | ||
178 | rc = kmalloc(sizeof(*rc), GFP_KERNEL); | 223 | rc = kzalloc(sizeof(*rc), GFP_KERNEL); |
179 | if (!rc) | 224 | if (!rc) |
180 | return; | 225 | return; |
181 | 226 | ||
182 | INIT_LIST_HEAD(&rc->node); | 227 | INIT_LIST_HEAD(&rc->node); |
183 | rc->dev = component_dev; | 228 | class_device_initialize(&rc->cdev); |
229 | rc->cdev.release = raid_component_release; | ||
230 | rc->cdev.dev = get_device(component_dev); | ||
184 | rc->num = rd->component_count++; | 231 | rc->num = rd->component_count++; |
185 | 232 | ||
186 | snprintf(buf, sizeof(buf), "component-%d", rc->num); | 233 | snprintf(rc->cdev.class_id, sizeof(rc->cdev.class_id), |
234 | "component-%d", rc->num); | ||
187 | list_add_tail(&rc->node, &rd->component_list); | 235 | list_add_tail(&rc->node, &rd->component_list); |
188 | sysfs_create_link(&cdev->kobj, &component_dev->kobj, buf); | 236 | rc->cdev.parent = cdev; |
237 | rc->cdev.class = &raid_class.class; | ||
238 | class_device_add(&rc->cdev); | ||
189 | } | 239 | } |
190 | EXPORT_SYMBOL(raid_component_add); | 240 | EXPORT_SYMBOL(raid_component_add); |
191 | 241 | ||
192 | struct raid_template * | 242 | struct raid_template * |
193 | raid_class_attach(struct raid_function_template *ft) | 243 | raid_class_attach(struct raid_function_template *ft) |
194 | { | 244 | { |
195 | struct raid_internal *i = kmalloc(sizeof(struct raid_internal), | 245 | struct raid_internal *i = kzalloc(sizeof(struct raid_internal), |
196 | GFP_KERNEL); | 246 | GFP_KERNEL); |
197 | int count = 0; | 247 | int count = 0; |
198 | 248 | ||
199 | if (unlikely(!i)) | 249 | if (unlikely(!i)) |
200 | return NULL; | 250 | return NULL; |
201 | 251 | ||
202 | memset(i, 0, sizeof(*i)); | ||
203 | |||
204 | i->f = ft; | 252 | i->f = ft; |
205 | 253 | ||
206 | i->r.raid_attrs.ac.class = &raid_class.class; | 254 | i->r.raid_attrs.ac.class = &raid_class.class; |
diff --git a/include/linux/raid_class.h b/include/linux/raid_class.h index a71123c28272..48831eac2910 100644 --- a/include/linux/raid_class.h +++ b/include/linux/raid_class.h | |||
@@ -1,4 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * raid_class.h - a generic raid visualisation class | ||
3 | * | ||
4 | * Copyright (c) 2005 - James Bottomley <James.Bottomley@steeleye.com> | ||
5 | * | ||
6 | * This file is licensed under GPLv2 | ||
2 | */ | 7 | */ |
3 | #include <linux/transport_class.h> | 8 | #include <linux/transport_class.h> |
4 | 9 | ||
@@ -14,20 +19,35 @@ struct raid_function_template { | |||
14 | }; | 19 | }; |
15 | 20 | ||
16 | enum raid_state { | 21 | enum raid_state { |
17 | RAID_ACTIVE = 1, | 22 | RAID_STATE_UNKNOWN = 0, |
18 | RAID_DEGRADED, | 23 | RAID_STATE_ACTIVE, |
19 | RAID_RESYNCING, | 24 | RAID_STATE_DEGRADED, |
20 | RAID_OFFLINE, | 25 | RAID_STATE_RESYNCING, |
26 | RAID_STATE_OFFLINE, | ||
27 | }; | ||
28 | |||
29 | enum raid_level { | ||
30 | RAID_LEVEL_UNKNOWN = 0, | ||
31 | RAID_LEVEL_LINEAR, | ||
32 | RAID_LEVEL_0, | ||
33 | RAID_LEVEL_1, | ||
34 | RAID_LEVEL_3, | ||
35 | RAID_LEVEL_4, | ||
36 | RAID_LEVEL_5, | ||
37 | RAID_LEVEL_6, | ||
21 | }; | 38 | }; |
22 | 39 | ||
23 | struct raid_data { | 40 | struct raid_data { |
24 | struct list_head component_list; | 41 | struct list_head component_list; |
25 | int component_count; | 42 | int component_count; |
26 | int level; | 43 | enum raid_level level; |
27 | enum raid_state state; | 44 | enum raid_state state; |
28 | int resync; | 45 | int resync; |
29 | }; | 46 | }; |
30 | 47 | ||
48 | /* resync complete goes from 0 to this */ | ||
49 | #define RAID_MAX_RESYNC (10000) | ||
50 | |||
31 | #define DEFINE_RAID_ATTRIBUTE(type, attr) \ | 51 | #define DEFINE_RAID_ATTRIBUTE(type, attr) \ |
32 | static inline void \ | 52 | static inline void \ |
33 | raid_set_##attr(struct raid_template *r, struct device *dev, type value) { \ | 53 | raid_set_##attr(struct raid_template *r, struct device *dev, type value) { \ |
@@ -48,7 +68,7 @@ raid_get_##attr(struct raid_template *r, struct device *dev) { \ | |||
48 | return rd->attr; \ | 68 | return rd->attr; \ |
49 | } | 69 | } |
50 | 70 | ||
51 | DEFINE_RAID_ATTRIBUTE(int, level) | 71 | DEFINE_RAID_ATTRIBUTE(enum raid_level, level) |
52 | DEFINE_RAID_ATTRIBUTE(int, resync) | 72 | DEFINE_RAID_ATTRIBUTE(int, resync) |
53 | DEFINE_RAID_ATTRIBUTE(enum raid_state, state) | 73 | DEFINE_RAID_ATTRIBUTE(enum raid_state, state) |
54 | 74 | ||