This source file includes following definitions.
- find_gendisk
- partition_name
- set_ra
- md_ioctl
- md_open
- md_release
- md_map
- do_md_request
- md_geninit
- get_md_status
- register_md_personality
- unregister_md_personality
- md_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <linux/config.h>
23 #include <linux/module.h>
24 #include <linux/version.h>
25 #include <linux/malloc.h>
26 #include <linux/mm.h>
27 #include <linux/md.h>
28 #include <linux/hdreg.h>
29 #include <linux/stat.h>
30 #include <linux/fs.h>
31 #include <linux/proc_fs.h>
32 #include <linux/blkdev.h>
33 #include <linux/genhd.h>
34 #ifdef CONFIG_KERNELD
35 #include <linux/kerneld.h>
36 #endif
37 #include <linux/errno.h>
38
39 #define MAJOR_NR MD_MAJOR
40 #define MD_DRIVER
41
42 #include <linux/blk.h>
43
44 static struct hd_struct md_hd_struct[MAX_MD_DEV];
45 static int md_blocksizes[MAX_MD_DEV];
46
47 int md_size[MAX_MD_DEV]={0, };
48
49 static void md_geninit (struct gendisk *);
50
51 static struct gendisk md_gendisk=
52 {
53 MD_MAJOR,
54 "md",
55 0,
56 1,
57 MAX_MD_DEV,
58 md_geninit,
59 md_hd_struct,
60 md_size,
61 MAX_MD_DEV,
62 NULL,
63 NULL
64 };
65
66 static struct md_personality *pers[MAX_PERSONALITY]={NULL, };
67
68 struct real_dev devices[MAX_MD_DEV][MAX_REAL];
69 struct md_dev md_dev[MAX_MD_DEV];
70
71 static struct gendisk *find_gendisk (kdev_t dev)
72 {
73 struct gendisk *tmp=gendisk_head;
74
75 while (tmp != NULL)
76 {
77 if (tmp->major==MAJOR(dev))
78 return (tmp);
79
80 tmp=tmp->next;
81 }
82
83 return (NULL);
84 }
85
86
87
88 char *partition_name (kdev_t dev)
89 {
90 static char name[40];
91
92 struct gendisk *hd = find_gendisk (dev);
93
94 if (!hd)
95 {
96 printk ("No gendisk entry for dev %s\n", kdevname(dev));
97 sprintf (name, "dev %s", kdevname(dev));
98 return (name);
99 }
100
101 return disk_name (hd, MINOR(dev), name);
102 }
103
104
105 static void set_ra (void)
106 {
107 int i, j, minra=INT_MAX;
108
109 for (i=0; i<MAX_MD_DEV; i++)
110 {
111 if (!md_dev[i].pers)
112 continue;
113
114 for (j=0; j<md_dev[i].nb_dev; j++)
115 if (read_ahead[MAJOR(devices[i][j].dev)]<minra)
116 minra=read_ahead[MAJOR(devices[i][j].dev)];
117 }
118
119 read_ahead[MD_MAJOR]=minra;
120 }
121
122
123 static int md_ioctl (struct inode *inode, struct file *file,
124 unsigned int cmd, unsigned long arg)
125 {
126 int minor, index, err, current_ra;
127 struct gendisk *gen_real;
128 struct hd_geometry *loc = (struct hd_geometry *) arg;
129 kdev_t dev;
130
131 if (!suser())
132 return -EACCES;
133
134 if (((minor=MINOR(inode->i_rdev)) & 0x80) &&
135 (minor & 0x7f) < MAX_PERSONALITY &&
136 pers[minor & 0x7f] &&
137 pers[minor & 0x7f]->ioctl)
138 return (pers[minor & 0x7f]->ioctl (inode, file, cmd, arg));
139
140 if (minor >= MAX_MD_DEV)
141 return -EINVAL;
142
143 switch (cmd)
144 {
145 case REGISTER_DEV:
146 dev=to_kdev_t ((dev_t) arg);
147 if (MAJOR(dev)==MD_MAJOR || md_dev[minor].nb_dev==MAX_REAL)
148 return -EINVAL;
149
150 if (!fs_may_mount (dev) || md_dev[minor].pers)
151 return -EBUSY;
152
153 if (!(gen_real=find_gendisk (dev)))
154 return -ENOENT;
155
156 index=md_dev[minor].nb_dev++;
157 devices[minor][index].dev=dev;
158
159
160
161
162
163
164 devices[minor][index].inode=get_empty_inode ();
165 devices[minor][index].inode->i_dev=dev;
166
167 insert_inode_hash (devices[minor][index].inode);
168
169
170
171
172
173 devices[minor][index].size=gen_real->sizes[MINOR(dev)] & ~((PAGE_SIZE >> 10)-1);
174 devices[minor][index].offset=index ?
175 (devices[minor][index-1].offset + devices[minor][index-1].size) : 0;
176
177 if (!index)
178 md_size[minor]=devices[minor][index].size;
179 else
180 md_size[minor]+=devices[minor][index].size;
181
182 printk("REGISTER_DEV %s to md%x done\n", partition_name(dev), minor);
183 break;
184
185 case START_MD:
186 if (!md_dev[minor].nb_dev)
187 return -EINVAL;
188
189 if (md_dev[minor].pers)
190 return -EBUSY;
191
192 md_dev[minor].repartition=(int) arg;
193
194 if ((index=PERSONALITY(md_dev+minor) >> (PERSONALITY_SHIFT))
195 >= MAX_PERSONALITY)
196 return -EINVAL;
197
198 if (!pers[index])
199 {
200 #ifdef CONFIG_KERNELD
201 char module_name[80];
202 sprintf (module_name, "md-personality-%d", index);
203 request_module (module_name);
204 if (!pers[index])
205 #endif
206 return -EINVAL;
207 }
208
209 md_dev[minor].pers=pers[index];
210
211 if ((err=md_dev[minor].pers->run (minor, md_dev+minor)))
212 {
213 md_dev[minor].pers=NULL;
214 return (err);
215 }
216
217
218
219
220 md_hd_struct[minor].start_sect=0;
221 md_hd_struct[minor].nr_sects=md_size[minor]<<1;
222
223
224
225
226 current_ra=read_ahead[MD_MAJOR];
227
228 for (index=0; index<md_dev[minor].nb_dev; index++)
229 {
230 if (current_ra>read_ahead[MAJOR(devices[minor][index].dev)])
231 current_ra=read_ahead[MAJOR(devices[minor][index].dev)];
232
233 devices[minor][index].fault_count=0;
234 devices[minor][index].invalid=VALID;
235 }
236
237 read_ahead[MD_MAJOR]=current_ra;
238
239 printk ("START_DEV md%x %s\n", minor, md_dev[minor].pers->name);
240 break;
241
242 case STOP_MD:
243 if (inode->i_count>1 || md_dev[minor].busy>1)
244 {
245 printk ("STOP_MD md%x failed : i_count=%d, busy=%d\n", minor, inode->i_count, md_dev[minor].busy);
246 return -EBUSY;
247 }
248
249 if (md_dev[minor].pers)
250 {
251
252 fsync_dev (inode->i_rdev);
253 invalidate_buffers (inode->i_rdev);
254 md_dev[minor].pers->stop (minor, md_dev+minor);
255 }
256
257
258 for (index=0; index<md_dev[minor].nb_dev; index++)
259 clear_inode (devices[minor][index].inode);
260
261 md_dev[minor].nb_dev=md_size[minor]=0;
262 md_dev[minor].pers=NULL;
263
264 set_ra ();
265
266 printk ("STOP_DEV md%x\n", minor);
267 break;
268
269 #if defined(CONFIG_MD_SUPPORT_RAID1) || defined(CONFIG_MD_SUPPORT_RAID5)
270 case MD_INVALID:
271 dev=to_kdev_t ((dev_t) arg);
272 if (!(err=md_valid_device (minor, dev, INVALID_ALWAYS)))
273 printk ("md%d : %s disabled\n", minor, partition_name (dev));
274
275 return (err);
276
277 case MD_VALID:
278 dev=to_kdev_t ((dev_t) arg);
279 if (!(err=md_valid_device (minor, dev, VALID)))
280 printk ("md%d : %s enabled\n", minor, partition_name (dev));
281
282 return (err);
283 #endif
284
285 case BLKGETSIZE:
286 if (!arg) return -EINVAL;
287 err=verify_area (VERIFY_WRITE, (long *) arg, sizeof(long));
288 if (err)
289 return err;
290 put_user (md_hd_struct[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
291 break;
292
293 case BLKFLSBUF:
294 fsync_dev (inode->i_rdev);
295 invalidate_buffers (inode->i_rdev);
296 break;
297
298 case BLKRASET:
299 if (arg > 0xff)
300 return -EINVAL;
301 read_ahead[MAJOR(inode->i_rdev)] = arg;
302 return 0;
303
304 case BLKRAGET:
305 if (!arg) return -EINVAL;
306 err=verify_area (VERIFY_WRITE, (long *) arg, sizeof(long));
307 if (err)
308 return err;
309 put_user (read_ahead[MAJOR(inode->i_rdev)], (long *) arg);
310 break;
311
312 case HDIO_GETGEO:
313 if (!loc) return -EINVAL;
314 err = verify_area(VERIFY_WRITE, loc, sizeof(*loc));
315 if (err)
316 return err;
317 put_user (2, (char *) &loc->heads);
318 put_user (4, (char *) &loc->sectors);
319 put_user (md_hd_struct[minor].nr_sects/8, (short *) &loc->cylinders);
320 put_user (md_hd_struct[MINOR(inode->i_rdev)].start_sect,
321 (long *) &loc->start);
322 break;
323
324 RO_IOCTLS(inode->i_rdev,arg);
325
326 default:
327 printk ("Unknown md_ioctl %d\n", cmd);
328 return -EINVAL;
329 }
330
331 return (0);
332 }
333
334
335 static int md_open (struct inode *inode, struct file *file)
336 {
337 int minor=MINOR(inode->i_rdev);
338
339 md_dev[minor].busy++;
340 return (0);
341 }
342
343
344 static void md_release (struct inode *inode, struct file *file)
345 {
346 int minor=MINOR(inode->i_rdev);
347
348 sync_dev (inode->i_rdev);
349 md_dev[minor].busy--;
350 }
351
352
353 static struct file_operations md_fops=
354 {
355 NULL,
356 block_read,
357 block_write,
358 NULL,
359 NULL,
360 md_ioctl,
361 NULL,
362 md_open,
363 md_release,
364 block_fsync
365 };
366
367 int md_map (int minor, kdev_t *rdev, unsigned long *rsector, unsigned long size)
368 {
369 if ((unsigned int) minor >= MAX_MD_DEV)
370 {
371 printk ("Bad md device %d\n", minor);
372 return (-1);
373 }
374
375 if (!md_dev[minor].pers)
376 {
377 printk ("Oops ! md%d not running, giving up !\n", minor);
378 return (-1);
379 }
380
381 return (md_dev[minor].pers->map(md_dev+minor, rdev, rsector, size));
382 }
383
384
385 static void do_md_request (void)
386 {
387 printk ("Got md request, not good...");
388 return;
389 }
390
391 static struct symbol_table md_symbol_table=
392 {
393 #include <linux/symtab_begin.h>
394
395 X(devices),
396 X(md_size),
397 X(register_md_personality),
398 X(unregister_md_personality),
399 X(partition_name),
400
401 #if defined(CONFIG_MD_SUPPORT_RAID1) || defined(CONFIG_MD_SUPPORT_RAID5)
402 X(md_valid_device),
403 X(md_can_reemit),
404 #endif
405
406 #include <linux/symtab_end.h>
407 };
408
409
410 static void md_geninit (struct gendisk *gdisk)
411 {
412 int i;
413
414 for(i=0;i<MAX_MD_DEV;i++)
415 {
416 md_blocksizes[i] = 1024;
417 md_gendisk.part[i].start_sect=-1;
418 md_dev[i].pers=NULL;
419 #ifdef MD_COUNT_SIZES
420 md_dev[i].smallest_count=md_dev[i].biggest_count=md_dev[i].equal_count=0;
421 #endif
422 }
423
424 blksize_size[MAJOR_NR] = md_blocksizes;
425 register_symtab (&md_symbol_table);
426
427 proc_register(&proc_root,
428 &(struct proc_dir_entry)
429 {
430 PROC_MD, 6, "mdstat",
431 S_IFREG | S_IRUGO, 1, 0, 0,
432 });
433 }
434
435
436 int get_md_status (char *page)
437 {
438 int sz=0, i, j;
439
440 sz+=sprintf( page+sz, "Personalities : ");
441 for (i=0; i<MAX_PERSONALITY; i++)
442 if (pers[i])
443 sz+=sprintf (page+sz, "[%d %s] ", i, pers[i]->name);
444
445 page[sz-1]='\n';
446
447 sz+=sprintf (page+sz, "read_ahead ");
448 if (read_ahead[MD_MAJOR]==INT_MAX)
449 sz+=sprintf (page+sz, "not set\n");
450 else
451 sz+=sprintf (page+sz, "%d sectors\n", read_ahead[MD_MAJOR]);
452
453 for (i=0; i<MAX_MD_DEV; i++)
454 {
455 sz+=sprintf (page+sz, "md%d : %sactive", i, md_dev[i].pers ? "" : "in");
456
457 if (md_dev[i].pers)
458 sz+=sprintf (page+sz, " %s", md_dev[i].pers->name);
459
460 for (j=0; j<md_dev[i].nb_dev; j++)
461 sz+=sprintf (page+sz, " %s%s%s",
462 (devices[i][j].invalid==VALID) ? "" : "(",
463 partition_name(devices[i][j].dev),
464 (devices[i][j].invalid==VALID) ? "" : ")");
465
466 if (md_dev[i].nb_dev)
467 sz+=sprintf (page+sz, " %d blocks", md_size[i]);
468
469 if (!md_dev[i].pers)
470 {
471 sz+=sprintf (page+sz, "\n");
472 continue;
473 }
474
475 if (md_dev[i].pers->max_invalid_dev)
476 sz+=sprintf (page+sz, " maxfault=%ld", MAX_FAULT(md_dev+i));
477
478 if (md_dev[i].pers != pers[(LINEAR>>PERSONALITY_SHIFT)])
479 {
480 sz+=sprintf (page+sz, " %dk chunks", 1<<FACTOR_SHIFT(FACTOR(md_dev+i)));
481 }
482 sz+=sprintf (page+sz, "\n");
483 sz+=md_dev[i].pers->status (page+sz, i, md_dev+i);
484 }
485
486 return (sz);
487 }
488
489 int register_md_personality (int p_num, struct md_personality *p)
490 {
491 int i=(p_num >> PERSONALITY_SHIFT);
492
493 if (i >= MAX_PERSONALITY)
494 return -EINVAL;
495
496 if (pers[i])
497 return -EBUSY;
498
499 pers[i]=p;
500 printk ("%s personality registered\n", p->name);
501 return 0;
502 }
503
504 int unregister_md_personality (int p_num)
505 {
506 int i=(p_num >> PERSONALITY_SHIFT);
507
508 if (i >= MAX_PERSONALITY)
509 return -EINVAL;
510
511 printk ("%s personality unregistered\n", pers[i]->name);
512 pers[i]=NULL;
513 return 0;
514 }
515
516 void linear_init (void);
517 void raid0_init (void);
518 void raid1_init (void);
519 void raid5_init (void);
520
521 int md_init (void)
522 {
523 printk ("md driver %s MAX_MD_DEV=%d, MAX_REAL=%d\n", MD_VERSION, MAX_MD_DEV, MAX_REAL);
524
525 if (register_blkdev (MD_MAJOR, "md", &md_fops))
526 {
527 printk ("Unable to get major %d for md\n", MD_MAJOR);
528 return (-1);
529 }
530
531 blk_dev[MD_MAJOR].request_fn=DEVICE_REQUEST;
532 blk_dev[MD_MAJOR].current_request=NULL;
533 read_ahead[MD_MAJOR]=INT_MAX;
534 md_gendisk.next=gendisk_head;
535
536 gendisk_head=&md_gendisk;
537
538 #ifdef CONFIG_MD_LINEAR
539 linear_init ();
540 #endif
541 #ifdef CONFIG_MD_STRIPED
542 raid0_init ();
543 #endif
544
545 return (0);
546 }