| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | linear.c : Multiple Devices driver for Linux |
|---|
| 3 | 4 | Copyright (C) 1994-96 Marc ZYNGIER |
|---|
| .. | .. |
|---|
| 6 | 7 | |
|---|
| 7 | 8 | Linear mode management functions. |
|---|
| 8 | 9 | |
|---|
| 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 | 10 | */ |
|---|
| 18 | 11 | |
|---|
| 19 | 12 | #include <linux/blkdev.h> |
|---|
| .. | .. |
|---|
| 53 | 46 | return conf->disks + lo; |
|---|
| 54 | 47 | } |
|---|
| 55 | 48 | |
|---|
| 56 | | -/* |
|---|
| 57 | | - * In linear_congested() conf->raid_disks is used as a copy of |
|---|
| 58 | | - * mddev->raid_disks to iterate conf->disks[], because conf->raid_disks |
|---|
| 59 | | - * and conf->disks[] are created in linear_conf(), they are always |
|---|
| 60 | | - * consitent with each other, but mddev->raid_disks does not. |
|---|
| 61 | | - */ |
|---|
| 62 | | -static int linear_congested(struct mddev *mddev, int bits) |
|---|
| 63 | | -{ |
|---|
| 64 | | - struct linear_conf *conf; |
|---|
| 65 | | - int i, ret = 0; |
|---|
| 66 | | - |
|---|
| 67 | | - rcu_read_lock(); |
|---|
| 68 | | - conf = rcu_dereference(mddev->private); |
|---|
| 69 | | - |
|---|
| 70 | | - for (i = 0; i < conf->raid_disks && !ret ; i++) { |
|---|
| 71 | | - struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev); |
|---|
| 72 | | - ret |= bdi_congested(q->backing_dev_info, bits); |
|---|
| 73 | | - } |
|---|
| 74 | | - |
|---|
| 75 | | - rcu_read_unlock(); |
|---|
| 76 | | - return ret; |
|---|
| 77 | | -} |
|---|
| 78 | | - |
|---|
| 79 | 49 | static sector_t linear_size(struct mddev *mddev, sector_t sectors, int raid_disks) |
|---|
| 80 | 50 | { |
|---|
| 81 | 51 | struct linear_conf *conf; |
|---|
| .. | .. |
|---|
| 96 | 66 | int i, cnt; |
|---|
| 97 | 67 | bool discard_supported = false; |
|---|
| 98 | 68 | |
|---|
| 99 | | - conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info), |
|---|
| 100 | | - GFP_KERNEL); |
|---|
| 69 | + conf = kzalloc(struct_size(conf, disks, raid_disks), GFP_KERNEL); |
|---|
| 101 | 70 | if (!conf) |
|---|
| 102 | 71 | return NULL; |
|---|
| 103 | 72 | |
|---|
| .. | .. |
|---|
| 233 | 202 | md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); |
|---|
| 234 | 203 | set_capacity(mddev->gendisk, mddev->array_sectors); |
|---|
| 235 | 204 | mddev_resume(mddev); |
|---|
| 236 | | - revalidate_disk(mddev->gendisk); |
|---|
| 205 | + revalidate_disk_size(mddev->gendisk, true); |
|---|
| 237 | 206 | kfree_rcu(oldconf, rcu); |
|---|
| 238 | 207 | return 0; |
|---|
| 239 | 208 | } |
|---|
| .. | .. |
|---|
| 265 | 234 | bio_sector < start_sector)) |
|---|
| 266 | 235 | goto out_of_bounds; |
|---|
| 267 | 236 | |
|---|
| 237 | + if (unlikely(is_mddev_broken(tmp_dev->rdev, "linear"))) { |
|---|
| 238 | + bio_io_error(bio); |
|---|
| 239 | + return true; |
|---|
| 240 | + } |
|---|
| 241 | + |
|---|
| 268 | 242 | if (unlikely(bio_end_sector(bio) > end_sector)) { |
|---|
| 269 | 243 | /* This bio crosses a device boundary, so we have to split it */ |
|---|
| 270 | 244 | struct bio *split = bio_split(bio, end_sector - bio_sector, |
|---|
| 271 | 245 | GFP_NOIO, &mddev->bio_set); |
|---|
| 272 | 246 | bio_chain(split, bio); |
|---|
| 273 | | - generic_make_request(bio); |
|---|
| 247 | + submit_bio_noacct(bio); |
|---|
| 274 | 248 | bio = split; |
|---|
| 275 | 249 | } |
|---|
| 276 | 250 | |
|---|
| .. | .. |
|---|
| 289 | 263 | bio_sector); |
|---|
| 290 | 264 | mddev_check_writesame(mddev, bio); |
|---|
| 291 | 265 | mddev_check_write_zeroes(mddev, bio); |
|---|
| 292 | | - generic_make_request(bio); |
|---|
| 266 | + submit_bio_noacct(bio); |
|---|
| 293 | 267 | } |
|---|
| 294 | 268 | return true; |
|---|
| 295 | 269 | |
|---|
| .. | .. |
|---|
| 325 | 299 | .hot_add_disk = linear_add, |
|---|
| 326 | 300 | .size = linear_size, |
|---|
| 327 | 301 | .quiesce = linear_quiesce, |
|---|
| 328 | | - .congested = linear_congested, |
|---|
| 329 | 302 | }; |
|---|
| 330 | 303 | |
|---|
| 331 | 304 | static int __init linear_init (void) |
|---|