3 linear.c : Multiple Devices driver for Linux
4 Copyright (C) 1994-96 Marc ZYNGIER
5 <zyngier@ufr-info-p7.ibp.fr> or
8 Linear mode management functions.
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
15 You should have received a copy of the GNU General Public License
16 (for example /usr/src/linux/COPYING); if not, write to the Free
17 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <linux/module.h>
23 #include <linux/malloc.h>
24 #include <linux/init.h>
28 #define MAJOR_NR MD_MAJOR
30 #define MD_PERSONALITY
32 static int linear_run (int minor
, struct md_dev
*mddev
)
34 int cur
=0, i
, size
, dev0_size
, nb_zone
;
35 struct linear_data
*data
;
39 mddev
->private=kmalloc (sizeof (struct linear_data
), GFP_KERNEL
);
40 data
=(struct linear_data
*) mddev
->private;
43 Find out the smallest device. This was previously done
44 at registry time, but since it violates modularity,
45 I moved it here... Any comment ? ;-)
48 data
->smallest
=mddev
->devices
;
49 for (i
=1; i
<mddev
->nb_dev
; i
++)
50 if (data
->smallest
->size
> mddev
->devices
[i
].size
)
51 data
->smallest
=mddev
->devices
+i
;
53 nb_zone
=data
->nr_zones
=
54 md_size
[minor
]/data
->smallest
->size
+
55 (md_size
[minor
]%data
->smallest
->size
? 1 : 0);
57 data
->hash_table
=kmalloc (sizeof (struct linear_hash
)*nb_zone
, GFP_KERNEL
);
59 size
=mddev
->devices
[cur
].size
;
62 while (cur
<mddev
->nb_dev
)
64 data
->hash_table
[i
].dev0
=mddev
->devices
+cur
;
66 if (size
>=data
->smallest
->size
) /* If we completely fill the slot */
68 data
->hash_table
[i
++].dev1
=NULL
;
69 size
-=data
->smallest
->size
;
73 if (++cur
==mddev
->nb_dev
) continue;
74 size
=mddev
->devices
[cur
].size
;
80 if (++cur
==mddev
->nb_dev
) /* Last dev, set dev1 as NULL */
82 data
->hash_table
[i
].dev1
=NULL
;
86 dev0_size
=size
; /* Here, we use a 2nd dev to fill the slot */
87 size
=mddev
->devices
[cur
].size
;
88 data
->hash_table
[i
++].dev1
=mddev
->devices
+cur
;
89 size
-=(data
->smallest
->size
- dev0_size
);
95 static int linear_stop (int minor
, struct md_dev
*mddev
)
97 struct linear_data
*data
=(struct linear_data
*) mddev
->private;
99 kfree (data
->hash_table
);
108 static int linear_map (struct md_dev
*mddev
, kdev_t
*rdev
,
109 unsigned long *rsector
, unsigned long size
)
111 struct linear_data
*data
=(struct linear_data
*) mddev
->private;
112 struct linear_hash
*hash
;
113 struct real_dev
*tmp_dev
;
117 hash
=data
->hash_table
+(block
/data
->smallest
->size
);
119 if (block
>= (hash
->dev0
->size
+ hash
->dev0
->offset
))
123 printk ("linear_map : hash->dev1==NULL for block %ld\n", block
);
132 if (block
>= (tmp_dev
->size
+ tmp_dev
->offset
) || block
< tmp_dev
->offset
)
133 printk ("Block %ld out of bounds on dev %s size %d offset %d\n",
134 block
, kdevname(tmp_dev
->dev
), tmp_dev
->size
, tmp_dev
->offset
);
137 *rsector
=(block
-(tmp_dev
->offset
)) << 1;
142 static int linear_status (char *page
, int minor
, struct md_dev
*mddev
)
149 struct linear_data
*data
=(struct linear_data
*) mddev
->private;
151 sz
+=sprintf (page
+sz
, " ");
152 for (j
=0; j
<data
->nr_zones
; j
++)
154 sz
+=sprintf (page
+sz
, "[%s",
155 partition_name (data
->hash_table
[j
].dev0
->dev
));
157 if (data
->hash_table
[j
].dev1
)
158 sz
+=sprintf (page
+sz
, "/%s] ",
159 partition_name(data
->hash_table
[j
].dev1
->dev
));
161 sz
+=sprintf (page
+sz
, "] ");
164 sz
+=sprintf (page
+sz
, "\n");
166 sz
+=sprintf (page
+sz
, " %dk rounding", 1<<FACTOR_SHIFT(FACTOR(mddev
)));
171 static struct md_personality linear_personality
=
180 NULL
, /* no ioctls */
187 __initfunc(void linear_init (void))
189 register_md_personality (LINEAR
, &linear_personality
);
194 int init_module (void)
196 return (register_md_personality (LINEAR
, &linear_personality
));
199 void cleanup_module (void)
201 unregister_md_personality (LINEAR
);