diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-17 08:48:45 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-02-17 08:48:45 -0800 |
| commit | 99dfe2d4da67d863ff8f185d1e8033cce28e4c49 (patch) | |
| tree | a5afa6d4923bf972103f10c176d2c65d0f1ba9a1 /drivers | |
| parent | 7b751b01ade7f666de2f5c365bd9562c2dcd7d60 (diff) | |
| parent | dfe48ea179733be948c432f6af2fc3913cf5dd28 (diff) | |
Merge tag 'block-7.0-20260216' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux
Pull more block updates from Jens Axboe:
- Fix partial IOVA mapping cleanup in error handling
- Minor prep series ignoring discard return value, as
the inline value is always known
- Ensure BLK_FEAT_STABLE_WRITES is set for drbd
- Fix leak of folio in bio_iov_iter_bounce_read()
- Allow IOC_PR_READ_* for read-only open
- Another debugfs deadlock fix
- A few doc updates
* tag 'block-7.0-20260216' of git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux:
blk-mq: use NOIO context to prevent deadlock during debugfs creation
blk-stat: convert struct blk_stat_callback to kernel-doc
block: fix enum descriptions kernel-doc
block: update docs for bio and bvec_iter
block: change return type to void
nvmet: ignore discard return value
md: ignore discard return value
block: fix partial IOVA mapping cleanup in blk_rq_dma_map_iova
block: fix folio leak in bio_iov_iter_bounce_read()
block: allow IOC_PR_READ_* ioctls with BLK_OPEN_READ
drbd: always set BLK_FEAT_STABLE_WRITES
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/block/drbd/drbd_main.c | 3 | ||||
| -rw-r--r-- | drivers/block/drbd/drbd_nl.c | 20 | ||||
| -rw-r--r-- | drivers/md/md.c | 4 | ||||
| -rw-r--r-- | drivers/nvme/target/io-cmd-bdev.c | 28 |
4 files changed, 28 insertions, 27 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index c73376886e7a..1f6ac9202b66 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -2659,9 +2659,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig * connect. */ .max_hw_sectors = DRBD_MAX_BIO_SIZE_SAFE >> 8, - .features = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA | - BLK_FEAT_ROTATIONAL | - BLK_FEAT_STABLE_WRITES, }; device = minor_to_device(minor); diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 91f3b8afb63c..b502038be0a9 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1296,6 +1296,8 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device, lim.max_segments = drbd_backing_dev_max_segments(device); } else { lim.max_segments = BLK_MAX_SEGMENTS; + lim.features = BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA | + BLK_FEAT_ROTATIONAL | BLK_FEAT_STABLE_WRITES; } lim.max_hw_sectors = new >> SECTOR_SHIFT; @@ -1318,8 +1320,24 @@ void drbd_reconsider_queue_parameters(struct drbd_device *device, lim.max_hw_discard_sectors = 0; } - if (bdev) + if (bdev) { blk_stack_limits(&lim, &b->limits, 0); + /* + * blk_set_stacking_limits() cleared the features, and + * blk_stack_limits() may or may not have inherited + * BLK_FEAT_STABLE_WRITES from the backing device. + * + * DRBD always requires stable writes because: + * 1. The same bio data is read for both local disk I/O and + * network transmission. If the page changes mid-flight, + * the local and remote copies could diverge. + * 2. When data integrity is enabled, DRBD calculates a + * checksum before sending the data. If the page changes + * between checksum calculation and transmission, the + * receiver will detect a checksum mismatch. + */ + lim.features |= BLK_FEAT_STABLE_WRITES; + } /* * If we can handle "zeroes" efficiently on the protocol, we want to do diff --git a/drivers/md/md.c b/drivers/md/md.c index 9ca5d74fd2b2..72a1c7267851 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -9179,8 +9179,8 @@ void md_submit_discard_bio(struct mddev *mddev, struct md_rdev *rdev, { struct bio *discard_bio = NULL; - if (__blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO, - &discard_bio) || !discard_bio) + __blkdev_issue_discard(rdev->bdev, start, size, GFP_NOIO, &discard_bio); + if (!discard_bio) return; bio_chain(discard_bio, bio); diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c index 0103815542d4..f15d1c213bc6 100644 --- a/drivers/nvme/target/io-cmd-bdev.c +++ b/drivers/nvme/target/io-cmd-bdev.c @@ -363,29 +363,14 @@ u16 nvmet_bdev_flush(struct nvmet_req *req) return 0; } -static u16 nvmet_bdev_discard_range(struct nvmet_req *req, - struct nvme_dsm_range *range, struct bio **bio) -{ - struct nvmet_ns *ns = req->ns; - int ret; - - ret = __blkdev_issue_discard(ns->bdev, - nvmet_lba_to_sect(ns, range->slba), - le32_to_cpu(range->nlb) << (ns->blksize_shift - 9), - GFP_KERNEL, bio); - if (ret && ret != -EOPNOTSUPP) { - req->error_slba = le64_to_cpu(range->slba); - return errno_to_nvme_status(req, ret); - } - return NVME_SC_SUCCESS; -} - static void nvmet_bdev_execute_discard(struct nvmet_req *req) { + struct nvmet_ns *ns = req->ns; struct nvme_dsm_range range; struct bio *bio = NULL; + sector_t nr_sects; int i; - u16 status; + u16 status = NVME_SC_SUCCESS; for (i = 0; i <= le32_to_cpu(req->cmd->dsm.nr); i++) { status = nvmet_copy_from_sgl(req, i * sizeof(range), &range, @@ -393,9 +378,10 @@ static void nvmet_bdev_execute_discard(struct nvmet_req *req) if (status) break; - status = nvmet_bdev_discard_range(req, &range, &bio); - if (status) - break; + nr_sects = le32_to_cpu(range.nlb) << (ns->blksize_shift - 9); + __blkdev_issue_discard(ns->bdev, + nvmet_lba_to_sect(ns, range.slba), nr_sects, + GFP_KERNEL, &bio); } if (bio) { |
