block: add a bdev_discard_granularity helper
[platform/kernel/linux-starfive.git] / block / blk-lib.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Functions related to generic helpers functions
4  */
5 #include <linux/kernel.h>
6 #include <linux/module.h>
7 #include <linux/bio.h>
8 #include <linux/blkdev.h>
9 #include <linux/scatterlist.h>
10
11 #include "blk.h"
12
13 static sector_t bio_discard_limit(struct block_device *bdev, sector_t sector)
14 {
15         unsigned int discard_granularity = bdev_discard_granularity(bdev);
16         sector_t granularity_aligned_sector;
17
18         if (bdev_is_partition(bdev))
19                 sector += bdev->bd_start_sect;
20
21         granularity_aligned_sector =
22                 round_up(sector, discard_granularity >> SECTOR_SHIFT);
23
24         /*
25          * Make sure subsequent bios start aligned to the discard granularity if
26          * it needs to be split.
27          */
28         if (granularity_aligned_sector != sector)
29                 return granularity_aligned_sector - sector;
30
31         /*
32          * Align the bio size to the discard granularity to make splitting the bio
33          * at discard granularity boundaries easier in the driver if needed.
34          */
35         return round_down(UINT_MAX, discard_granularity) >> SECTOR_SHIFT;
36 }
37
38 int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
39                 sector_t nr_sects, gfp_t gfp_mask, int flags,
40                 struct bio **biop)
41 {
42         struct request_queue *q = bdev_get_queue(bdev);
43         struct bio *bio = *biop;
44         unsigned int op;
45         sector_t bs_mask;
46
47         if (bdev_read_only(bdev))
48                 return -EPERM;
49
50         if (flags & BLKDEV_DISCARD_SECURE) {
51                 if (!blk_queue_secure_erase(q))
52                         return -EOPNOTSUPP;
53                 op = REQ_OP_SECURE_ERASE;
54         } else {
55                 if (!bdev_max_discard_sectors(bdev))
56                         return -EOPNOTSUPP;
57                 op = REQ_OP_DISCARD;
58         }
59
60         /* In case the discard granularity isn't set by buggy device driver */
61         if (WARN_ON_ONCE(!bdev_discard_granularity(bdev))) {
62                 char dev_name[BDEVNAME_SIZE];
63
64                 bdevname(bdev, dev_name);
65                 pr_err_ratelimited("%s: Error: discard_granularity is 0.\n", dev_name);
66                 return -EOPNOTSUPP;
67         }
68
69         bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
70         if ((sector | nr_sects) & bs_mask)
71                 return -EINVAL;
72
73         if (!nr_sects)
74                 return -EINVAL;
75
76         while (nr_sects) {
77                 sector_t req_sects =
78                         min(nr_sects, bio_discard_limit(bdev, sector));
79
80                 bio = blk_next_bio(bio, bdev, 0, op, gfp_mask);
81                 bio->bi_iter.bi_sector = sector;
82                 bio->bi_iter.bi_size = req_sects << 9;
83                 sector += req_sects;
84                 nr_sects -= req_sects;
85
86                 /*
87                  * We can loop for a long time in here, if someone does
88                  * full device discards (like mkfs). Be nice and allow
89                  * us to schedule out to avoid softlocking if preempt
90                  * is disabled.
91                  */
92                 cond_resched();
93         }
94
95         *biop = bio;
96         return 0;
97 }
98 EXPORT_SYMBOL(__blkdev_issue_discard);
99
100 /**
101  * blkdev_issue_discard - queue a discard
102  * @bdev:       blockdev to issue discard for
103  * @sector:     start sector
104  * @nr_sects:   number of sectors to discard
105  * @gfp_mask:   memory allocation flags (for bio_alloc)
106  * @flags:      BLKDEV_DISCARD_* flags to control behaviour
107  *
108  * Description:
109  *    Issue a discard request for the sectors in question.
110  */
111 int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
112                 sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
113 {
114         struct bio *bio = NULL;
115         struct blk_plug plug;
116         int ret;
117
118         blk_start_plug(&plug);
119         ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, flags,
120                         &bio);
121         if (!ret && bio) {
122                 ret = submit_bio_wait(bio);
123                 if (ret == -EOPNOTSUPP)
124                         ret = 0;
125                 bio_put(bio);
126         }
127         blk_finish_plug(&plug);
128
129         return ret;
130 }
131 EXPORT_SYMBOL(blkdev_issue_discard);
132
133 static int __blkdev_issue_write_zeroes(struct block_device *bdev,
134                 sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
135                 struct bio **biop, unsigned flags)
136 {
137         struct bio *bio = *biop;
138         unsigned int max_write_zeroes_sectors;
139
140         if (bdev_read_only(bdev))
141                 return -EPERM;
142
143         /* Ensure that max_write_zeroes_sectors doesn't overflow bi_size */
144         max_write_zeroes_sectors = bdev_write_zeroes_sectors(bdev);
145
146         if (max_write_zeroes_sectors == 0)
147                 return -EOPNOTSUPP;
148
149         while (nr_sects) {
150                 bio = blk_next_bio(bio, bdev, 0, REQ_OP_WRITE_ZEROES, gfp_mask);
151                 bio->bi_iter.bi_sector = sector;
152                 if (flags & BLKDEV_ZERO_NOUNMAP)
153                         bio->bi_opf |= REQ_NOUNMAP;
154
155                 if (nr_sects > max_write_zeroes_sectors) {
156                         bio->bi_iter.bi_size = max_write_zeroes_sectors << 9;
157                         nr_sects -= max_write_zeroes_sectors;
158                         sector += max_write_zeroes_sectors;
159                 } else {
160                         bio->bi_iter.bi_size = nr_sects << 9;
161                         nr_sects = 0;
162                 }
163                 cond_resched();
164         }
165
166         *biop = bio;
167         return 0;
168 }
169
170 /*
171  * Convert a number of 512B sectors to a number of pages.
172  * The result is limited to a number of pages that can fit into a BIO.
173  * Also make sure that the result is always at least 1 (page) for the cases
174  * where nr_sects is lower than the number of sectors in a page.
175  */
176 static unsigned int __blkdev_sectors_to_bio_pages(sector_t nr_sects)
177 {
178         sector_t pages = DIV_ROUND_UP_SECTOR_T(nr_sects, PAGE_SIZE / 512);
179
180         return min(pages, (sector_t)BIO_MAX_VECS);
181 }
182
183 static int __blkdev_issue_zero_pages(struct block_device *bdev,
184                 sector_t sector, sector_t nr_sects, gfp_t gfp_mask,
185                 struct bio **biop)
186 {
187         struct bio *bio = *biop;
188         int bi_size = 0;
189         unsigned int sz;
190
191         if (bdev_read_only(bdev))
192                 return -EPERM;
193
194         while (nr_sects != 0) {
195                 bio = blk_next_bio(bio, bdev, __blkdev_sectors_to_bio_pages(nr_sects),
196                                    REQ_OP_WRITE, gfp_mask);
197                 bio->bi_iter.bi_sector = sector;
198
199                 while (nr_sects != 0) {
200                         sz = min((sector_t) PAGE_SIZE, nr_sects << 9);
201                         bi_size = bio_add_page(bio, ZERO_PAGE(0), sz, 0);
202                         nr_sects -= bi_size >> 9;
203                         sector += bi_size >> 9;
204                         if (bi_size < sz)
205                                 break;
206                 }
207                 cond_resched();
208         }
209
210         *biop = bio;
211         return 0;
212 }
213
214 /**
215  * __blkdev_issue_zeroout - generate number of zero filed write bios
216  * @bdev:       blockdev to issue
217  * @sector:     start sector
218  * @nr_sects:   number of sectors to write
219  * @gfp_mask:   memory allocation flags (for bio_alloc)
220  * @biop:       pointer to anchor bio
221  * @flags:      controls detailed behavior
222  *
223  * Description:
224  *  Zero-fill a block range, either using hardware offload or by explicitly
225  *  writing zeroes to the device.
226  *
227  *  If a device is using logical block provisioning, the underlying space will
228  *  not be released if %flags contains BLKDEV_ZERO_NOUNMAP.
229  *
230  *  If %flags contains BLKDEV_ZERO_NOFALLBACK, the function will return
231  *  -EOPNOTSUPP if no explicit hardware offload for zeroing is provided.
232  */
233 int __blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
234                 sector_t nr_sects, gfp_t gfp_mask, struct bio **biop,
235                 unsigned flags)
236 {
237         int ret;
238         sector_t bs_mask;
239
240         bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
241         if ((sector | nr_sects) & bs_mask)
242                 return -EINVAL;
243
244         ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects, gfp_mask,
245                         biop, flags);
246         if (ret != -EOPNOTSUPP || (flags & BLKDEV_ZERO_NOFALLBACK))
247                 return ret;
248
249         return __blkdev_issue_zero_pages(bdev, sector, nr_sects, gfp_mask,
250                                          biop);
251 }
252 EXPORT_SYMBOL(__blkdev_issue_zeroout);
253
254 /**
255  * blkdev_issue_zeroout - zero-fill a block range
256  * @bdev:       blockdev to write
257  * @sector:     start sector
258  * @nr_sects:   number of sectors to write
259  * @gfp_mask:   memory allocation flags (for bio_alloc)
260  * @flags:      controls detailed behavior
261  *
262  * Description:
263  *  Zero-fill a block range, either using hardware offload or by explicitly
264  *  writing zeroes to the device.  See __blkdev_issue_zeroout() for the
265  *  valid values for %flags.
266  */
267 int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
268                 sector_t nr_sects, gfp_t gfp_mask, unsigned flags)
269 {
270         int ret = 0;
271         sector_t bs_mask;
272         struct bio *bio;
273         struct blk_plug plug;
274         bool try_write_zeroes = !!bdev_write_zeroes_sectors(bdev);
275
276         bs_mask = (bdev_logical_block_size(bdev) >> 9) - 1;
277         if ((sector | nr_sects) & bs_mask)
278                 return -EINVAL;
279
280 retry:
281         bio = NULL;
282         blk_start_plug(&plug);
283         if (try_write_zeroes) {
284                 ret = __blkdev_issue_write_zeroes(bdev, sector, nr_sects,
285                                                   gfp_mask, &bio, flags);
286         } else if (!(flags & BLKDEV_ZERO_NOFALLBACK)) {
287                 ret = __blkdev_issue_zero_pages(bdev, sector, nr_sects,
288                                                 gfp_mask, &bio);
289         } else {
290                 /* No zeroing offload support */
291                 ret = -EOPNOTSUPP;
292         }
293         if (ret == 0 && bio) {
294                 ret = submit_bio_wait(bio);
295                 bio_put(bio);
296         }
297         blk_finish_plug(&plug);
298         if (ret && try_write_zeroes) {
299                 if (!(flags & BLKDEV_ZERO_NOFALLBACK)) {
300                         try_write_zeroes = false;
301                         goto retry;
302                 }
303                 if (!bdev_write_zeroes_sectors(bdev)) {
304                         /*
305                          * Zeroing offload support was indicated, but the
306                          * device reported ILLEGAL REQUEST (for some devices
307                          * there is no non-destructive way to verify whether
308                          * WRITE ZEROES is actually supported).
309                          */
310                         ret = -EOPNOTSUPP;
311                 }
312         }
313
314         return ret;
315 }
316 EXPORT_SYMBOL(blkdev_issue_zeroout);