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 <linux/module.h>
23 #include <linux/slab.h>
24 #include "md.h"
25 #include "linear.h"
26 
27 /*
28  * find which device holds a particular offset
29  */
which_dev(struct mddev * mddev,sector_t sector)30 static inline struct dev_info *which_dev(struct mddev *mddev, sector_t sector)
31 {
32 	int lo, mid, hi;
33 	struct linear_conf *conf;
34 
35 	lo = 0;
36 	hi = mddev->raid_disks - 1;
37 	conf = rcu_dereference(mddev->private);
38 
39 	/*
40 	 * Binary Search
41 	 */
42 
43 	while (hi > lo) {
44 
45 		mid = (hi + lo) / 2;
46 		if (sector < conf->disks[mid].end_sector)
47 			hi = mid;
48 		else
49 			lo = mid + 1;
50 	}
51 
52 	return conf->disks + lo;
53 }
54 
55 /**
56  *	linear_mergeable_bvec -- tell bio layer if two requests can be merged
57  *	@q: request queue
58  *	@bvm: properties of new bio
59  *	@biovec: the request that could be merged to it.
60  *
61  *	Return amount of bytes we can take at this offset
62  */
linear_mergeable_bvec(struct request_queue * q,struct bvec_merge_data * bvm,struct bio_vec * biovec)63 static int linear_mergeable_bvec(struct request_queue *q,
64 				 struct bvec_merge_data *bvm,
65 				 struct bio_vec *biovec)
66 {
67 	struct mddev *mddev = q->queuedata;
68 	struct dev_info *dev0;
69 	unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9;
70 	sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev);
71 
72 	rcu_read_lock();
73 	dev0 = which_dev(mddev, sector);
74 	maxsectors = dev0->end_sector - sector;
75 	rcu_read_unlock();
76 
77 	if (maxsectors < bio_sectors)
78 		maxsectors = 0;
79 	else
80 		maxsectors -= bio_sectors;
81 
82 	if (maxsectors <= (PAGE_SIZE >> 9 ) && bio_sectors == 0)
83 		return biovec->bv_len;
84 	/* The bytes available at this offset could be really big,
85 	 * so we cap at 2^31 to avoid overflow */
86 	if (maxsectors > (1 << (31-9)))
87 		return 1<<31;
88 	return maxsectors << 9;
89 }
90 
linear_congested(void * data,int bits)91 static int linear_congested(void *data, int bits)
92 {
93 	struct mddev *mddev = data;
94 	struct linear_conf *conf;
95 	int i, ret = 0;
96 
97 	if (mddev_congested(mddev, bits))
98 		return 1;
99 
100 	rcu_read_lock();
101 	conf = rcu_dereference(mddev->private);
102 
103 	for (i = 0; i < mddev->raid_disks && !ret ; i++) {
104 		struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
105 		ret |= bdi_congested(&q->backing_dev_info, bits);
106 	}
107 
108 	rcu_read_unlock();
109 	return ret;
110 }
111 
linear_size(struct mddev * mddev,sector_t sectors,int raid_disks)112 static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disks)
113 {
114 	struct linear_conf *conf;
115 	sector_t array_sectors;
116 
117 	rcu_read_lock();
118 	conf = rcu_dereference(mddev->private);
119 	WARN_ONCE(sectors || raid_disks,
120 		  "%s does not support generic reshape\n", __func__);
121 	array_sectors = conf->array_sectors;
122 	rcu_read_unlock();
123 
124 	return array_sectors;
125 }
126 
linear_conf(struct mddev * mddev,int raid_disks)127 static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
128 {
129 	struct linear_conf *conf;
130 	struct md_rdev *rdev;
131 	int i, cnt;
132 
133 	conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info),
134 			GFP_KERNEL);
135 	if (!conf)
136 		return NULL;
137 
138 	cnt = 0;
139 	conf->array_sectors = 0;
140 
141 	list_for_each_entry(rdev, &mddev->disks, same_set) {
142 		int j = rdev->raid_disk;
143 		struct dev_info *disk = conf->disks + j;
144 		sector_t sectors;
145 
146 		if (j < 0 || j >= raid_disks || disk->rdev) {
147 			printk(KERN_ERR "md/linear:%s: disk numbering problem. Aborting!\n",
148 			       mdname(mddev));
149 			goto out;
150 		}
151 
152 		disk->rdev = rdev;
153 		if (mddev->chunk_sectors) {
154 			sectors = rdev->sectors;
155 			sector_div(sectors, mddev->chunk_sectors);
156 			rdev->sectors = sectors * mddev->chunk_sectors;
157 		}
158 
159 		disk_stack_limits(mddev->gendisk, rdev->bdev,
160 				  rdev->data_offset << 9);
161 		/* as we don't honour merge_bvec_fn, we must never risk
162 		 * violating it, so limit max_segments to 1 lying within
163 		 * a single page.
164 		 */
165 		if (rdev->bdev->bd_disk->queue->merge_bvec_fn) {
166 			blk_queue_max_segments(mddev->queue, 1);
167 			blk_queue_segment_boundary(mddev->queue,
168 						   PAGE_CACHE_SIZE - 1);
169 		}
170 
171 		conf->array_sectors += rdev->sectors;
172 		cnt++;
173 
174 	}
175 	if (cnt != raid_disks) {
176 		printk(KERN_ERR "md/linear:%s: not enough drives present. Aborting!\n",
177 		       mdname(mddev));
178 		goto out;
179 	}
180 
181 	/*
182 	 * Here we calculate the device offsets.
183 	 */
184 	conf->disks[0].end_sector = conf->disks[0].rdev->sectors;
185 
186 	for (i = 1; i < raid_disks; i++)
187 		conf->disks[i].end_sector =
188 			conf->disks[i-1].end_sector +
189 			conf->disks[i].rdev->sectors;
190 
191 	return conf;
192 
193 out:
194 	kfree(conf);
195 	return NULL;
196 }
197 
linear_run(struct mddev * mddev)198 static int linear_run (struct mddev *mddev)
199 {
200 	struct linear_conf *conf;
201 
202 	if (md_check_no_bitmap(mddev))
203 		return -EINVAL;
204 	conf = linear_conf(mddev, mddev->raid_disks);
205 
206 	if (!conf)
207 		return 1;
208 	mddev->private = conf;
209 	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
210 
211 	blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
212 	mddev->queue->backing_dev_info.congested_fn = linear_congested;
213 	mddev->queue->backing_dev_info.congested_data = mddev;
214 	return md_integrity_register(mddev);
215 }
216 
linear_add(struct mddev * mddev,struct md_rdev * rdev)217 static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
218 {
219 	/* Adding a drive to a linear array allows the array to grow.
220 	 * It is permitted if the new drive has a matching superblock
221 	 * already on it, with raid_disk equal to raid_disks.
222 	 * It is achieved by creating a new linear_private_data structure
223 	 * and swapping it in in-place of the current one.
224 	 * The current one is never freed until the array is stopped.
225 	 * This avoids races.
226 	 */
227 	struct linear_conf *newconf, *oldconf;
228 
229 	if (rdev->saved_raid_disk != mddev->raid_disks)
230 		return -EINVAL;
231 
232 	rdev->raid_disk = rdev->saved_raid_disk;
233 	rdev->saved_raid_disk = -1;
234 
235 	newconf = linear_conf(mddev,mddev->raid_disks+1);
236 
237 	if (!newconf)
238 		return -ENOMEM;
239 
240 	oldconf = rcu_dereference(mddev->private);
241 	mddev->raid_disks++;
242 	rcu_assign_pointer(mddev->private, newconf);
243 	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
244 	set_capacity(mddev->gendisk, mddev->array_sectors);
245 	revalidate_disk(mddev->gendisk);
246 	kfree_rcu(oldconf, rcu);
247 	return 0;
248 }
249 
linear_stop(struct mddev * mddev)250 static int linear_stop (struct mddev *mddev)
251 {
252 	struct linear_conf *conf = mddev->private;
253 
254 	/*
255 	 * We do not require rcu protection here since
256 	 * we hold reconfig_mutex for both linear_add and
257 	 * linear_stop, so they cannot race.
258 	 * We should make sure any old 'conf's are properly
259 	 * freed though.
260 	 */
261 	rcu_barrier();
262 	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
263 	kfree(conf);
264 	mddev->private = NULL;
265 
266 	return 0;
267 }
268 
linear_make_request(struct mddev * mddev,struct bio * bio)269 static void linear_make_request(struct mddev *mddev, struct bio *bio)
270 {
271 	struct dev_info *tmp_dev;
272 	sector_t start_sector;
273 
274 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
275 		md_flush_request(mddev, bio);
276 		return;
277 	}
278 
279 	rcu_read_lock();
280 	tmp_dev = which_dev(mddev, bio->bi_sector);
281 	start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
282 
283 
284 	if (unlikely(bio->bi_sector >= (tmp_dev->end_sector)
285 		     || (bio->bi_sector < start_sector))) {
286 		char b[BDEVNAME_SIZE];
287 
288 		printk(KERN_ERR
289 		       "md/linear:%s: make_request: Sector %llu out of bounds on "
290 		       "dev %s: %llu sectors, offset %llu\n",
291 		       mdname(mddev),
292 		       (unsigned long long)bio->bi_sector,
293 		       bdevname(tmp_dev->rdev->bdev, b),
294 		       (unsigned long long)tmp_dev->rdev->sectors,
295 		       (unsigned long long)start_sector);
296 		rcu_read_unlock();
297 		bio_io_error(bio);
298 		return;
299 	}
300 	if (unlikely(bio->bi_sector + (bio->bi_size >> 9) >
301 		     tmp_dev->end_sector)) {
302 		/* This bio crosses a device boundary, so we have to
303 		 * split it.
304 		 */
305 		struct bio_pair *bp;
306 		sector_t end_sector = tmp_dev->end_sector;
307 
308 		rcu_read_unlock();
309 
310 		bp = bio_split(bio, end_sector - bio->bi_sector);
311 
312 		linear_make_request(mddev, &bp->bio1);
313 		linear_make_request(mddev, &bp->bio2);
314 		bio_pair_release(bp);
315 		return;
316 	}
317 
318 	bio->bi_bdev = tmp_dev->rdev->bdev;
319 	bio->bi_sector = bio->bi_sector - start_sector
320 		+ tmp_dev->rdev->data_offset;
321 	rcu_read_unlock();
322 	generic_make_request(bio);
323 }
324 
linear_status(struct seq_file * seq,struct mddev * mddev)325 static void linear_status (struct seq_file *seq, struct mddev *mddev)
326 {
327 
328 	seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2);
329 }
330 
331 
332 static struct md_personality linear_personality =
333 {
334 	.name		= "linear",
335 	.level		= LEVEL_LINEAR,
336 	.owner		= THIS_MODULE,
337 	.make_request	= linear_make_request,
338 	.run		= linear_run,
339 	.stop		= linear_stop,
340 	.status		= linear_status,
341 	.hot_add_disk	= linear_add,
342 	.size		= linear_size,
343 };
344 
linear_init(void)345 static int __init linear_init (void)
346 {
347 	return register_md_personality (&linear_personality);
348 }
349 
linear_exit(void)350 static void linear_exit (void)
351 {
352 	unregister_md_personality (&linear_personality);
353 }
354 
355 
356 module_init(linear_init);
357 module_exit(linear_exit);
358 MODULE_LICENSE("GPL");
359 MODULE_DESCRIPTION("Linear device concatenation personality for MD");
360 MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/
361 MODULE_ALIAS("md-linear");
362 MODULE_ALIAS("md-level--1");
363