From 244b2c5ca8b14627e4a17755e5922221e121c771 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 09 Oct 2024 06:15:07 +0000
Subject: [PATCH] change system file
---
kernel/block/blk-lib.c | 53 +++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 43 insertions(+), 10 deletions(-)
diff --git a/kernel/block/blk-lib.c b/kernel/block/blk-lib.c
index 0dbc9e2..e90614f 100644
--- a/kernel/block/blk-lib.c
+++ b/kernel/block/blk-lib.c
@@ -10,8 +10,7 @@
#include "blk.h"
-static struct bio *next_bio(struct bio *bio, unsigned int nr_pages,
- gfp_t gfp)
+struct bio *blk_next_bio(struct bio *bio, unsigned int nr_pages, gfp_t gfp)
{
struct bio *new = bio_alloc(gfp, nr_pages);
@@ -30,7 +29,7 @@
struct request_queue *q = bdev_get_queue(bdev);
struct bio *bio = *biop;
unsigned int op;
- sector_t bs_mask;
+ sector_t bs_mask, part_offset = 0;
if (!q)
return -ENXIO;
@@ -48,6 +47,15 @@
op = REQ_OP_DISCARD;
}
+ /* In case the discard granularity isn't set by buggy device driver */
+ if (WARN_ON_ONCE(!q->limits.discard_granularity)) {
+ char dev_name[BDEVNAME_SIZE];
+
+ bdevname(bdev, dev_name);
+ pr_err_ratelimited("%s: Error: discard_granularity is 0.\n", dev_name);
+ return -EOPNOTSUPP;
+ }
+
bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
if ((sector | nr_sects) & bs_mask)
return -EINVAL;
@@ -55,13 +63,38 @@
if (!nr_sects)
return -EINVAL;
+ /* In case the discard request is in a partition */
+ if (bdev_is_partition(bdev))
+ part_offset = bdev->bd_part->start_sect;
+
while (nr_sects) {
- sector_t req_sects = min_t(sector_t, nr_sects,
- bio_allowed_max_sectors(q));
+ sector_t granularity_aligned_lba, req_sects;
+ sector_t sector_mapped = sector + part_offset;
+
+ granularity_aligned_lba = round_up(sector_mapped,
+ q->limits.discard_granularity >> SECTOR_SHIFT);
+
+ /*
+ * Check whether the discard bio starts at a discard_granularity
+ * aligned LBA,
+ * - If no: set (granularity_aligned_lba - sector_mapped) to
+ * bi_size of the first split bio, then the second bio will
+ * start at a discard_granularity aligned LBA on the device.
+ * - If yes: use bio_aligned_discard_max_sectors() as the max
+ * possible bi_size of the first split bio. Then when this bio
+ * is split in device drive, the split ones are very probably
+ * to be aligned to discard_granularity of the device's queue.
+ */
+ if (granularity_aligned_lba == sector_mapped)
+ req_sects = min_t(sector_t, nr_sects,
+ bio_aligned_discard_max_sectors(q));
+ else
+ req_sects = min_t(sector_t, nr_sects,
+ granularity_aligned_lba - sector_mapped);
WARN_ON_ONCE((req_sects << 9) > UINT_MAX);
- bio = next_bio(bio, 0, gfp_mask);
+ bio = blk_next_bio(bio, 0, gfp_mask);
bio->bi_iter.bi_sector = sector;
bio_set_dev(bio, bdev);
bio_set_op_attrs(bio, op, 0);
@@ -155,7 +188,7 @@
max_write_same_sectors = bio_allowed_max_sectors(q);
while (nr_sects) {
- bio = next_bio(bio, 1, gfp_mask);
+ bio = blk_next_bio(bio, 1, gfp_mask);
bio->bi_iter.bi_sector = sector;
bio_set_dev(bio, bdev);
bio->bi_vcnt = 1;
@@ -231,7 +264,7 @@
return -EOPNOTSUPP;
while (nr_sects) {
- bio = next_bio(bio, 0, gfp_mask);
+ bio = blk_next_bio(bio, 0, gfp_mask);
bio->bi_iter.bi_sector = sector;
bio_set_dev(bio, bdev);
bio->bi_opf = REQ_OP_WRITE_ZEROES;
@@ -282,8 +315,8 @@
return -EPERM;
while (nr_sects != 0) {
- bio = next_bio(bio, __blkdev_sectors_to_bio_pages(nr_sects),
- gfp_mask);
+ bio = blk_next_bio(bio, __blkdev_sectors_to_bio_pages(nr_sects),
+ gfp_mask);
bio->bi_iter.bi_sector = sector;
bio_set_dev(bio, bdev);
bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
--
Gitblit v1.6.2