Re: [PATCH 3/8] iomap/xfs: wire up file_operations ->iopoll()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 2018-11-20 at 10:19 -0700, Jens Axboe wrote:
> Add an iomap implementation of fops->iopoll() and wire it up for
> XFS.
> 
> Signed-off-by: Jens Axboe <axboe@xxxxxxxxx>
> ---
>  fs/iomap.c            | 50 +++++++++++++++++++++++++++++--------------
>  fs/xfs/xfs_file.c     |  1 +
>  include/linux/iomap.h |  1 +
>  3 files changed, 36 insertions(+), 16 deletions(-)
> 
> diff --git a/fs/iomap.c b/fs/iomap.c
> index 74c1f37f0fd6..faf96198f99a 100644
> --- a/fs/iomap.c
> +++ b/fs/iomap.c
> @@ -1419,14 +1419,14 @@ struct iomap_dio {
>  	unsigned		flags;
>  	int			error;
>  	bool			wait_for_completion;
> +	blk_qc_t		cookie;
> +	struct request_queue	*last_queue;
>  
>  	union {
>  		/* used during submission and for synchronous completion: */
>  		struct {
>  			struct iov_iter		*iter;
>  			struct task_struct	*waiter;
> -			struct request_queue	*last_queue;
> -			blk_qc_t		cookie;
>  		} submit;
>  
>  		/* used for aio completion: */
> @@ -1436,6 +1436,30 @@ struct iomap_dio {
>  	};
>  };
>  
> +int iomap_dio_iopoll(struct kiocb *kiocb, bool spin)
> +{
> +	struct iomap_dio *dio = kiocb->private;
> +	struct request_queue *q = READ_ONCE(dio->last_queue);
> +
> +	if (!q || dio->cookie == BLK_QC_T_NONE)
> +		return 0;
> +	return blk_poll(q, READ_ONCE(dio->cookie), spin);

How about:
	blk_qc_t cookie = READ_ONCE(dio->cookie);

	if (!q || cookie == BLK_QC_T_NONE)
		return 0;
	return blk_poll(q, cookie, spin);

Is there a chance the dio->cookie in the if () condition
will be stale?

> 
> +}
> +EXPORT_SYMBOL_GPL(iomap_dio_iopoll);
> +
> +static void iomap_dio_submit_bio(struct iomap_dio *dio, struct iomap *iomap,
> +		struct bio *bio)
> +{
> +	atomic_inc(&dio->ref);
> +
> +	/*
> +	 * iomap_dio_iopoll can race with us.  A non-zero last_queue marks that
> +	 * we are ready to poll.
> +	 */
> +	WRITE_ONCE(dio->cookie, submit_bio(bio));
> +	WRITE_ONCE(dio->last_queue, bdev_get_queue(iomap->bdev));
> +}
> +
>  static ssize_t iomap_dio_complete(struct iomap_dio *dio)
>  {
>  	struct kiocb *iocb = dio->iocb;
> @@ -1548,7 +1572,7 @@ static void iomap_dio_bio_end_io(struct bio *bio)
>  	}
>  }
>  
> -static blk_qc_t
> +static void
>  iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos,
>  		unsigned len)
>  {
> @@ -1568,9 +1592,7 @@ iomap_dio_zero(struct iomap_dio *dio, struct iomap *iomap, loff_t pos,
>  	get_page(page);
>  	__bio_add_page(bio, page, len, 0);
>  	bio_set_op_attrs(bio, REQ_OP_WRITE, flags);
> -
> -	atomic_inc(&dio->ref);
> -	return submit_bio(bio);
> +	iomap_dio_submit_bio(dio, iomap, bio);
>  }
>  
>  static loff_t
> @@ -1676,11 +1698,7 @@ iomap_dio_bio_actor(struct inode *inode, loff_t pos, loff_t length,
>  		copied += n;
>  
>  		nr_pages = iov_iter_npages(&iter, BIO_MAX_PAGES);
> -
> -		atomic_inc(&dio->ref);
> -
> -		dio->submit.last_queue = bdev_get_queue(iomap->bdev);
> -		dio->submit.cookie = submit_bio(bio);
> +		iomap_dio_submit_bio(dio, iomap, bio);
>  	} while (nr_pages);
>  
>  	if (need_zeroout) {
> @@ -1782,6 +1800,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
>  	dio = kmalloc(sizeof(*dio), GFP_KERNEL);
>  	if (!dio)
>  		return -ENOMEM;
> +	iocb->private = dio;
>  
>  	dio->iocb = iocb;
>  	atomic_set(&dio->ref, 1);
> @@ -1791,11 +1810,11 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
>  	dio->error = 0;
>  	dio->flags = 0;
>  	dio->wait_for_completion = is_sync_kiocb(iocb);
> +	dio->cookie = BLK_QC_T_NONE;
> +	dio->last_queue = NULL;
>  
>  	dio->submit.iter = iter;
>  	dio->submit.waiter = current;
> -	dio->submit.cookie = BLK_QC_T_NONE;
> -	dio->submit.last_queue = NULL;
>  
>  	if (iov_iter_rw(iter) == READ) {
>  		if (pos >= dio->i_size)
> @@ -1894,9 +1913,8 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
>  				break;
>  
>  			if (!(iocb->ki_flags & IOCB_HIPRI) ||
> -			    !dio->submit.last_queue ||
> -			    !blk_poll(dio->submit.last_queue,
> -					 dio->submit.cookie, true))
> +			    !dio->last_queue ||
> +			    !blk_poll(dio->last_queue, dio->cookie, true))
>  				io_schedule();
>  		}
>  		__set_current_state(TASK_RUNNING);
> diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
> index 53c9ab8fb777..603e705781a4 100644
> --- a/fs/xfs/xfs_file.c
> +++ b/fs/xfs/xfs_file.c
> @@ -1203,6 +1203,7 @@ const struct file_operations xfs_file_operations = {
>  	.write_iter	= xfs_file_write_iter,
>  	.splice_read	= generic_file_splice_read,
>  	.splice_write	= iter_file_splice_write,
> +	.iopoll		= iomap_dio_iopoll,
>  	.unlocked_ioctl	= xfs_file_ioctl,
>  #ifdef CONFIG_COMPAT
>  	.compat_ioctl	= xfs_file_compat_ioctl,
> diff --git a/include/linux/iomap.h b/include/linux/iomap.h
> index 9a4258154b25..0fefb5455bda 100644
> --- a/include/linux/iomap.h
> +++ b/include/linux/iomap.h
> @@ -162,6 +162,7 @@ typedef int (iomap_dio_end_io_t)(struct kiocb *iocb, ssize_t ret,
>  		unsigned flags);
>  ssize_t iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
>  		const struct iomap_ops *ops, iomap_dio_end_io_t end_io);
> +int iomap_dio_iopoll(struct kiocb *kiocb, bool spin);
>  
>  #ifdef CONFIG_SWAP
>  struct file;




[Index of Archives]     [Linux RAID]     [Linux SCSI]     [Linux ATA RAID]     [IDE]     [Linux Wireless]     [Linux Kernel]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Device Mapper]

  Powered by Linux