mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	block: add __blkdev_issue_discard
This is a version of blkdev_issue_discard which doesn't wait for the I/O to complete, but instead allows the caller to submit the final bio and/or chain it to others. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Ming Lin <ming.l@ssi.samsung.com> Signed-off-by: Sagi Grimberg <sagig@grimberg.me> Reviewed-by: Ming Lei <tom.leiming@gmail.com> Signed-off-by: Jens Axboe <axboe@fb.com>
This commit is contained in:
		
							parent
							
								
									9082e87bfb
								
							
						
					
					
						commit
						38f2525533
					
				
					 2 changed files with 39 additions and 26 deletions
				
			
		| 
						 | 
				
			
			@ -22,45 +22,25 @@ static struct bio *next_bio(struct bio *bio, int rw, unsigned int nr_pages,
 | 
			
		|||
	return new;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * blkdev_issue_discard - queue a discard
 | 
			
		||||
 * @bdev:	blockdev to issue discard for
 | 
			
		||||
 * @sector:	start sector
 | 
			
		||||
 * @nr_sects:	number of sectors to discard
 | 
			
		||||
 * @gfp_mask:	memory allocation flags (for bio_alloc)
 | 
			
		||||
 * @flags:	BLKDEV_IFL_* flags to control behaviour
 | 
			
		||||
 *
 | 
			
		||||
 * Description:
 | 
			
		||||
 *    Issue a discard request for the sectors in question.
 | 
			
		||||
 */
 | 
			
		||||
int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 | 
			
		||||
		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
 | 
			
		||||
int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 | 
			
		||||
		sector_t nr_sects, gfp_t gfp_mask, int type, struct bio **biop)
 | 
			
		||||
{
 | 
			
		||||
	struct request_queue *q = bdev_get_queue(bdev);
 | 
			
		||||
	int type = REQ_WRITE | REQ_DISCARD;
 | 
			
		||||
	struct bio *bio = *biop;
 | 
			
		||||
	unsigned int granularity;
 | 
			
		||||
	int alignment;
 | 
			
		||||
	struct bio *bio = NULL;
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	struct blk_plug plug;
 | 
			
		||||
 | 
			
		||||
	if (!q)
 | 
			
		||||
		return -ENXIO;
 | 
			
		||||
 | 
			
		||||
	if (!blk_queue_discard(q))
 | 
			
		||||
		return -EOPNOTSUPP;
 | 
			
		||||
	if ((type & REQ_SECURE) && !blk_queue_secdiscard(q))
 | 
			
		||||
		return -EOPNOTSUPP;
 | 
			
		||||
 | 
			
		||||
	/* Zero-sector (unknown) and one-sector granularities are the same.  */
 | 
			
		||||
	granularity = max(q->limits.discard_granularity >> 9, 1U);
 | 
			
		||||
	alignment = (bdev_discard_alignment(bdev) >> 9) % granularity;
 | 
			
		||||
 | 
			
		||||
	if (flags & BLKDEV_DISCARD_SECURE) {
 | 
			
		||||
		if (!blk_queue_secdiscard(q))
 | 
			
		||||
			return -EOPNOTSUPP;
 | 
			
		||||
		type |= REQ_SECURE;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	blk_start_plug(&plug);
 | 
			
		||||
	while (nr_sects) {
 | 
			
		||||
		unsigned int req_sects;
 | 
			
		||||
		sector_t end_sect, tmp;
 | 
			
		||||
| 
						 | 
				
			
			@ -98,7 +78,38 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 | 
			
		|||
		 */
 | 
			
		||||
		cond_resched();
 | 
			
		||||
	}
 | 
			
		||||
	if (bio)
 | 
			
		||||
 | 
			
		||||
	*biop = bio;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL(__blkdev_issue_discard);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * blkdev_issue_discard - queue a discard
 | 
			
		||||
 * @bdev:	blockdev to issue discard for
 | 
			
		||||
 * @sector:	start sector
 | 
			
		||||
 * @nr_sects:	number of sectors to discard
 | 
			
		||||
 * @gfp_mask:	memory allocation flags (for bio_alloc)
 | 
			
		||||
 * @flags:	BLKDEV_IFL_* flags to control behaviour
 | 
			
		||||
 *
 | 
			
		||||
 * Description:
 | 
			
		||||
 *    Issue a discard request for the sectors in question.
 | 
			
		||||
 */
 | 
			
		||||
int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 | 
			
		||||
		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags)
 | 
			
		||||
{
 | 
			
		||||
	int type = REQ_WRITE | REQ_DISCARD;
 | 
			
		||||
	struct bio *bio = NULL;
 | 
			
		||||
	struct blk_plug plug;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (flags & BLKDEV_DISCARD_SECURE)
 | 
			
		||||
		type |= REQ_SECURE;
 | 
			
		||||
 | 
			
		||||
	blk_start_plug(&plug);
 | 
			
		||||
	ret = __blkdev_issue_discard(bdev, sector, nr_sects, gfp_mask, type,
 | 
			
		||||
			&bio);
 | 
			
		||||
	if (!ret && bio)
 | 
			
		||||
		ret = submit_bio_wait(type, bio);
 | 
			
		||||
	blk_finish_plug(&plug);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1131,6 +1131,8 @@ static inline struct request *blk_map_queue_find_tag(struct blk_queue_tag *bqt,
 | 
			
		|||
extern int blkdev_issue_flush(struct block_device *, gfp_t, sector_t *);
 | 
			
		||||
extern int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 | 
			
		||||
		sector_t nr_sects, gfp_t gfp_mask, unsigned long flags);
 | 
			
		||||
extern int __blkdev_issue_discard(struct block_device *bdev, sector_t sector,
 | 
			
		||||
		sector_t nr_sects, gfp_t gfp_mask, int type, struct bio **biop);
 | 
			
		||||
extern int blkdev_issue_write_same(struct block_device *bdev, sector_t sector,
 | 
			
		||||
		sector_t nr_sects, gfp_t gfp_mask, struct page *page);
 | 
			
		||||
extern int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue