2 linear.c : Multiple Devices driver for Linux
3 Copyright (C) 1994-96 Marc ZYNGIER
4 <zyngier@ufr-info-p7.ibp.fr> or
7 Linear mode management functions.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2, or (at your option)
14 You should have received a copy of the GNU General Public License
15 (for example /usr/src/linux/COPYING); if not, write to the Free
16 Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 #include <linux/module.h>
21 #include <linux/raid/md.h>
22 #include <linux/slab.h>
23 #include <linux/raid/linear.h>
25 #define MAJOR_NR MD_MAJOR
27 #define MD_PERSONALITY
30 * find which device holds a particular offset
32 static inline dev_info_t
*which_dev(mddev_t
*mddev
, sector_t sector
)
35 linear_conf_t
*conf
= mddev_to_conf(mddev
);
36 sector_t block
= sector
>> 1;
39 * sector_div(a,b) returns the remainer and sets a to a/b
41 (void)sector_div(block
, conf
->smallest
->size
);
42 hash
= conf
->hash_table
[block
];
44 while ((sector
>>1) >= (hash
->size
+ hash
->offset
))
50 * linear_mergeable_bvec -- tell bio layer if a two requests can be merged
52 * @bio: the buffer head that's been built up so far
53 * @biovec: the request that could be merged to it.
55 * Return amount of bytes we can take at this offset
57 static int linear_mergeable_bvec(request_queue_t
*q
, struct bio
*bio
, struct bio_vec
*biovec
)
59 mddev_t
*mddev
= q
->queuedata
;
61 unsigned long maxsectors
, bio_sectors
= bio
->bi_size
>> 9;
62 sector_t sector
= bio
->bi_sector
+ get_start_sect(bio
->bi_bdev
);
64 dev0
= which_dev(mddev
, sector
);
65 maxsectors
= (dev0
->size
<< 1) - (sector
- (dev0
->offset
<<1));
67 if (maxsectors
< bio_sectors
)
70 maxsectors
-= bio_sectors
;
72 if (maxsectors
<= (PAGE_SIZE
>> 9 ) && bio_sectors
== 0)
73 return biovec
->bv_len
;
74 /* The bytes available at this offset could be really big,
75 * so we cap at 2^31 to avoid overflow */
76 if (maxsectors
> (1 << (31-9)))
78 return maxsectors
<< 9;
81 static void linear_unplug(request_queue_t
*q
)
83 mddev_t
*mddev
= q
->queuedata
;
84 linear_conf_t
*conf
= mddev_to_conf(mddev
);
87 for (i
=0; i
< mddev
->raid_disks
; i
++) {
88 request_queue_t
*r_queue
= bdev_get_queue(conf
->disks
[i
].rdev
->bdev
);
89 if (r_queue
->unplug_fn
)
90 r_queue
->unplug_fn(r_queue
);
94 static int linear_issue_flush(request_queue_t
*q
, struct gendisk
*disk
,
95 sector_t
*error_sector
)
97 mddev_t
*mddev
= q
->queuedata
;
98 linear_conf_t
*conf
= mddev_to_conf(mddev
);
101 for (i
=0; i
< mddev
->raid_disks
&& ret
== 0; i
++) {
102 struct block_device
*bdev
= conf
->disks
[i
].rdev
->bdev
;
103 request_queue_t
*r_queue
= bdev_get_queue(bdev
);
105 if (!r_queue
->issue_flush_fn
)
108 ret
= r_queue
->issue_flush_fn(r_queue
, bdev
->bd_disk
, error_sector
);
113 static int linear_run (mddev_t
*mddev
)
120 sector_t curr_offset
;
121 struct list_head
*tmp
;
123 conf
= kmalloc (sizeof (*conf
) + mddev
->raid_disks
*sizeof(dev_info_t
),
127 memset(conf
, 0, sizeof(*conf
) + mddev
->raid_disks
*sizeof(dev_info_t
));
128 mddev
->private = conf
;
131 * Find the smallest device.
134 conf
->smallest
= NULL
;
136 mddev
->array_size
= 0;
138 ITERATE_RDEV(mddev
,rdev
,tmp
) {
139 int j
= rdev
->raid_disk
;
140 dev_info_t
*disk
= conf
->disks
+ j
;
142 if (j
< 0 || j
> mddev
->raid_disks
|| disk
->rdev
) {
143 printk("linear: disk numbering problem. Aborting!\n");
149 blk_queue_stack_limits(mddev
->queue
,
150 rdev
->bdev
->bd_disk
->queue
);
151 /* as we don't honour merge_bvec_fn, we must never risk
152 * violating it, so limit ->max_sector to one PAGE, as
153 * a one page request is never in violation.
155 if (rdev
->bdev
->bd_disk
->queue
->merge_bvec_fn
&&
156 mddev
->queue
->max_sectors
> (PAGE_SIZE
>>9))
157 blk_queue_max_sectors(mddev
->queue
, PAGE_SIZE
>>9);
159 disk
->size
= rdev
->size
;
160 mddev
->array_size
+= rdev
->size
;
162 if (!conf
->smallest
|| (disk
->size
< conf
->smallest
->size
))
163 conf
->smallest
= disk
;
166 if (cnt
!= mddev
->raid_disks
) {
167 printk("linear: not enough drives present. Aborting!\n");
172 * This code was restructured to work around a gcc-2.95.3 internal
173 * compiler error. Alter it with care.
180 sz
= mddev
->array_size
;
181 base
= conf
->smallest
->size
;
182 round
= sector_div(sz
, base
);
183 nb_zone
= conf
->nr_zones
= sz
+ (round
? 1 : 0);
186 conf
->hash_table
= kmalloc (sizeof (dev_info_t
*) * nb_zone
,
188 if (!conf
->hash_table
)
192 * Here we generate the linear hash table
194 table
= conf
->hash_table
;
197 for (i
= 0; i
< cnt
; i
++) {
198 dev_info_t
*disk
= conf
->disks
+ i
;
200 disk
->offset
= curr_offset
;
201 curr_offset
+= disk
->size
;
203 /* 'curr_offset' is the end of this disk
204 * 'start' is the start of table
206 while (start
< curr_offset
) {
208 start
+= conf
->smallest
->size
;
211 if (table
-conf
->hash_table
!= nb_zone
)
214 blk_queue_merge_bvec(mddev
->queue
, linear_mergeable_bvec
);
215 mddev
->queue
->unplug_fn
= linear_unplug
;
216 mddev
->queue
->issue_flush_fn
= linear_issue_flush
;
224 static int linear_stop (mddev_t
*mddev
)
226 linear_conf_t
*conf
= mddev_to_conf(mddev
);
228 blk_sync_queue(mddev
->queue
); /* the unplug fn references 'conf'*/
229 kfree(conf
->hash_table
);
235 static int linear_make_request (request_queue_t
*q
, struct bio
*bio
)
237 mddev_t
*mddev
= q
->queuedata
;
241 if (bio_data_dir(bio
)==WRITE
) {
242 disk_stat_inc(mddev
->gendisk
, writes
);
243 disk_stat_add(mddev
->gendisk
, write_sectors
, bio_sectors(bio
));
245 disk_stat_inc(mddev
->gendisk
, reads
);
246 disk_stat_add(mddev
->gendisk
, read_sectors
, bio_sectors(bio
));
249 tmp_dev
= which_dev(mddev
, bio
->bi_sector
);
250 block
= bio
->bi_sector
>> 1;
252 if (unlikely(block
>= (tmp_dev
->size
+ tmp_dev
->offset
)
253 || block
< tmp_dev
->offset
)) {
254 char b
[BDEVNAME_SIZE
];
256 printk("linear_make_request: Block %llu out of bounds on "
257 "dev %s size %llu offset %llu\n",
258 (unsigned long long)block
,
259 bdevname(tmp_dev
->rdev
->bdev
, b
),
260 (unsigned long long)tmp_dev
->size
,
261 (unsigned long long)tmp_dev
->offset
);
262 bio_io_error(bio
, bio
->bi_size
);
265 if (unlikely(bio
->bi_sector
+ (bio
->bi_size
>> 9) >
266 (tmp_dev
->offset
+ tmp_dev
->size
)<<1)) {
267 /* This bio crosses a device boundary, so we have to
271 bp
= bio_split(bio
, bio_split_pool
,
272 ((tmp_dev
->offset
+ tmp_dev
->size
)<<1) - bio
->bi_sector
);
273 if (linear_make_request(q
, &bp
->bio1
))
274 generic_make_request(&bp
->bio1
);
275 if (linear_make_request(q
, &bp
->bio2
))
276 generic_make_request(&bp
->bio2
);
277 bio_pair_release(bp
);
281 bio
->bi_bdev
= tmp_dev
->rdev
->bdev
;
282 bio
->bi_sector
= bio
->bi_sector
- (tmp_dev
->offset
<< 1) + tmp_dev
->rdev
->data_offset
;
287 static void linear_status (struct seq_file
*seq
, mddev_t
*mddev
)
293 linear_conf_t
*conf
= mddev_to_conf(mddev
);
296 seq_printf(seq
, " ");
297 for (j
= 0; j
< conf
->nr_zones
; j
++)
299 char b
[BDEVNAME_SIZE
];
300 s
+= conf
->smallest_size
;
301 seq_printf(seq
, "[%s",
302 bdevname(conf
->hash_table
[j
][0].rdev
->bdev
,b
));
304 while (s
> conf
->hash_table
[j
][0].offset
+
305 conf
->hash_table
[j
][0].size
)
306 seq_printf(seq
, "/%s] ",
307 bdevname(conf
->hash_table
[j
][1].rdev
->bdev
,b
));
309 seq_printf(seq
, "] ");
311 seq_printf(seq
, "\n");
313 seq_printf(seq
, " %dk rounding", mddev
->chunk_size
/1024);
317 static mdk_personality_t linear_personality
=
320 .owner
= THIS_MODULE
,
321 .make_request
= linear_make_request
,
324 .status
= linear_status
,
327 static int __init
linear_init (void)
329 return register_md_personality (LINEAR
, &linear_personality
);
332 static void linear_exit (void)
334 unregister_md_personality (LINEAR
);
338 module_init(linear_init
);
339 module_exit(linear_exit
);
340 MODULE_LICENSE("GPL");
341 MODULE_ALIAS("md-personality-1"); /* LINEAR */