md: Removal of hash table in linear raid
[safe/jmp/linux-2.6] / drivers / md / linear.c
1 /*
2    linear.c : Multiple Devices driver for Linux
3               Copyright (C) 1994-96 Marc ZYNGIER
4               <zyngier@ufr-info-p7.ibp.fr> or
5               <maz@gloups.fdn.fr>
6
7    Linear mode management functions.
8
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)
12    any later version.
13    
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.  
17 */
18
19 #include <linux/blkdev.h>
20 #include <linux/raid/md_u.h>
21 #include <linux/seq_file.h>
22 #include "md.h"
23 #include "linear.h"
24
25 /*
26  * find which device holds a particular offset 
27  */
28 static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector)
29 {
30         dev_info_t *hash;
31         linear_conf_t *conf = mddev->private;
32
33         hash = conf->disks;
34
35         while (sector >= hash->num_sectors + hash->start_sector)
36                 hash++;
37         return hash;
38 }
39
40 /**
41  *      linear_mergeable_bvec -- tell bio layer if two requests can be merged
42  *      @q: request queue
43  *      @bvm: properties of new bio
44  *      @biovec: the request that could be merged to it.
45  *
46  *      Return amount of bytes we can take at this offset
47  */
48 static int linear_mergeable_bvec(struct request_queue *q,
49                                  struct bvec_merge_data *bvm,
50                                  struct bio_vec *biovec)
51 {
52         mddev_t *mddev = q->queuedata;
53         dev_info_t *dev0;
54         unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
55         sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
56
57         dev0 = which_dev(mddev, sector);
58         maxsectors = dev0->num_sectors - (sector - dev0->start_sector);
59
60         if (maxsectors < bio_sectors)
61                 maxsectors = 0;
62         else
63                 maxsectors -= bio_sectors;
64
65         if (maxsectors <= (PAGE_SIZE >> 9 ) && bio_sectors == 0)
66                 return biovec->bv_len;
67         /* The bytes available at this offset could be really big,
68          * so we cap at 2^31 to avoid overflow */
69         if (maxsectors > (1 << (31-9)))
70                 return 1<<31;
71         return maxsectors << 9;
72 }
73
74 static void linear_unplug(struct request_queue *q)
75 {
76         mddev_t *mddev = q->queuedata;
77         linear_conf_t *conf = mddev->private;
78         int i;
79
80         for (i=0; i < mddev->raid_disks; i++) {
81                 struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev);
82                 blk_unplug(r_queue);
83         }
84 }
85
86 static int linear_congested(void *data, int bits)
87 {
88         mddev_t *mddev = data;
89         linear_conf_t *conf = mddev->private;
90         int i, ret = 0;
91
92         for (i = 0; i < mddev->raid_disks && !ret ; i++) {
93                 struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
94                 ret |= bdi_congested(&q->backing_dev_info, bits);
95         }
96         return ret;
97 }
98
99 static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks)
100 {
101         linear_conf_t *conf = mddev->private;
102
103         WARN_ONCE(sectors || raid_disks,
104                   "%s does not support generic reshape\n", __func__);
105
106         return conf->array_sectors;
107 }
108
109 static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
110 {
111         linear_conf_t *conf;
112         mdk_rdev_t *rdev;
113         int i, cnt;
114
115         conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(dev_info_t),
116                         GFP_KERNEL);
117         if (!conf)
118                 return NULL;
119
120         cnt = 0;
121         conf->array_sectors = 0;
122
123         list_for_each_entry(rdev, &mddev->disks, same_set) {
124                 int j = rdev->raid_disk;
125                 dev_info_t *disk = conf->disks + j;
126
127                 if (j < 0 || j >= raid_disks || disk->rdev) {
128                         printk("linear: disk numbering problem. Aborting!\n");
129                         goto out;
130                 }
131
132                 disk->rdev = rdev;
133
134                 blk_queue_stack_limits(mddev->queue,
135                                        rdev->bdev->bd_disk->queue);
136                 /* as we don't honour merge_bvec_fn, we must never risk
137                  * violating it, so limit ->max_sector to one PAGE, as
138                  * a one page request is never in violation.
139                  */
140                 if (rdev->bdev->bd_disk->queue->merge_bvec_fn &&
141                     queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9))
142                         blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9);
143
144                 disk->num_sectors = rdev->sectors;
145                 conf->array_sectors += rdev->sectors;
146
147                 cnt++;
148         }
149         if (cnt != raid_disks) {
150                 printk("linear: not enough drives present. Aborting!\n");
151                 goto out;
152         }
153
154         /*
155          * Here we calculate the device offsets.
156          */
157         conf->disks[0].start_sector = 0;
158         for (i = 1; i < raid_disks; i++)
159                 conf->disks[i].start_sector =
160                         conf->disks[i-1].start_sector +
161                         conf->disks[i-1].num_sectors;
162
163         return conf;
164
165 out:
166         kfree(conf);
167         return NULL;
168 }
169
170 static int linear_run (mddev_t *mddev)
171 {
172         linear_conf_t *conf;
173
174         mddev->queue->queue_lock = &mddev->queue->__queue_lock;
175         conf = linear_conf(mddev, mddev->raid_disks);
176
177         if (!conf)
178                 return 1;
179         mddev->private = conf;
180         md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
181
182         blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
183         mddev->queue->unplug_fn = linear_unplug;
184         mddev->queue->backing_dev_info.congested_fn = linear_congested;
185         mddev->queue->backing_dev_info.congested_data = mddev;
186         return 0;
187 }
188
189 static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev)
190 {
191         /* Adding a drive to a linear array allows the array to grow.
192          * It is permitted if the new drive has a matching superblock
193          * already on it, with raid_disk equal to raid_disks.
194          * It is achieved by creating a new linear_private_data structure
195          * and swapping it in in-place of the current one.
196          * The current one is never freed until the array is stopped.
197          * This avoids races.
198          */
199         linear_conf_t *newconf;
200
201         if (rdev->saved_raid_disk != mddev->raid_disks)
202                 return -EINVAL;
203
204         rdev->raid_disk = rdev->saved_raid_disk;
205
206         newconf = linear_conf(mddev,mddev->raid_disks+1);
207
208         if (!newconf)
209                 return -ENOMEM;
210
211         newconf->prev = mddev->private;
212         mddev->private = newconf;
213         mddev->raid_disks++;
214         md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
215         set_capacity(mddev->gendisk, mddev->array_sectors);
216         return 0;
217 }
218
219 static int linear_stop (mddev_t *mddev)
220 {
221         linear_conf_t *conf = mddev->private;
222   
223         blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
224         do {
225                 linear_conf_t *t = conf->prev;
226                 kfree(conf);
227                 conf = t;
228         } while (conf);
229
230         return 0;
231 }
232
233 static int linear_make_request (struct request_queue *q, struct bio *bio)
234 {
235         const int rw = bio_data_dir(bio);
236         mddev_t *mddev = q->queuedata;
237         dev_info_t *tmp_dev;
238         int cpu;
239
240         if (unlikely(bio_barrier(bio))) {
241                 bio_endio(bio, -EOPNOTSUPP);
242                 return 0;
243         }
244
245         cpu = part_stat_lock();
246         part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
247         part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
248                       bio_sectors(bio));
249         part_stat_unlock();
250
251         tmp_dev = which_dev(mddev, bio->bi_sector);
252     
253         if (unlikely(bio->bi_sector >= (tmp_dev->num_sectors +
254                                         tmp_dev->start_sector)
255                      || (bio->bi_sector <
256                          tmp_dev->start_sector))) {
257                 char b[BDEVNAME_SIZE];
258
259                 printk("linear_make_request: Sector %llu out of bounds on "
260                         "dev %s: %llu sectors, offset %llu\n",
261                         (unsigned long long)bio->bi_sector,
262                         bdevname(tmp_dev->rdev->bdev, b),
263                         (unsigned long long)tmp_dev->num_sectors,
264                         (unsigned long long)tmp_dev->start_sector);
265                 bio_io_error(bio);
266                 return 0;
267         }
268         if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
269                      tmp_dev->start_sector + tmp_dev->num_sectors)) {
270                 /* This bio crosses a device boundary, so we have to
271                  * split it.
272                  */
273                 struct bio_pair *bp;
274
275                 bp = bio_split(bio,
276                                tmp_dev->start_sector + tmp_dev->num_sectors
277                                - bio->bi_sector);
278
279                 if (linear_make_request(q, &bp->bio1))
280                         generic_make_request(&bp->bio1);
281                 if (linear_make_request(q, &bp->bio2))
282                         generic_make_request(&bp->bio2);
283                 bio_pair_release(bp);
284                 return 0;
285         }
286                     
287         bio->bi_bdev = tmp_dev->rdev->bdev;
288         bio->bi_sector = bio->bi_sector - tmp_dev->start_sector
289                 + tmp_dev->rdev->data_offset;
290
291         return 1;
292 }
293
294 static void linear_status (struct seq_file *seq, mddev_t *mddev)
295 {
296
297         seq_printf(seq, " %dk rounding", mddev->chunk_size/1024);
298 }
299
300
301 static struct mdk_personality linear_personality =
302 {
303         .name           = "linear",
304         .level          = LEVEL_LINEAR,
305         .owner          = THIS_MODULE,
306         .make_request   = linear_make_request,
307         .run            = linear_run,
308         .stop           = linear_stop,
309         .status         = linear_status,
310         .hot_add_disk   = linear_add,
311         .size           = linear_size,
312 };
313
314 static int __init linear_init (void)
315 {
316         return register_md_personality (&linear_personality);
317 }
318
319 static void linear_exit (void)
320 {
321         unregister_md_personality (&linear_personality);
322 }
323
324
325 module_init(linear_init);
326 module_exit(linear_exit);
327 MODULE_LICENSE("GPL");
328 MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/
329 MODULE_ALIAS("md-linear");
330 MODULE_ALIAS("md-level--1");