hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/block/blk-lib.c
....@@ -10,8 +10,7 @@
1010
1111 #include "blk.h"
1212
13
-static struct bio *next_bio(struct bio *bio, unsigned int nr_pages,
14
- gfp_t gfp)
13
+struct bio *blk_next_bio(struct bio *bio, unsigned int nr_pages, gfp_t gfp)
1514 {
1615 struct bio *new = bio_alloc(gfp, nr_pages);
1716
....@@ -30,7 +29,7 @@
3029 struct request_queue *q = bdev_get_queue(bdev);
3130 struct bio *bio = *biop;
3231 unsigned int op;
33
- sector_t bs_mask;
32
+ sector_t bs_mask, part_offset = 0;
3433
3534 if (!q)
3635 return -ENXIO;
....@@ -48,6 +47,15 @@
4847 op = REQ_OP_DISCARD;
4948 }
5049
50
+ /* In case the discard granularity isn't set by buggy device driver */
51
+ if (WARN_ON_ONCE(!q->limits.discard_granularity)) {
52
+ char dev_name[BDEVNAME_SIZE];
53
+
54
+ bdevname(bdev, dev_name);
55
+ pr_err_ratelimited("%s: Error: discard_granularity is 0.\n", dev_name);
56
+ return -EOPNOTSUPP;
57
+ }
58
+
5159 bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
5260 if ((sector | nr_sects) & bs_mask)
5361 return -EINVAL;
....@@ -55,13 +63,38 @@
5563 if (!nr_sects)
5664 return -EINVAL;
5765
66
+ /* In case the discard request is in a partition */
67
+ if (bdev_is_partition(bdev))
68
+ part_offset = bdev->bd_part->start_sect;
69
+
5870 while (nr_sects) {
59
- sector_t req_sects = min_t(sector_t, nr_sects,
60
- bio_allowed_max_sectors(q));
71
+ sector_t granularity_aligned_lba, req_sects;
72
+ sector_t sector_mapped = sector + part_offset;
73
+
74
+ granularity_aligned_lba = round_up(sector_mapped,
75
+ q->limits.discard_granularity >> SECTOR_SHIFT);
76
+
77
+ /*
78
+ * Check whether the discard bio starts at a discard_granularity
79
+ * aligned LBA,
80
+ * - If no: set (granularity_aligned_lba - sector_mapped) to
81
+ * bi_size of the first split bio, then the second bio will
82
+ * start at a discard_granularity aligned LBA on the device.
83
+ * - If yes: use bio_aligned_discard_max_sectors() as the max
84
+ * possible bi_size of the first split bio. Then when this bio
85
+ * is split in device drive, the split ones are very probably
86
+ * to be aligned to discard_granularity of the device's queue.
87
+ */
88
+ if (granularity_aligned_lba == sector_mapped)
89
+ req_sects = min_t(sector_t, nr_sects,
90
+ bio_aligned_discard_max_sectors(q));
91
+ else
92
+ req_sects = min_t(sector_t, nr_sects,
93
+ granularity_aligned_lba - sector_mapped);
6194
6295 WARN_ON_ONCE((req_sects << 9) > UINT_MAX);
6396
64
- bio = next_bio(bio, 0, gfp_mask);
97
+ bio = blk_next_bio(bio, 0, gfp_mask);
6598 bio->bi_iter.bi_sector = sector;
6699 bio_set_dev(bio, bdev);
67100 bio_set_op_attrs(bio, op, 0);
....@@ -155,7 +188,7 @@
155188 max_write_same_sectors = bio_allowed_max_sectors(q);
156189
157190 while (nr_sects) {
158
- bio = next_bio(bio, 1, gfp_mask);
191
+ bio = blk_next_bio(bio, 1, gfp_mask);
159192 bio->bi_iter.bi_sector = sector;
160193 bio_set_dev(bio, bdev);
161194 bio->bi_vcnt = 1;
....@@ -231,7 +264,7 @@
231264 return -EOPNOTSUPP;
232265
233266 while (nr_sects) {
234
- bio = next_bio(bio, 0, gfp_mask);
267
+ bio = blk_next_bio(bio, 0, gfp_mask);
235268 bio->bi_iter.bi_sector = sector;
236269 bio_set_dev(bio, bdev);
237270 bio->bi_opf = REQ_OP_WRITE_ZEROES;
....@@ -282,8 +315,8 @@
282315 return -EPERM;
283316
284317 while (nr_sects != 0) {
285
- bio = next_bio(bio, __blkdev_sectors_to_bio_pages(nr_sects),
286
- gfp_mask);
318
+ bio = blk_next_bio(bio, __blkdev_sectors_to_bio_pages(nr_sects),
319
+ gfp_mask);
287320 bio->bi_iter.bi_sector = sector;
288321 bio_set_dev(bio, bdev);
289322 bio_set_op_attrs(bio, REQ_OP_WRITE, 0);