On Tue, Dec 22, 2020 at 12:48:55PM +0900, Naohiro Aota wrote:
> 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: Christoph Hellwig <h...@lst.de>
> Signed-off-by: Naohiro Aota <naohiro.a...@wdc.com>

Looks fine to me too,
Reviewed-by: Darrick J. Wong <darrick.w...@oracle.com>

Do the authors intend this one patch to go into 5.12 via the iomap tree?

--D

> ---
>  fs/iomap/direct-io.c  | 43 +++++++++++++++++++++++++++++++++++++------
>  include/linux/iomap.h |  1 +
>  2 files changed, 38 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/iomap/direct-io.c b/fs/iomap/direct-io.c
> index 933f234d5bec..2273120d8ed7 100644
> --- a/fs/iomap/direct-io.c
> +++ b/fs/iomap/direct-io.c
> @@ -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);
>               }
> diff --git a/include/linux/iomap.h b/include/linux/iomap.h
> index 5bd3cac4df9c..8ebb1fa6f3b7 100644
> --- a/include/linux/iomap.h
> +++ b/include/linux/iomap.h
> @@ -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:
> -- 
> 2.27.0
> 

Reply via email to