mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +02:00 
			
		
		
		
	iomap: support REQ_OP_ZONE_APPEND
A ZONE_APPEND bio must follow hardware restrictions (e.g. not exceeding max_zone_append_sectors) not to be split. bio_iov_iter_get_pages builds such restricted bio using __bio_iov_append_get_pages if bio_op(bio) == REQ_OP_ZONE_APPEND. To utilize it, we need to set the bio_op before calling bio_iov_iter_get_pages(). This commit introduces IOMAP_F_ZONE_APPEND, so that iomap user can set the flag to indicate they want REQ_OP_ZONE_APPEND and restricted bio. Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									ae29333fa6
								
							
						
					
					
						commit
						c3b0e880bb
					
				
					 2 changed files with 38 additions and 6 deletions
				
			
		|  | @ -201,6 +201,34 @@ iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos, | |||
| 	iomap_dio_submit_bio(dio, iomap, bio, pos); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Figure out the bio's operation flags from the dio request, the | ||||
|  * mapping, and whether or not we want FUA.  Note that we can end up | ||||
|  * clearing the WRITE_FUA flag in the dio request. | ||||
|  */ | ||||
| static inline unsigned int | ||||
| iomap_dio_bio_opflags(struct iomap_dio *dio, struct iomap *iomap, bool use_fua) | ||||
| { | ||||
| 	unsigned int opflags = REQ_SYNC | REQ_IDLE; | ||||
| 
 | ||||
| 	if (!(dio->flags & IOMAP_DIO_WRITE)) { | ||||
| 		WARN_ON_ONCE(iomap->flags & IOMAP_F_ZONE_APPEND); | ||||
| 		return REQ_OP_READ; | ||||
| 	} | ||||
| 
 | ||||
| 	if (iomap->flags & IOMAP_F_ZONE_APPEND) | ||||
| 		opflags |= REQ_OP_ZONE_APPEND; | ||||
| 	else | ||||
| 		opflags |= REQ_OP_WRITE; | ||||
| 
 | ||||
| 	if (use_fua) | ||||
| 		opflags |= REQ_FUA; | ||||
| 	else | ||||
| 		dio->flags &= ~IOMAP_DIO_WRITE_FUA; | ||||
| 
 | ||||
| 	return opflags; | ||||
| } | ||||
| 
 | ||||
| static loff_t | ||||
| iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, | ||||
| 		struct iomap_dio *dio, struct iomap *iomap) | ||||
|  | @ -208,6 +236,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, | |||
| 	unsigned int blkbits = blksize_bits(bdev_logical_block_size(iomap->bdev)); | ||||
| 	unsigned int fs_block_size = i_blocksize(inode), pad; | ||||
| 	unsigned int align = iov_iter_alignment(dio->submit.iter); | ||||
| 	unsigned int bio_opf; | ||||
| 	struct bio *bio; | ||||
| 	bool need_zeroout = false; | ||||
| 	bool use_fua = false; | ||||
|  | @ -263,6 +292,13 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, | |||
| 			iomap_dio_zero(dio, iomap, pos - pad, pad); | ||||
| 	} | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Set the operation flags early so that bio_iov_iter_get_pages | ||||
| 	 * can set up the page vector appropriately for a ZONE_APPEND | ||||
| 	 * operation. | ||||
| 	 */ | ||||
| 	bio_opf = iomap_dio_bio_opflags(dio, iomap, use_fua); | ||||
| 
 | ||||
| 	do { | ||||
| 		size_t n; | ||||
| 		if (dio->error) { | ||||
|  | @ -278,6 +314,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, | |||
| 		bio->bi_ioprio = dio->iocb->ki_ioprio; | ||||
| 		bio->bi_private = dio; | ||||
| 		bio->bi_end_io = iomap_dio_bio_end_io; | ||||
| 		bio->bi_opf = bio_opf; | ||||
| 
 | ||||
| 		ret = bio_iov_iter_get_pages(bio, dio->submit.iter); | ||||
| 		if (unlikely(ret)) { | ||||
|  | @ -293,14 +330,8 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length, | |||
| 
 | ||||
| 		n = bio->bi_iter.bi_size; | ||||
| 		if (dio->flags & IOMAP_DIO_WRITE) { | ||||
| 			bio->bi_opf = REQ_OP_WRITE | REQ_SYNC | REQ_IDLE; | ||||
| 			if (use_fua) | ||||
| 				bio->bi_opf |= REQ_FUA; | ||||
| 			else | ||||
| 				dio->flags &= ~IOMAP_DIO_WRITE_FUA; | ||||
| 			task_io_account_write(n); | ||||
| 		} else { | ||||
| 			bio->bi_opf = REQ_OP_READ; | ||||
| 			if (dio->flags & IOMAP_DIO_DIRTY) | ||||
| 				bio_set_pages_dirty(bio); | ||||
| 		} | ||||
|  |  | |||
|  | @ -55,6 +55,7 @@ struct vm_fault; | |||
| #define IOMAP_F_SHARED		0x04 | ||||
| #define IOMAP_F_MERGED		0x08 | ||||
| #define IOMAP_F_BUFFER_HEAD	0x10 | ||||
| #define IOMAP_F_ZONE_APPEND	0x20 | ||||
| 
 | ||||
| /*
 | ||||
|  * Flags set by the core iomap code during operations: | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Naohiro Aota
						Naohiro Aota