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 */ 30static 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 = 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 */ 63static int linear_mergeable_bvec(struct mddev *mddev, 64 struct bvec_merge_data *bvm, 65 struct bio_vec *biovec) 66{ 67 struct dev_info *dev0; 68 unsigned long maxsectors, bio_sectors = bvm->bi_size >> 9; 69 sector_t sector = bvm->bi_sector + get_start_sect(bvm->bi_bdev); 70 int maxbytes = biovec->bv_len; 71 struct request_queue *subq; 72 73 dev0 = which_dev(mddev, sector); 74 maxsectors = dev0->end_sector - sector; 75 subq = bdev_get_queue(dev0->rdev->bdev); 76 if (subq->merge_bvec_fn) { 77 bvm->bi_bdev = dev0->rdev->bdev; 78 bvm->bi_sector -= dev0->end_sector - dev0->rdev->sectors; 79 maxbytes = min(maxbytes, subq->merge_bvec_fn(subq, bvm, 80 biovec)); 81 } 82 83 if (maxsectors < bio_sectors) 84 maxsectors = 0; 85 else 86 maxsectors -= bio_sectors; 87 88 if (maxsectors <= (PAGE_SIZE >> 9 ) && bio_sectors == 0) 89 return maxbytes; 90 91 if (maxsectors > (maxbytes >> 9)) 92 return maxbytes; 93 else 94 return maxsectors << 9; 95} 96 97static int linear_congested(struct mddev *mddev, int bits) 98{ 99 struct linear_conf *conf; 100 int i, ret = 0; 101 102 conf = mddev->private; 103 104 for (i = 0; i < mddev->raid_disks && !ret ; i++) { 105 struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev); 106 ret |= bdi_congested(&q->backing_dev_info, bits); 107 } 108 109 return ret; 110} 111 112static 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 conf = mddev->private; 118 WARN_ONCE(sectors || raid_disks, 119 "%s does not support generic reshape\n", __func__); 120 array_sectors = conf->array_sectors; 121 122 return array_sectors; 123} 124 125static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks) 126{ 127 struct linear_conf *conf; 128 struct md_rdev *rdev; 129 int i, cnt; 130 bool discard_supported = false; 131 132 conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info), 133 GFP_KERNEL); 134 if (!conf) 135 return NULL; 136 137 cnt = 0; 138 conf->array_sectors = 0; 139 140 rdev_for_each(rdev, mddev) { 141 int j = rdev->raid_disk; 142 struct dev_info *disk = conf->disks + j; 143 sector_t sectors; 144 145 if (j < 0 || j >= raid_disks || disk->rdev) { 146 printk(KERN_ERR "md/linear:%s: disk numbering problem. Aborting!\n", 147 mdname(mddev)); 148 goto out; 149 } 150 151 disk->rdev = rdev; 152 if (mddev->chunk_sectors) { 153 sectors = rdev->sectors; 154 sector_div(sectors, mddev->chunk_sectors); 155 rdev->sectors = sectors * mddev->chunk_sectors; 156 } 157 158 disk_stack_limits(mddev->gendisk, rdev->bdev, 159 rdev->data_offset << 9); 160 161 conf->array_sectors += rdev->sectors; 162 cnt++; 163 164 if (blk_queue_discard(bdev_get_queue(rdev->bdev))) 165 discard_supported = true; 166 } 167 if (cnt != raid_disks) { 168 printk(KERN_ERR "md/linear:%s: not enough drives present. Aborting!\n", 169 mdname(mddev)); 170 goto out; 171 } 172 173 if (!discard_supported) 174 queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); 175 else 176 queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); 177 178 /* 179 * Here we calculate the device offsets. 180 */ 181 conf->disks[0].end_sector = conf->disks[0].rdev->sectors; 182 183 for (i = 1; i < raid_disks; i++) 184 conf->disks[i].end_sector = 185 conf->disks[i-1].end_sector + 186 conf->disks[i].rdev->sectors; 187 188 return conf; 189 190out: 191 kfree(conf); 192 return NULL; 193} 194 195static int linear_run (struct mddev *mddev) 196{ 197 struct linear_conf *conf; 198 int ret; 199 200 if (md_check_no_bitmap(mddev)) 201 return -EINVAL; 202 conf = linear_conf(mddev, mddev->raid_disks); 203 204 if (!conf) 205 return 1; 206 mddev->private = conf; 207 md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); 208 209 ret = md_integrity_register(mddev); 210 if (ret) { 211 kfree(conf); 212 mddev->private = NULL; 213 } 214 return ret; 215} 216 217static 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 mddev_suspend(mddev); 241 oldconf = mddev->private; 242 mddev->raid_disks++; 243 mddev->private = newconf; 244 md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); 245 set_capacity(mddev->gendisk, mddev->array_sectors); 246 mddev_resume(mddev); 247 revalidate_disk(mddev->gendisk); 248 kfree(oldconf); 249 return 0; 250} 251 252static void linear_free(struct mddev *mddev, void *priv) 253{ 254 struct linear_conf *conf = priv; 255 256 kfree(conf); 257} 258 259static void linear_make_request(struct mddev *mddev, struct bio *bio) 260{ 261 char b[BDEVNAME_SIZE]; 262 struct dev_info *tmp_dev; 263 struct bio *split; 264 sector_t start_sector, end_sector, data_offset; 265 266 if (unlikely(bio->bi_rw & REQ_FLUSH)) { 267 md_flush_request(mddev, bio); 268 return; 269 } 270 271 do { 272 tmp_dev = which_dev(mddev, bio->bi_iter.bi_sector); 273 start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; 274 end_sector = tmp_dev->end_sector; 275 data_offset = tmp_dev->rdev->data_offset; 276 bio->bi_bdev = tmp_dev->rdev->bdev; 277 278 if (unlikely(bio->bi_iter.bi_sector >= end_sector || 279 bio->bi_iter.bi_sector < start_sector)) 280 goto out_of_bounds; 281 282 if (unlikely(bio_end_sector(bio) > end_sector)) { 283 /* This bio crosses a device boundary, so we have to 284 * split it. 285 */ 286 split = bio_split(bio, end_sector - 287 bio->bi_iter.bi_sector, 288 GFP_NOIO, fs_bio_set); 289 bio_chain(split, bio); 290 } else { 291 split = bio; 292 } 293 294 split->bi_iter.bi_sector = split->bi_iter.bi_sector - 295 start_sector + data_offset; 296 297 if (unlikely((split->bi_rw & REQ_DISCARD) && 298 !blk_queue_discard(bdev_get_queue(split->bi_bdev)))) { 299 /* Just ignore it */ 300 bio_endio(split, 0); 301 } else 302 generic_make_request(split); 303 } while (split != bio); 304 return; 305 306out_of_bounds: 307 printk(KERN_ERR 308 "md/linear:%s: make_request: Sector %llu out of bounds on " 309 "dev %s: %llu sectors, offset %llu\n", 310 mdname(mddev), 311 (unsigned long long)bio->bi_iter.bi_sector, 312 bdevname(tmp_dev->rdev->bdev, b), 313 (unsigned long long)tmp_dev->rdev->sectors, 314 (unsigned long long)start_sector); 315 bio_io_error(bio); 316} 317 318static void linear_status (struct seq_file *seq, struct mddev *mddev) 319{ 320 321 seq_printf(seq, " %dk rounding", mddev->chunk_sectors / 2); 322} 323 324static void linear_quiesce(struct mddev *mddev, int state) 325{ 326} 327 328static struct md_personality linear_personality = 329{ 330 .name = "linear", 331 .level = LEVEL_LINEAR, 332 .owner = THIS_MODULE, 333 .make_request = linear_make_request, 334 .run = linear_run, 335 .free = linear_free, 336 .status = linear_status, 337 .hot_add_disk = linear_add, 338 .size = linear_size, 339 .quiesce = linear_quiesce, 340 .congested = linear_congested, 341 .mergeable_bvec = linear_mergeable_bvec, 342}; 343 344static int __init linear_init (void) 345{ 346 return register_md_personality (&linear_personality); 347} 348 349static void linear_exit (void) 350{ 351 unregister_md_personality (&linear_personality); 352} 353 354module_init(linear_init); 355module_exit(linear_exit); 356MODULE_LICENSE("GPL"); 357MODULE_DESCRIPTION("Linear device concatenation personality for MD"); 358MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/ 359MODULE_ALIAS("md-linear"); 360MODULE_ALIAS("md-level--1"); 361