aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-barrier.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blk-barrier.c')
-rw-r--r--block/blk-barrier.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/block/blk-barrier.c b/block/blk-barrier.c
index a09ead19f9c5..273121c0eb80 100644
--- a/block/blk-barrier.c
+++ b/block/blk-barrier.c
@@ -315,3 +315,72 @@ int blkdev_issue_flush(struct block_device *bdev, sector_t *error_sector)
315 return ret; 315 return ret;
316} 316}
317EXPORT_SYMBOL(blkdev_issue_flush); 317EXPORT_SYMBOL(blkdev_issue_flush);
318
319static void blkdev_discard_end_io(struct bio *bio, int err)
320{
321 if (err) {
322 if (err == -EOPNOTSUPP)
323 set_bit(BIO_EOPNOTSUPP, &bio->bi_flags);
324 clear_bit(BIO_UPTODATE, &bio->bi_flags);
325 }
326
327 bio_put(bio);
328}
329
330/**
331 * blkdev_issue_discard - queue a discard
332 * @bdev: blockdev to issue discard for
333 * @sector: start sector
334 * @nr_sects: number of sectors to discard
335 *
336 * Description:
337 * Issue a discard request for the sectors in question. Does not wait.
338 */
339int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
340 unsigned nr_sects)
341{
342 struct request_queue *q;
343 struct bio *bio;
344 int ret = 0;
345
346 if (bdev->bd_disk == NULL)
347 return -ENXIO;
348
349 q = bdev_get_queue(bdev);
350 if (!q)
351 return -ENXIO;
352
353 if (!q->prepare_discard_fn)
354 return -EOPNOTSUPP;
355
356 while (nr_sects && !ret) {
357 bio = bio_alloc(GFP_KERNEL, 0);
358 if (!bio)
359 return -ENOMEM;
360
361 bio->bi_end_io = blkdev_discard_end_io;
362 bio->bi_bdev = bdev;
363
364 bio->bi_sector = sector;
365
366 if (nr_sects > q->max_hw_sectors) {
367 bio->bi_size = q->max_hw_sectors << 9;
368 nr_sects -= q->max_hw_sectors;
369 sector += q->max_hw_sectors;
370 } else {
371 bio->bi_size = nr_sects << 9;
372 nr_sects = 0;
373 }
374 bio_get(bio);
375 submit_bio(WRITE_DISCARD, bio);
376
377 /* Check if it failed immediately */
378 if (bio_flagged(bio, BIO_EOPNOTSUPP))
379 ret = -EOPNOTSUPP;
380 else if (!bio_flagged(bio, BIO_UPTODATE))
381 ret = -EIO;
382 bio_put(bio);
383 }
384 return ret;
385}
386EXPORT_SYMBOL(blkdev_issue_discard);