]>
git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blob - block/blk-lib.c
ff2a7f04af4df84475e107e2d2d244da6739eb1e
2 * Functions related to generic helpers functions
4 #include <linux/kernel.h>
5 #include <linux/module.h>
7 #include <linux/blkdev.h>
8 #include <linux/scatterlist.h>
12 static struct bio
*next_bio(struct bio
*bio
, unsigned int nr_pages
,
15 struct bio
*new = bio_alloc(gfp
, nr_pages
);
25 int __blkdev_issue_discard(struct block_device
*bdev
, sector_t sector
,
26 sector_t nr_sects
, gfp_t gfp_mask
, int op_flags
,
29 struct request_queue
*q
= bdev_get_queue(bdev
);
30 struct bio
*bio
= *biop
;
31 unsigned int granularity
;
36 if (!blk_queue_discard(q
))
38 if ((op_flags
& REQ_SECURE
) && !blk_queue_secdiscard(q
))
41 /* Zero-sector (unknown) and one-sector granularities are the same. */
42 granularity
= max(q
->limits
.discard_granularity
>> 9, 1U);
43 alignment
= (bdev_discard_alignment(bdev
) >> 9) % granularity
;
46 unsigned int req_sects
;
47 sector_t end_sect
, tmp
;
49 /* Make sure bi_size doesn't overflow */
50 req_sects
= min_t(sector_t
, nr_sects
, UINT_MAX
>> 9);
53 * If splitting a request, and the next starting sector would be
54 * misaligned, stop the discard at the previous aligned sector.
56 end_sect
= sector
+ req_sects
;
58 if (req_sects
< nr_sects
&&
59 sector_div(tmp
, granularity
) != alignment
) {
60 end_sect
= end_sect
- alignment
;
61 sector_div(end_sect
, granularity
);
62 end_sect
= end_sect
* granularity
+ alignment
;
63 req_sects
= end_sect
- sector
;
66 bio
= next_bio(bio
, 1, gfp_mask
);
67 bio
->bi_iter
.bi_sector
= sector
;
69 bio_set_op_attrs(bio
, REQ_OP_DISCARD
, op_flags
);
71 bio
->bi_iter
.bi_size
= req_sects
<< 9;
72 nr_sects
-= req_sects
;
76 * We can loop for a long time in here, if someone does
77 * full device discards (like mkfs). Be nice and allow
78 * us to schedule out to avoid softlocking if preempt
87 EXPORT_SYMBOL(__blkdev_issue_discard
);
90 * blkdev_issue_discard - queue a discard
91 * @bdev: blockdev to issue discard for
92 * @sector: start sector
93 * @nr_sects: number of sectors to discard
94 * @gfp_mask: memory allocation flags (for bio_alloc)
95 * @flags: BLKDEV_IFL_* flags to control behaviour
98 * Issue a discard request for the sectors in question.
100 int blkdev_issue_discard(struct block_device
*bdev
, sector_t sector
,
101 sector_t nr_sects
, gfp_t gfp_mask
, unsigned long flags
)
104 struct bio
*bio
= NULL
;
105 struct blk_plug plug
;
108 if (flags
& BLKDEV_DISCARD_SECURE
)
109 op_flags
|= REQ_SECURE
;
111 blk_start_plug(&plug
);
112 ret
= __blkdev_issue_discard(bdev
, sector
, nr_sects
, gfp_mask
, op_flags
,
115 ret
= submit_bio_wait(bio
);
116 if (ret
== -EOPNOTSUPP
)
119 blk_finish_plug(&plug
);
123 EXPORT_SYMBOL(blkdev_issue_discard
);
126 * blkdev_issue_write_same - queue a write same operation
127 * @bdev: target blockdev
128 * @sector: start sector
129 * @nr_sects: number of sectors to write
130 * @gfp_mask: memory allocation flags (for bio_alloc)
131 * @page: page containing data to write
134 * Issue a write same request for the sectors in question.
136 int blkdev_issue_write_same(struct block_device
*bdev
, sector_t sector
,
137 sector_t nr_sects
, gfp_t gfp_mask
,
140 struct request_queue
*q
= bdev_get_queue(bdev
);
141 unsigned int max_write_same_sectors
;
142 struct bio
*bio
= NULL
;
148 /* Ensure that max_write_same_sectors doesn't overflow bi_size */
149 max_write_same_sectors
= UINT_MAX
>> 9;
152 bio
= next_bio(bio
, 1, gfp_mask
);
153 bio
->bi_iter
.bi_sector
= sector
;
156 bio
->bi_io_vec
->bv_page
= page
;
157 bio
->bi_io_vec
->bv_offset
= 0;
158 bio
->bi_io_vec
->bv_len
= bdev_logical_block_size(bdev
);
159 bio_set_op_attrs(bio
, REQ_OP_WRITE_SAME
, 0);
161 if (nr_sects
> max_write_same_sectors
) {
162 bio
->bi_iter
.bi_size
= max_write_same_sectors
<< 9;
163 nr_sects
-= max_write_same_sectors
;
164 sector
+= max_write_same_sectors
;
166 bio
->bi_iter
.bi_size
= nr_sects
<< 9;
172 ret
= submit_bio_wait(bio
);
173 return ret
!= -EOPNOTSUPP
? ret
: 0;
175 EXPORT_SYMBOL(blkdev_issue_write_same
);
178 * blkdev_issue_zeroout - generate number of zero filed write bios
179 * @bdev: blockdev to issue
180 * @sector: start sector
181 * @nr_sects: number of sectors to write
182 * @gfp_mask: memory allocation flags (for bio_alloc)
185 * Generate and issue number of bios with zerofiled pages.
188 static int __blkdev_issue_zeroout(struct block_device
*bdev
, sector_t sector
,
189 sector_t nr_sects
, gfp_t gfp_mask
)
192 struct bio
*bio
= NULL
;
195 while (nr_sects
!= 0) {
196 bio
= next_bio(bio
, min(nr_sects
, (sector_t
)BIO_MAX_PAGES
),
198 bio
->bi_iter
.bi_sector
= sector
;
200 bio_set_op_attrs(bio
, REQ_OP_WRITE
, 0);
202 while (nr_sects
!= 0) {
203 sz
= min((sector_t
) PAGE_SIZE
>> 9 , nr_sects
);
204 ret
= bio_add_page(bio
, ZERO_PAGE(0), sz
<< 9, 0);
205 nr_sects
-= ret
>> 9;
213 return submit_bio_wait(bio
);
218 * blkdev_issue_zeroout - zero-fill a block range
219 * @bdev: blockdev to write
220 * @sector: start sector
221 * @nr_sects: number of sectors to write
222 * @gfp_mask: memory allocation flags (for bio_alloc)
223 * @discard: whether to discard the block range
226 * Zero-fill a block range. If the discard flag is set and the block
227 * device guarantees that subsequent READ operations to the block range
228 * in question will return zeroes, the blocks will be discarded. Should
229 * the discard request fail, if the discard flag is not set, or if
230 * discard_zeroes_data is not supported, this function will resort to
231 * zeroing the blocks manually, thus provisioning (allocating,
232 * anchoring) them. If the block device supports the WRITE SAME command
233 * blkdev_issue_zeroout() will use it to optimize the process of
234 * clearing the block range. Otherwise the zeroing will be performed
235 * using regular WRITE calls.
238 int blkdev_issue_zeroout(struct block_device
*bdev
, sector_t sector
,
239 sector_t nr_sects
, gfp_t gfp_mask
, bool discard
)
241 struct request_queue
*q
= bdev_get_queue(bdev
);
243 if (discard
&& blk_queue_discard(q
) && q
->limits
.discard_zeroes_data
&&
244 blkdev_issue_discard(bdev
, sector
, nr_sects
, gfp_mask
, 0) == 0)
247 if (bdev_write_same(bdev
) &&
248 blkdev_issue_write_same(bdev
, sector
, nr_sects
, gfp_mask
,
252 return __blkdev_issue_zeroout(bdev
, sector
, nr_sects
, gfp_mask
);
254 EXPORT_SYMBOL(blkdev_issue_zeroout
);