| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | raid0.c : Multiple Devices driver for Linux |
|---|
| 3 | 4 | Copyright (C) 1994-96 Marc ZYNGIER |
|---|
| .. | .. |
|---|
| 7 | 8 | |
|---|
| 8 | 9 | RAID-0 management functions. |
|---|
| 9 | 10 | |
|---|
| 10 | | - This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - it under the terms of the GNU General Public License as published by |
|---|
| 12 | | - the Free Software Foundation; either version 2, or (at your option) |
|---|
| 13 | | - any later version. |
|---|
| 14 | | - |
|---|
| 15 | | - You should have received a copy of the GNU General Public License |
|---|
| 16 | | - (for example /usr/src/linux/COPYING); if not, write to the Free |
|---|
| 17 | | - Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
|---|
| 18 | 11 | */ |
|---|
| 19 | 12 | |
|---|
| 20 | 13 | #include <linux/blkdev.h> |
|---|
| .. | .. |
|---|
| 36 | 29 | (1L << MD_HAS_PPL) | \ |
|---|
| 37 | 30 | (1L << MD_HAS_MULTIPLE_PPLS)) |
|---|
| 38 | 31 | |
|---|
| 39 | | -static int raid0_congested(struct mddev *mddev, int bits) |
|---|
| 40 | | -{ |
|---|
| 41 | | - struct r0conf *conf = mddev->private; |
|---|
| 42 | | - struct md_rdev **devlist = conf->devlist; |
|---|
| 43 | | - int raid_disks = conf->strip_zone[0].nb_dev; |
|---|
| 44 | | - int i, ret = 0; |
|---|
| 45 | | - |
|---|
| 46 | | - for (i = 0; i < raid_disks && !ret ; i++) { |
|---|
| 47 | | - struct request_queue *q = bdev_get_queue(devlist[i]->bdev); |
|---|
| 48 | | - |
|---|
| 49 | | - ret |= bdi_congested(q->backing_dev_info, bits); |
|---|
| 50 | | - } |
|---|
| 51 | | - return ret; |
|---|
| 52 | | -} |
|---|
| 53 | | - |
|---|
| 54 | 32 | /* |
|---|
| 55 | 33 | * inform the user of the raid configuration |
|---|
| 56 | 34 | */ |
|---|
| .. | .. |
|---|
| 70 | 48 | int len = 0; |
|---|
| 71 | 49 | |
|---|
| 72 | 50 | for (k = 0; k < conf->strip_zone[j].nb_dev; k++) |
|---|
| 73 | | - len += snprintf(line+len, 200-len, "%s%s", k?"/":"", |
|---|
| 51 | + len += scnprintf(line+len, 200-len, "%s%s", k?"/":"", |
|---|
| 74 | 52 | bdevname(conf->devlist[j*raid_disks |
|---|
| 75 | 53 | + k]->bdev, b)); |
|---|
| 76 | 54 | pr_debug("md: zone%d=[%s]\n", j, line); |
|---|
| .. | .. |
|---|
| 150 | 128 | pr_debug("md/raid0:%s: FINAL %d zones\n", |
|---|
| 151 | 129 | mdname(mddev), conf->nr_strip_zones); |
|---|
| 152 | 130 | |
|---|
| 153 | | - if (conf->nr_strip_zones == 1) { |
|---|
| 154 | | - conf->layout = RAID0_ORIG_LAYOUT; |
|---|
| 155 | | - } else if (mddev->layout == RAID0_ORIG_LAYOUT || |
|---|
| 156 | | - mddev->layout == RAID0_ALT_MULTIZONE_LAYOUT) { |
|---|
| 157 | | - conf->layout = mddev->layout; |
|---|
| 158 | | - } else if (default_layout == RAID0_ORIG_LAYOUT || |
|---|
| 159 | | - default_layout == RAID0_ALT_MULTIZONE_LAYOUT) { |
|---|
| 160 | | - conf->layout = default_layout; |
|---|
| 161 | | - } else { |
|---|
| 162 | | - pr_err("md/raid0:%s: cannot assemble multi-zone RAID0 with default_layout setting\n", |
|---|
| 163 | | - mdname(mddev)); |
|---|
| 164 | | - pr_err("md/raid0: please set raid0.default_layout to 1 or 2\n"); |
|---|
| 165 | | - err = -ENOTSUPP; |
|---|
| 166 | | - goto abort; |
|---|
| 167 | | - } |
|---|
| 168 | 131 | /* |
|---|
| 169 | 132 | * now since we have the hard sector sizes, we can make sure |
|---|
| 170 | 133 | * chunk size is a multiple of that sector size |
|---|
| .. | .. |
|---|
| 293 | 256 | pr_debug("md/raid0:%s: current zone start: %llu\n", |
|---|
| 294 | 257 | mdname(mddev), |
|---|
| 295 | 258 | (unsigned long long)smallest->sectors); |
|---|
| 259 | + } |
|---|
| 260 | + |
|---|
| 261 | + if (conf->nr_strip_zones == 1 || conf->strip_zone[1].nb_dev == 1) { |
|---|
| 262 | + conf->layout = RAID0_ORIG_LAYOUT; |
|---|
| 263 | + } else if (mddev->layout == RAID0_ORIG_LAYOUT || |
|---|
| 264 | + mddev->layout == RAID0_ALT_MULTIZONE_LAYOUT) { |
|---|
| 265 | + conf->layout = mddev->layout; |
|---|
| 266 | + } else if (default_layout == RAID0_ORIG_LAYOUT || |
|---|
| 267 | + default_layout == RAID0_ALT_MULTIZONE_LAYOUT) { |
|---|
| 268 | + conf->layout = default_layout; |
|---|
| 269 | + } else { |
|---|
| 270 | + pr_err("md/raid0:%s: cannot assemble multi-zone RAID0 with default_layout setting\n", |
|---|
| 271 | + mdname(mddev)); |
|---|
| 272 | + pr_err("md/raid0: please set raid0.default_layout to 1 or 2\n"); |
|---|
| 273 | + err = -EOPNOTSUPP; |
|---|
| 274 | + goto abort; |
|---|
| 296 | 275 | } |
|---|
| 297 | 276 | |
|---|
| 298 | 277 | pr_debug("md/raid0:%s: done.\n", mdname(mddev)); |
|---|
| .. | .. |
|---|
| 432 | 411 | mdname(mddev), |
|---|
| 433 | 412 | (unsigned long long)mddev->array_sectors); |
|---|
| 434 | 413 | |
|---|
| 435 | | - if (mddev->queue) { |
|---|
| 436 | | - /* calculate the max read-ahead size. |
|---|
| 437 | | - * For read-ahead of large files to be effective, we need to |
|---|
| 438 | | - * readahead at least twice a whole stripe. i.e. number of devices |
|---|
| 439 | | - * multiplied by chunk size times 2. |
|---|
| 440 | | - * If an individual device has an ra_pages greater than the |
|---|
| 441 | | - * chunk size, then we will not drive that device as hard as it |
|---|
| 442 | | - * wants. We consider this a configuration error: a larger |
|---|
| 443 | | - * chunksize should be used in that case. |
|---|
| 444 | | - */ |
|---|
| 445 | | - int stripe = mddev->raid_disks * |
|---|
| 446 | | - (mddev->chunk_sectors << 9) / PAGE_SIZE; |
|---|
| 447 | | - if (mddev->queue->backing_dev_info->ra_pages < 2* stripe) |
|---|
| 448 | | - mddev->queue->backing_dev_info->ra_pages = 2* stripe; |
|---|
| 449 | | - } |
|---|
| 450 | | - |
|---|
| 451 | 414 | dump_zones(mddev); |
|---|
| 452 | 415 | |
|---|
| 453 | 416 | ret = md_integrity_register(mddev); |
|---|
| .. | .. |
|---|
| 462 | 425 | kfree(conf->strip_zone); |
|---|
| 463 | 426 | kfree(conf->devlist); |
|---|
| 464 | 427 | kfree(conf); |
|---|
| 465 | | -} |
|---|
| 466 | | - |
|---|
| 467 | | -/* |
|---|
| 468 | | - * Is io distribute over 1 or more chunks ? |
|---|
| 469 | | -*/ |
|---|
| 470 | | -static inline int is_io_in_chunk_boundary(struct mddev *mddev, |
|---|
| 471 | | - unsigned int chunk_sects, struct bio *bio) |
|---|
| 472 | | -{ |
|---|
| 473 | | - if (likely(is_power_of_2(chunk_sects))) { |
|---|
| 474 | | - return chunk_sects >= |
|---|
| 475 | | - ((bio->bi_iter.bi_sector & (chunk_sects-1)) |
|---|
| 476 | | - + bio_sectors(bio)); |
|---|
| 477 | | - } else{ |
|---|
| 478 | | - sector_t sector = bio->bi_iter.bi_sector; |
|---|
| 479 | | - return chunk_sects >= (sector_div(sector, chunk_sects) |
|---|
| 480 | | - + bio_sectors(bio)); |
|---|
| 481 | | - } |
|---|
| 482 | 428 | } |
|---|
| 483 | 429 | |
|---|
| 484 | 430 | static void raid0_handle_discard(struct mddev *mddev, struct bio *bio) |
|---|
| .. | .. |
|---|
| 502 | 448 | zone->zone_end - bio->bi_iter.bi_sector, GFP_NOIO, |
|---|
| 503 | 449 | &mddev->bio_set); |
|---|
| 504 | 450 | bio_chain(split, bio); |
|---|
| 505 | | - generic_make_request(bio); |
|---|
| 451 | + submit_bio_noacct(bio); |
|---|
| 506 | 452 | bio = split; |
|---|
| 507 | 453 | end = zone->zone_end; |
|---|
| 508 | 454 | } else |
|---|
| .. | .. |
|---|
| 561 | 507 | !discard_bio) |
|---|
| 562 | 508 | continue; |
|---|
| 563 | 509 | bio_chain(discard_bio, bio); |
|---|
| 564 | | - bio_clone_blkcg_association(discard_bio, bio); |
|---|
| 510 | + bio_clone_blkg_association(discard_bio, bio); |
|---|
| 565 | 511 | if (mddev->gendisk) |
|---|
| 566 | 512 | trace_block_bio_remap(bdev_get_queue(rdev->bdev), |
|---|
| 567 | 513 | discard_bio, disk_devt(mddev->gendisk), |
|---|
| 568 | 514 | bio->bi_iter.bi_sector); |
|---|
| 569 | | - bio_clear_flag(bio, BIO_QUEUE_ENTERED); |
|---|
| 570 | | - generic_make_request(discard_bio); |
|---|
| 515 | + submit_bio_noacct(discard_bio); |
|---|
| 571 | 516 | } |
|---|
| 572 | 517 | bio_endio(bio); |
|---|
| 573 | 518 | } |
|---|
| .. | .. |
|---|
| 608 | 553 | struct bio *split = bio_split(bio, sectors, GFP_NOIO, |
|---|
| 609 | 554 | &mddev->bio_set); |
|---|
| 610 | 555 | bio_chain(split, bio); |
|---|
| 611 | | - generic_make_request(bio); |
|---|
| 556 | + submit_bio_noacct(bio); |
|---|
| 612 | 557 | bio = split; |
|---|
| 613 | 558 | } |
|---|
| 614 | 559 | |
|---|
| .. | .. |
|---|
| 627 | 572 | return true; |
|---|
| 628 | 573 | } |
|---|
| 629 | 574 | |
|---|
| 575 | + if (unlikely(is_mddev_broken(tmp_dev, "raid0"))) { |
|---|
| 576 | + bio_io_error(bio); |
|---|
| 577 | + return true; |
|---|
| 578 | + } |
|---|
| 579 | + |
|---|
| 630 | 580 | bio_set_dev(bio, tmp_dev->bdev); |
|---|
| 631 | 581 | bio->bi_iter.bi_sector = sector + zone->dev_start + |
|---|
| 632 | 582 | tmp_dev->data_offset; |
|---|
| .. | .. |
|---|
| 636 | 586 | disk_devt(mddev->gendisk), bio_sector); |
|---|
| 637 | 587 | mddev_check_writesame(mddev, bio); |
|---|
| 638 | 588 | mddev_check_write_zeroes(mddev, bio); |
|---|
| 639 | | - bio_clear_flag(bio, BIO_QUEUE_ENTERED); |
|---|
| 640 | | - generic_make_request(bio); |
|---|
| 589 | + submit_bio_noacct(bio); |
|---|
| 641 | 590 | return true; |
|---|
| 642 | 591 | } |
|---|
| 643 | 592 | |
|---|
| .. | .. |
|---|
| 822 | 771 | .size = raid0_size, |
|---|
| 823 | 772 | .takeover = raid0_takeover, |
|---|
| 824 | 773 | .quiesce = raid0_quiesce, |
|---|
| 825 | | - .congested = raid0_congested, |
|---|
| 826 | 774 | }; |
|---|
| 827 | 775 | |
|---|
| 828 | 776 | static int __init raid0_init (void) |
|---|