This source file includes following definitions.
- create_strip_zones
- raid0_run
- raid0_stop
- raid0_map
- raid0_status
- raid0_init
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <linux/module.h>
21 #include <linux/md.h>
22 #include <linux/raid0.h>
23 #include <linux/malloc.h>
24
25 #define MAJOR_NR MD_MAJOR
26 #define MD_DRIVER
27 #define MD_PERSONALITY
28
29 static void create_strip_zones (int minor, struct md_dev *mddev)
30 {
31 int i, j, c=0;
32 int current_offset=0;
33 struct real_dev *smallest_by_zone;
34 struct raid0_data *data=(struct raid0_data *) mddev->private;
35
36 data->nr_strip_zones=1;
37
38 for (i=1; i<mddev->nb_dev; i++)
39 {
40 for (j=0; j<i; j++)
41 if (devices[minor][i].size==devices[minor][j].size)
42 {
43 c=1;
44 break;
45 }
46
47 if (!c)
48 data->nr_strip_zones++;
49
50 c=0;
51 }
52
53 data->strip_zone=kmalloc (sizeof(struct strip_zone)*data->nr_strip_zones,
54 GFP_KERNEL);
55
56 data->smallest=NULL;
57
58 for (i=0; i<data->nr_strip_zones; i++)
59 {
60 data->strip_zone[i].dev_offset=current_offset;
61 smallest_by_zone=NULL;
62 c=0;
63
64 for (j=0; j<mddev->nb_dev; j++)
65 if (devices[minor][j].size>current_offset)
66 {
67 data->strip_zone[i].dev[c++]=devices[minor]+j;
68 if (!smallest_by_zone ||
69 smallest_by_zone->size > devices[minor][j].size)
70 smallest_by_zone=devices[minor]+j;
71 }
72
73 data->strip_zone[i].nb_dev=c;
74 data->strip_zone[i].size=(smallest_by_zone->size-current_offset)*c;
75
76 if (!data->smallest ||
77 data->smallest->size > data->strip_zone[i].size)
78 data->smallest=data->strip_zone+i;
79
80 data->strip_zone[i].zone_offset=i ? (data->strip_zone[i-1].zone_offset+
81 data->strip_zone[i-1].size) : 0;
82 current_offset=smallest_by_zone->size;
83 }
84 }
85
86 static int raid0_run (int minor, struct md_dev *mddev)
87 {
88 int cur=0, i=0, size, zone0_size, nb_zone, min;
89 struct raid0_data *data;
90
91 min=1 << FACTOR_SHIFT(FACTOR(mddev));
92
93 for (i=0; i<mddev->nb_dev; i++)
94 if (devices[minor][i].size<min)
95 {
96 printk ("Cannot use %dk chunks on dev %s\n", min,
97 partition_name (devices[minor][i].dev));
98 return -EINVAL;
99 }
100
101 MOD_INC_USE_COUNT;
102
103
104 md_size[minor]=0;
105
106 for (i=0; i<mddev->nb_dev; i++)
107 {
108 devices[minor][i].size &= ~((1 << FACTOR_SHIFT(FACTOR(mddev))) - 1);
109 md_size[minor] += devices[minor][i].size;
110 }
111
112 mddev->private=kmalloc (sizeof (struct raid0_data), GFP_KERNEL);
113 data=(struct raid0_data *) mddev->private;
114
115 create_strip_zones (minor, mddev);
116
117 nb_zone=data->nr_zones=
118 md_size[minor]/data->smallest->size +
119 (md_size[minor]%data->smallest->size ? 1 : 0);
120
121 data->hash_table=kmalloc (sizeof (struct raid0_hash)*nb_zone, GFP_KERNEL);
122
123 size=data->strip_zone[cur].size;
124
125 i=0;
126 while (cur<data->nr_strip_zones)
127 {
128 data->hash_table[i].zone0=data->strip_zone+cur;
129
130 if (size>=data->smallest->size)
131 {
132 data->hash_table[i++].zone1=NULL;
133 size-=data->smallest->size;
134
135 if (!size)
136 {
137 if (++cur==data->nr_strip_zones) continue;
138 size=data->strip_zone[cur].size;
139 }
140
141 continue;
142 }
143
144 if (++cur==data->nr_strip_zones)
145 {
146 data->hash_table[i].zone1=NULL;
147 continue;
148 }
149
150 zone0_size=size;
151 size=data->strip_zone[cur].size;
152 data->hash_table[i++].zone1=data->strip_zone+cur;
153 size-=(data->smallest->size - zone0_size);
154 }
155
156 return (0);
157 }
158
159
160 static int raid0_stop (int minor, struct md_dev *mddev)
161 {
162 struct raid0_data *data=(struct raid0_data *) mddev->private;
163
164 kfree (data->hash_table);
165 kfree (data->strip_zone);
166 kfree (data);
167
168 MOD_DEC_USE_COUNT;
169 return 0;
170 }
171
172
173
174
175
176
177
178
179 static int raid0_map (struct md_dev *mddev, kdev_t *rdev,
180 unsigned long *rsector, unsigned long size)
181 {
182 struct raid0_data *data=(struct raid0_data *) mddev->private;
183 static struct raid0_hash *hash;
184 struct strip_zone *zone;
185 struct real_dev *tmp_dev;
186 int blk_in_chunk, factor, chunk, chunk_size;
187 long block, rblock;
188
189 factor=FACTOR(mddev);
190 chunk_size=(1UL << FACTOR_SHIFT(factor));
191 block=*rsector >> 1;
192 hash=data->hash_table+(block/data->smallest->size);
193
194
195 if ((chunk_size*2)<(*rsector % (chunk_size*2))+size)
196 {
197 printk ("raid0_convert : can't convert block across chunks or bigger than %dk %ld %ld\n", chunk_size, *rsector, size);
198 return (-1);
199 }
200
201 if (block >= (hash->zone0->size +
202 hash->zone0->zone_offset))
203 {
204 if (!hash->zone1)
205 {
206 printk ("raid0_convert : hash->zone1==NULL for block %ld\n", block);
207 return (-1);
208 }
209
210 zone=hash->zone1;
211 }
212 else
213 zone=hash->zone0;
214
215 blk_in_chunk=block & (chunk_size -1);
216 chunk=(block - zone->zone_offset) / (zone->nb_dev<<FACTOR_SHIFT(factor));
217 tmp_dev=zone->dev[(block >> FACTOR_SHIFT(factor)) % zone->nb_dev];
218 rblock=(chunk << FACTOR_SHIFT(factor)) + blk_in_chunk + zone->dev_offset;
219
220 *rdev=tmp_dev->dev;
221 *rsector=rblock<<1;
222
223 return (0);
224 }
225
226
227 static int raid0_status (char *page, int minor, struct md_dev *mddev)
228 {
229 int sz=0;
230 #undef MD_DEBUG
231 #ifdef MD_DEBUG
232 int j, k;
233 struct raid0_data *data=(struct raid0_data *) mddev->private;
234
235 sz+=sprintf (page+sz, " ");
236 for (j=0; j<data->nr_zones; j++)
237 {
238 sz+=sprintf (page+sz, "[z%d",
239 data->hash_table[j].zone0-data->strip_zone);
240 if (data->hash_table[j].zone1)
241 sz+=sprintf (page+sz, "/z%d] ",
242 data->hash_table[j].zone1-data->strip_zone);
243 else
244 sz+=sprintf (page+sz, "] ");
245 }
246
247 sz+=sprintf (page+sz, "\n");
248
249 for (j=0; j<data->nr_strip_zones; j++)
250 {
251 sz+=sprintf (page+sz, " z%d=[", j);
252 for (k=0; k<data->strip_zone[j].nb_dev; k++)
253 sz+=sprintf (page+sz, "%s/",
254 partition_name(data->strip_zone[j].dev[k]->dev));
255 sz--;
256 sz+=sprintf (page+sz, "] zo=%d do=%d s=%d\n",
257 data->strip_zone[j].zone_offset,
258 data->strip_zone[j].dev_offset,
259 data->strip_zone[j].size);
260 }
261 #endif
262 return sz;
263 }
264
265
266 static struct md_personality raid0_personality=
267 {
268 "raid0",
269 raid0_map,
270 raid0_run,
271 raid0_stop,
272 raid0_status,
273 NULL,
274 0
275 };
276
277
278 #ifndef MODULE
279
280 void raid0_init (void)
281 {
282 register_md_personality (RAID0, &raid0_personality);
283 }
284
285 #else
286
287 int init_module (void)
288 {
289 return (register_md_personality (RAID0, &raid0_personality));
290 }
291
292 void cleanup_module (void)
293 {
294 if (MOD_IN_USE)
295 printk ("md raid0 : module still busy...\n");
296 else
297 unregister_md_personality (RAID0);
298 }
299
300 #endif