Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'for-5.3/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm

Pull device mapper fixes from Mike Snitzer:

- Revert a DM bufio change from during the 5.3 merge window now that a
proper fix has been made to the block loopback driver.

- Fix DM kcopyd to wakeup so failed subjobs get completed.

- Various fixes to DM zoned target to address error handling, and other
small tweaks (SPDX license identifiers and fix typos).

- Fix DM integrity range locking race by tracking whether journal has
changed.

- Fix DM dust target to detect reads of badblocks beyond the first 512b
sector (applicable if blocksize is larger than 512b).

- Fix DM persistent-data issue in both the DM btree and DM
space-map-metadata interfaces.

- Fix out of bounds memory access with certain DM table configurations.

* tag 'for-5.3/dm-fixes-2' of git://git.kernel.org/pub/scm/linux/kernel/git/device-mapper/linux-dm:
dm table: fix invalid memory accesses with too high sector number
dm space map metadata: fix missing store of apply_bops() return value
dm btree: fix order of block initialization in btree_split_beneath
dm raid: add missing cleanup in raid_ctr()
dm zoned: fix potential NULL dereference in dmz_do_reclaim()
dm dust: use dust block size for badblocklist index
dm integrity: fix a crash due to BUG_ON in __journal_read_write()
dm zoned: fix a few typos
dm zoned: add SPDX license identifiers
dm zoned: properly handle backing device failure
dm zoned: improve error handling in i/o map code
dm zoned: improve error handling in reclaim
dm kcopyd: always complete failed jobs
Revert "dm bufio: fix deadlock with loop device"

+209 -60
+3 -1
drivers/md/dm-bufio.c
··· 1599 1599 unsigned long freed; 1600 1600 1601 1601 c = container_of(shrink, struct dm_bufio_client, shrinker); 1602 - if (!dm_bufio_trylock(c)) 1602 + if (sc->gfp_mask & __GFP_FS) 1603 + dm_bufio_lock(c); 1604 + else if (!dm_bufio_trylock(c)) 1603 1605 return SHRINK_STOP; 1604 1606 1605 1607 freed = __scan(c, sc->nr_to_scan, sc->gfp_mask);
+8 -3
drivers/md/dm-dust.c
··· 25 25 unsigned long long badblock_count; 26 26 spinlock_t dust_lock; 27 27 unsigned int blksz; 28 + int sect_per_block_shift; 28 29 unsigned int sect_per_block; 29 30 sector_t start; 30 31 bool fail_read_on_bb:1; ··· 80 79 unsigned long flags; 81 80 82 81 spin_lock_irqsave(&dd->dust_lock, flags); 83 - bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block); 82 + bblock = dust_rb_search(&dd->badblocklist, block); 84 83 85 84 if (bblock == NULL) { 86 85 if (!dd->quiet_mode) { ··· 114 113 } 115 114 116 115 spin_lock_irqsave(&dd->dust_lock, flags); 117 - bblock->bb = block * dd->sect_per_block; 116 + bblock->bb = block; 118 117 if (!dust_rb_insert(&dd->badblocklist, bblock)) { 119 118 if (!dd->quiet_mode) { 120 119 DMERR("%s: block %llu already in badblocklist", ··· 139 138 unsigned long flags; 140 139 141 140 spin_lock_irqsave(&dd->dust_lock, flags); 142 - bblock = dust_rb_search(&dd->badblocklist, block * dd->sect_per_block); 141 + bblock = dust_rb_search(&dd->badblocklist, block); 143 142 if (bblock != NULL) 144 143 DMINFO("%s: block %llu found in badblocklist", __func__, block); 145 144 else ··· 166 165 int ret = DM_MAPIO_REMAPPED; 167 166 168 167 if (fail_read_on_bb) { 168 + thisblock >>= dd->sect_per_block_shift; 169 169 spin_lock_irqsave(&dd->dust_lock, flags); 170 170 ret = __dust_map_read(dd, thisblock); 171 171 spin_unlock_irqrestore(&dd->dust_lock, flags); ··· 197 195 unsigned long flags; 198 196 199 197 if (fail_read_on_bb) { 198 + thisblock >>= dd->sect_per_block_shift; 200 199 spin_lock_irqsave(&dd->dust_lock, flags); 201 200 __dust_map_write(dd, thisblock); 202 201 spin_unlock_irqrestore(&dd->dust_lock, flags); ··· 333 330 dd->sect_per_block = sect_per_block; 334 331 dd->blksz = blksz; 335 332 dd->start = tmp; 333 + 334 + dd->sect_per_block_shift = __ffs(sect_per_block); 336 335 337 336 /* 338 337 * Whether to fail a read on a "bad" block.
+15
drivers/md/dm-integrity.c
··· 1943 1943 queue_work(ic->wait_wq, &dio->work); 1944 1944 return; 1945 1945 } 1946 + if (journal_read_pos != NOT_FOUND) 1947 + dio->range.n_sectors = ic->sectors_per_block; 1946 1948 wait_and_add_new_range(ic, &dio->range); 1949 + /* 1950 + * wait_and_add_new_range drops the spinlock, so the journal 1951 + * may have been changed arbitrarily. We need to recheck. 1952 + * To simplify the code, we restrict I/O size to just one block. 1953 + */ 1954 + if (journal_read_pos != NOT_FOUND) { 1955 + sector_t next_sector; 1956 + unsigned new_pos = find_journal_node(ic, dio->range.logical_sector, &next_sector); 1957 + if (unlikely(new_pos != journal_read_pos)) { 1958 + remove_range_unlocked(ic, &dio->range); 1959 + goto retry; 1960 + } 1961 + } 1947 1962 } 1948 1963 spin_unlock_irq(&ic->endio_wait.lock); 1949 1964
+4 -1
drivers/md/dm-kcopyd.c
··· 566 566 * no point in continuing. 567 567 */ 568 568 if (test_bit(DM_KCOPYD_WRITE_SEQ, &job->flags) && 569 - job->master_job->write_err) 569 + job->master_job->write_err) { 570 + job->write_err = job->master_job->write_err; 570 571 return -EIO; 572 + } 571 573 572 574 io_job_start(job->kc->throttle); 573 575 ··· 621 619 else 622 620 job->read_err = 1; 623 621 push(&kc->complete_jobs, job); 622 + wake(kc); 624 623 break; 625 624 } 626 625
+1 -1
drivers/md/dm-raid.c
··· 3194 3194 */ 3195 3195 r = rs_prepare_reshape(rs); 3196 3196 if (r) 3197 - return r; 3197 + goto bad; 3198 3198 3199 3199 /* Reshaping ain't recovery, so disable recovery */ 3200 3200 rs_setup_recovery(rs, MaxSector);
+4 -1
drivers/md/dm-table.c
··· 1342 1342 } 1343 1343 EXPORT_SYMBOL(dm_table_event); 1344 1344 1345 - sector_t dm_table_get_size(struct dm_table *t) 1345 + inline sector_t dm_table_get_size(struct dm_table *t) 1346 1346 { 1347 1347 return t->num_targets ? (t->highs[t->num_targets - 1] + 1) : 0; 1348 1348 } ··· 1366 1366 { 1367 1367 unsigned int l, n = 0, k = 0; 1368 1368 sector_t *node; 1369 + 1370 + if (unlikely(sector >= dm_table_get_size(t))) 1371 + return &t->targets[t->num_targets]; 1369 1372 1370 1373 for (l = 0; l < t->depth; l++) { 1371 1374 n = get_child(n, k);
+50 -18
drivers/md/dm-zoned-metadata.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 1 2 /* 2 3 * Copyright (C) 2017 Western Digital Corporation or its affiliates. 3 4 * ··· 35 34 * (1) Super block (1 block) 36 35 * (2) Chunk mapping table (nr_map_blocks) 37 36 * (3) Bitmap blocks (nr_bitmap_blocks) 38 - * All metadata blocks are stored in conventional zones, starting from the 37 + * All metadata blocks are stored in conventional zones, starting from 39 38 * the first conventional zone found on disk. 40 39 */ 41 40 struct dmz_super { ··· 234 233 * Lock/unlock metadata access. This is a "read" lock on a semaphore 235 234 * that prevents metadata flush from running while metadata are being 236 235 * modified. The actual metadata write mutual exclusion is achieved with 237 - * the map lock and zone styate management (active and reclaim state are 236 + * the map lock and zone state management (active and reclaim state are 238 237 * mutually exclusive). 239 238 */ 240 239 void dmz_lock_metadata(struct dmz_metadata *zmd) ··· 403 402 sector_t block = zmd->sb[zmd->mblk_primary].block + mblk_no; 404 403 struct bio *bio; 405 404 405 + if (dmz_bdev_is_dying(zmd->dev)) 406 + return ERR_PTR(-EIO); 407 + 406 408 /* Get a new block and a BIO to read it */ 407 409 mblk = dmz_alloc_mblock(zmd, mblk_no); 408 410 if (!mblk) 409 - return NULL; 411 + return ERR_PTR(-ENOMEM); 410 412 411 413 bio = bio_alloc(GFP_NOIO, 1); 412 414 if (!bio) { 413 415 dmz_free_mblock(zmd, mblk); 414 - return NULL; 416 + return ERR_PTR(-ENOMEM); 415 417 } 416 418 417 419 spin_lock(&zmd->mblk_lock); ··· 545 541 if (!mblk) { 546 542 /* Cache miss: read the block from disk */ 547 543 mblk = dmz_get_mblock_slow(zmd, mblk_no); 548 - if (!mblk) 549 - return ERR_PTR(-ENOMEM); 544 + if (IS_ERR(mblk)) 545 + return mblk; 550 546 } 551 547 552 548 /* Wait for on-going read I/O and check for error */ ··· 574 570 /* 575 571 * Issue a metadata block write BIO. 576 572 */ 577 - static void dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk, 578 - unsigned int set) 573 + static int dmz_write_mblock(struct dmz_metadata *zmd, struct dmz_mblock *mblk, 574 + unsigned int set) 579 575 { 580 576 sector_t block = zmd->sb[set].block + mblk->no; 581 577 struct bio *bio; 582 578 579 + if (dmz_bdev_is_dying(zmd->dev)) 580 + return -EIO; 581 + 583 582 bio = bio_alloc(GFP_NOIO, 1); 584 583 if (!bio) { 585 584 set_bit(DMZ_META_ERROR, &mblk->state); 586 - return; 585 + return -ENOMEM; 587 586 } 588 587 589 588 set_bit(DMZ_META_WRITING, &mblk->state); ··· 598 591 bio_set_op_attrs(bio, REQ_OP_WRITE, REQ_META | REQ_PRIO); 599 592 bio_add_page(bio, mblk->page, DMZ_BLOCK_SIZE, 0); 600 593 submit_bio(bio); 594 + 595 + return 0; 601 596 } 602 597 603 598 /* ··· 610 601 { 611 602 struct bio *bio; 612 603 int ret; 604 + 605 + if (dmz_bdev_is_dying(zmd->dev)) 606 + return -EIO; 613 607 614 608 bio = bio_alloc(GFP_NOIO, 1); 615 609 if (!bio) ··· 671 659 { 672 660 struct dmz_mblock *mblk; 673 661 struct blk_plug plug; 674 - int ret = 0; 662 + int ret = 0, nr_mblks_submitted = 0; 675 663 676 664 /* Issue writes */ 677 665 blk_start_plug(&plug); 678 - list_for_each_entry(mblk, write_list, link) 679 - dmz_write_mblock(zmd, mblk, set); 666 + list_for_each_entry(mblk, write_list, link) { 667 + ret = dmz_write_mblock(zmd, mblk, set); 668 + if (ret) 669 + break; 670 + nr_mblks_submitted++; 671 + } 680 672 blk_finish_plug(&plug); 681 673 682 674 /* Wait for completion */ 683 675 list_for_each_entry(mblk, write_list, link) { 676 + if (!nr_mblks_submitted) 677 + break; 684 678 wait_on_bit_io(&mblk->state, DMZ_META_WRITING, 685 679 TASK_UNINTERRUPTIBLE); 686 680 if (test_bit(DMZ_META_ERROR, &mblk->state)) { 687 681 clear_bit(DMZ_META_ERROR, &mblk->state); 688 682 ret = -EIO; 689 683 } 684 + nr_mblks_submitted--; 690 685 } 691 686 692 687 /* Flush drive cache (this will also sync data) */ ··· 754 735 * Concurrent execution is not allowed. 755 736 */ 756 737 dmz_lock_flush(zmd); 738 + 739 + if (dmz_bdev_is_dying(zmd->dev)) { 740 + ret = -EIO; 741 + goto out; 742 + } 757 743 758 744 /* Get dirty blocks */ 759 745 spin_lock(&zmd->mblk_lock); ··· 1566 1542 struct dm_zone *zone; 1567 1543 1568 1544 if (list_empty(&zmd->map_rnd_list)) 1569 - return NULL; 1545 + return ERR_PTR(-EBUSY); 1570 1546 1571 1547 list_for_each_entry(zone, &zmd->map_rnd_list, link) { 1572 1548 if (dmz_is_buf(zone)) ··· 1577 1553 return dzone; 1578 1554 } 1579 1555 1580 - return NULL; 1556 + return ERR_PTR(-EBUSY); 1581 1557 } 1582 1558 1583 1559 /* ··· 1588 1564 struct dm_zone *zone; 1589 1565 1590 1566 if (list_empty(&zmd->map_seq_list)) 1591 - return NULL; 1567 + return ERR_PTR(-EBUSY); 1592 1568 1593 1569 list_for_each_entry(zone, &zmd->map_seq_list, link) { 1594 1570 if (!zone->bzone) ··· 1597 1573 return zone; 1598 1574 } 1599 1575 1600 - return NULL; 1576 + return ERR_PTR(-EBUSY); 1601 1577 } 1602 1578 1603 1579 /* ··· 1652 1628 if (op != REQ_OP_WRITE) 1653 1629 goto out; 1654 1630 1655 - /* Alloate a random zone */ 1631 + /* Allocate a random zone */ 1656 1632 dzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND); 1657 1633 if (!dzone) { 1634 + if (dmz_bdev_is_dying(zmd->dev)) { 1635 + dzone = ERR_PTR(-EIO); 1636 + goto out; 1637 + } 1658 1638 dmz_wait_for_free_zones(zmd); 1659 1639 goto again; 1660 1640 } ··· 1753 1725 if (bzone) 1754 1726 goto out; 1755 1727 1756 - /* Alloate a random zone */ 1728 + /* Allocate a random zone */ 1757 1729 bzone = dmz_alloc_zone(zmd, DMZ_ALLOC_RND); 1758 1730 if (!bzone) { 1731 + if (dmz_bdev_is_dying(zmd->dev)) { 1732 + bzone = ERR_PTR(-EIO); 1733 + goto out; 1734 + } 1759 1735 dmz_wait_for_free_zones(zmd); 1760 1736 goto again; 1761 1737 }
+36 -11
drivers/md/dm-zoned-reclaim.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 1 2 /* 2 3 * Copyright (C) 2017 Western Digital Corporation or its affiliates. 3 4 * ··· 38 37 /* 39 38 * Number of seconds of target BIO inactivity to consider the target idle. 40 39 */ 41 - #define DMZ_IDLE_PERIOD (10UL * HZ) 40 + #define DMZ_IDLE_PERIOD (10UL * HZ) 42 41 43 42 /* 44 43 * Percentage of unmapped (free) random zones below which reclaim starts ··· 135 134 set_bit(DM_KCOPYD_WRITE_SEQ, &flags); 136 135 137 136 while (block < end_block) { 137 + if (dev->flags & DMZ_BDEV_DYING) 138 + return -EIO; 139 + 138 140 /* Get a valid region from the source zone */ 139 141 ret = dmz_first_valid_block(zmd, src_zone, &block); 140 142 if (ret <= 0) ··· 219 215 220 216 dmz_unlock_flush(zmd); 221 217 222 - return 0; 218 + return ret; 223 219 } 224 220 225 221 /* ··· 263 259 264 260 dmz_unlock_flush(zmd); 265 261 266 - return 0; 262 + return ret; 267 263 } 268 264 269 265 /* ··· 316 312 317 313 dmz_unlock_flush(zmd); 318 314 319 - return 0; 315 + return ret; 320 316 } 321 317 322 318 /* ··· 338 334 /* 339 335 * Find a candidate zone for reclaim and process it. 340 336 */ 341 - static void dmz_reclaim(struct dmz_reclaim *zrc) 337 + static int dmz_do_reclaim(struct dmz_reclaim *zrc) 342 338 { 343 339 struct dmz_metadata *zmd = zrc->metadata; 344 340 struct dm_zone *dzone; ··· 348 344 349 345 /* Get a data zone */ 350 346 dzone = dmz_get_zone_for_reclaim(zmd); 351 - if (!dzone) 352 - return; 347 + if (IS_ERR(dzone)) 348 + return PTR_ERR(dzone); 353 349 354 350 start = jiffies; 355 351 ··· 395 391 out: 396 392 if (ret) { 397 393 dmz_unlock_zone_reclaim(dzone); 398 - return; 394 + return ret; 399 395 } 400 396 401 - (void) dmz_flush_metadata(zrc->metadata); 397 + ret = dmz_flush_metadata(zrc->metadata); 398 + if (ret) { 399 + dmz_dev_debug(zrc->dev, 400 + "Metadata flush for zone %u failed, err %d\n", 401 + dmz_id(zmd, rzone), ret); 402 + return ret; 403 + } 402 404 403 405 dmz_dev_debug(zrc->dev, "Reclaimed zone %u in %u ms", 404 406 dmz_id(zmd, rzone), jiffies_to_msecs(jiffies - start)); 407 + return 0; 405 408 } 406 409 407 410 /* ··· 438 427 return false; 439 428 440 429 /* 441 - * If the percentage of unmappped random zones is low, 430 + * If the percentage of unmapped random zones is low, 442 431 * reclaim even if the target is busy. 443 432 */ 444 433 return p_unmap_rnd <= DMZ_RECLAIM_LOW_UNMAP_RND; ··· 453 442 struct dmz_metadata *zmd = zrc->metadata; 454 443 unsigned int nr_rnd, nr_unmap_rnd; 455 444 unsigned int p_unmap_rnd; 445 + int ret; 446 + 447 + if (dmz_bdev_is_dying(zrc->dev)) 448 + return; 456 449 457 450 if (!dmz_should_reclaim(zrc)) { 458 451 mod_delayed_work(zrc->wq, &zrc->work, DMZ_IDLE_PERIOD); ··· 486 471 (dmz_target_idle(zrc) ? "Idle" : "Busy"), 487 472 p_unmap_rnd, nr_unmap_rnd, nr_rnd); 488 473 489 - dmz_reclaim(zrc); 474 + ret = dmz_do_reclaim(zrc); 475 + if (ret) { 476 + dmz_dev_debug(zrc->dev, "Reclaim error %d\n", ret); 477 + if (ret == -EIO) 478 + /* 479 + * LLD might be performing some error handling sequence 480 + * at the underlying device. To not interfere, do not 481 + * attempt to schedule the next reclaim run immediately. 482 + */ 483 + return; 484 + } 490 485 491 486 dmz_schedule_reclaim(zrc); 492 487 }
+60 -8
drivers/md/dm-zoned-target.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 1 2 /* 2 3 * Copyright (C) 2017 Western Digital Corporation or its affiliates. 3 4 * ··· 134 133 135 134 refcount_inc(&bioctx->ref); 136 135 generic_make_request(clone); 136 + if (clone->bi_status == BLK_STS_IOERR) 137 + return -EIO; 137 138 138 139 if (bio_op(bio) == REQ_OP_WRITE && dmz_is_seq(zone)) 139 140 zone->wp_block += nr_blocks; ··· 280 277 281 278 /* Get the buffer zone. One will be allocated if needed */ 282 279 bzone = dmz_get_chunk_buffer(zmd, zone); 283 - if (!bzone) 284 - return -ENOSPC; 280 + if (IS_ERR(bzone)) 281 + return PTR_ERR(bzone); 285 282 286 283 if (dmz_is_readonly(bzone)) 287 284 return -EROFS; ··· 392 389 393 390 dmz_lock_metadata(zmd); 394 391 392 + if (dmz->dev->flags & DMZ_BDEV_DYING) { 393 + ret = -EIO; 394 + goto out; 395 + } 396 + 395 397 /* 396 398 * Get the data zone mapping the chunk. There may be no 397 399 * mapping for read and discard. If a mapping is obtained, ··· 501 493 502 494 /* Flush dirty metadata blocks */ 503 495 ret = dmz_flush_metadata(dmz->metadata); 496 + if (ret) 497 + dmz_dev_debug(dmz->dev, "Metadata flush failed, rc=%d\n", ret); 504 498 505 499 /* Process queued flush requests */ 506 500 while (1) { ··· 523 513 * Get a chunk work and start it to process a new BIO. 524 514 * If the BIO chunk has no work yet, create one. 525 515 */ 526 - static void dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio) 516 + static int dmz_queue_chunk_work(struct dmz_target *dmz, struct bio *bio) 527 517 { 528 518 unsigned int chunk = dmz_bio_chunk(dmz->dev, bio); 529 519 struct dm_chunk_work *cw; 520 + int ret = 0; 530 521 531 522 mutex_lock(&dmz->chunk_lock); 532 523 533 524 /* Get the BIO chunk work. If one is not active yet, create one */ 534 525 cw = radix_tree_lookup(&dmz->chunk_rxtree, chunk); 535 526 if (!cw) { 536 - int ret; 537 527 538 528 /* Create a new chunk work */ 539 529 cw = kmalloc(sizeof(struct dm_chunk_work), GFP_NOIO); 540 - if (!cw) 530 + if (unlikely(!cw)) { 531 + ret = -ENOMEM; 541 532 goto out; 533 + } 542 534 543 535 INIT_WORK(&cw->work, dmz_chunk_work); 544 536 refcount_set(&cw->refcount, 0); ··· 551 539 ret = radix_tree_insert(&dmz->chunk_rxtree, chunk, cw); 552 540 if (unlikely(ret)) { 553 541 kfree(cw); 554 - cw = NULL; 555 542 goto out; 556 543 } 557 544 } ··· 558 547 bio_list_add(&cw->bio_list, bio); 559 548 dmz_get_chunk_work(cw); 560 549 550 + dmz_reclaim_bio_acc(dmz->reclaim); 561 551 if (queue_work(dmz->chunk_wq, &cw->work)) 562 552 dmz_get_chunk_work(cw); 563 553 out: 564 554 mutex_unlock(&dmz->chunk_lock); 555 + return ret; 556 + } 557 + 558 + /* 559 + * Check the backing device availability. If it's on the way out, 560 + * start failing I/O. Reclaim and metadata components also call this 561 + * function to cleanly abort operation in the event of such failure. 562 + */ 563 + bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev) 564 + { 565 + struct gendisk *disk; 566 + 567 + if (!(dmz_dev->flags & DMZ_BDEV_DYING)) { 568 + disk = dmz_dev->bdev->bd_disk; 569 + if (blk_queue_dying(bdev_get_queue(dmz_dev->bdev))) { 570 + dmz_dev_warn(dmz_dev, "Backing device queue dying"); 571 + dmz_dev->flags |= DMZ_BDEV_DYING; 572 + } else if (disk->fops->check_events) { 573 + if (disk->fops->check_events(disk, 0) & 574 + DISK_EVENT_MEDIA_CHANGE) { 575 + dmz_dev_warn(dmz_dev, "Backing device offline"); 576 + dmz_dev->flags |= DMZ_BDEV_DYING; 577 + } 578 + } 579 + } 580 + 581 + return dmz_dev->flags & DMZ_BDEV_DYING; 565 582 } 566 583 567 584 /* ··· 603 564 sector_t sector = bio->bi_iter.bi_sector; 604 565 unsigned int nr_sectors = bio_sectors(bio); 605 566 sector_t chunk_sector; 567 + int ret; 568 + 569 + if (dmz_bdev_is_dying(dmz->dev)) 570 + return DM_MAPIO_KILL; 606 571 607 572 dmz_dev_debug(dev, "BIO op %d sector %llu + %u => chunk %llu, block %llu, %u blocks", 608 573 bio_op(bio), (unsigned long long)sector, nr_sectors, ··· 644 601 dm_accept_partial_bio(bio, dev->zone_nr_sectors - chunk_sector); 645 602 646 603 /* Now ready to handle this BIO */ 647 - dmz_reclaim_bio_acc(dmz->reclaim); 648 - dmz_queue_chunk_work(dmz, bio); 604 + ret = dmz_queue_chunk_work(dmz, bio); 605 + if (ret) { 606 + dmz_dev_debug(dmz->dev, 607 + "BIO op %d, can't process chunk %llu, err %i\n", 608 + bio_op(bio), (u64)dmz_bio_chunk(dmz->dev, bio), 609 + ret); 610 + return DM_MAPIO_REQUEUE; 611 + } 649 612 650 613 return DM_MAPIO_SUBMITTED; 651 614 } ··· 903 854 static int dmz_prepare_ioctl(struct dm_target *ti, struct block_device **bdev) 904 855 { 905 856 struct dmz_target *dmz = ti->private; 857 + 858 + if (dmz_bdev_is_dying(dmz->dev)) 859 + return -ENODEV; 906 860 907 861 *bdev = dmz->dev->bdev; 908 862
+11
drivers/md/dm-zoned.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 1 2 /* 2 3 * Copyright (C) 2017 Western Digital Corporation or its affiliates. 3 4 * ··· 57 56 58 57 unsigned int nr_zones; 59 58 59 + unsigned int flags; 60 + 60 61 sector_t zone_nr_sectors; 61 62 unsigned int zone_nr_sectors_shift; 62 63 ··· 69 66 #define dmz_bio_chunk(dev, bio) ((bio)->bi_iter.bi_sector >> \ 70 67 (dev)->zone_nr_sectors_shift) 71 68 #define dmz_chunk_block(dev, b) ((b) & ((dev)->zone_nr_blocks - 1)) 69 + 70 + /* Device flags. */ 71 + #define DMZ_BDEV_DYING (1 << 0) 72 72 73 73 /* 74 74 * Zone descriptor. ··· 250 244 void dmz_resume_reclaim(struct dmz_reclaim *zrc); 251 245 void dmz_reclaim_bio_acc(struct dmz_reclaim *zrc); 252 246 void dmz_schedule_reclaim(struct dmz_reclaim *zrc); 247 + 248 + /* 249 + * Functions defined in dm-zoned-target.c 250 + */ 251 + bool dmz_bdev_is_dying(struct dmz_dev *dmz_dev); 253 252 254 253 #endif /* DM_ZONED_H */
+16 -15
drivers/md/persistent-data/dm-btree.c
··· 628 628 629 629 new_parent = shadow_current(s); 630 630 631 + pn = dm_block_data(new_parent); 632 + size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ? 633 + sizeof(__le64) : s->info->value_type.size; 634 + 635 + /* create & init the left block */ 631 636 r = new_block(s->info, &left); 632 637 if (r < 0) 633 638 return r; 634 639 640 + ln = dm_block_data(left); 641 + nr_left = le32_to_cpu(pn->header.nr_entries) / 2; 642 + 643 + ln->header.flags = pn->header.flags; 644 + ln->header.nr_entries = cpu_to_le32(nr_left); 645 + ln->header.max_entries = pn->header.max_entries; 646 + ln->header.value_size = pn->header.value_size; 647 + memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0])); 648 + memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size); 649 + 650 + /* create & init the right block */ 635 651 r = new_block(s->info, &right); 636 652 if (r < 0) { 637 653 unlock_block(s->info, left); 638 654 return r; 639 655 } 640 656 641 - pn = dm_block_data(new_parent); 642 - ln = dm_block_data(left); 643 657 rn = dm_block_data(right); 644 - 645 - nr_left = le32_to_cpu(pn->header.nr_entries) / 2; 646 658 nr_right = le32_to_cpu(pn->header.nr_entries) - nr_left; 647 - 648 - ln->header.flags = pn->header.flags; 649 - ln->header.nr_entries = cpu_to_le32(nr_left); 650 - ln->header.max_entries = pn->header.max_entries; 651 - ln->header.value_size = pn->header.value_size; 652 659 653 660 rn->header.flags = pn->header.flags; 654 661 rn->header.nr_entries = cpu_to_le32(nr_right); 655 662 rn->header.max_entries = pn->header.max_entries; 656 663 rn->header.value_size = pn->header.value_size; 657 - 658 - memcpy(ln->keys, pn->keys, nr_left * sizeof(pn->keys[0])); 659 664 memcpy(rn->keys, pn->keys + nr_left, nr_right * sizeof(pn->keys[0])); 660 - 661 - size = le32_to_cpu(pn->header.flags) & INTERNAL_NODE ? 662 - sizeof(__le64) : s->info->value_type.size; 663 - memcpy(value_ptr(ln, 0), value_ptr(pn, 0), nr_left * size); 664 665 memcpy(value_ptr(rn, 0), value_ptr(pn, nr_left), 665 666 nr_right * size); 666 667
+1 -1
drivers/md/persistent-data/dm-space-map-metadata.c
··· 249 249 } 250 250 251 251 if (smm->recursion_count == 1) 252 - apply_bops(smm); 252 + r = apply_bops(smm); 253 253 254 254 smm->recursion_count--; 255 255