Unverified Commit ed86ac20 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!5720 [sync] PR-5708: ext4: dio: Put endio under

Merge Pull Request from: @openeuler-sync-bot 
 

Origin pull request: 
https://gitee.com/openeuler/kernel/pulls/5708 
 
PR sync from: Zhihao Cheng <chengzhihao1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/5JTDAWSCYRLOYFIKLJUDKUHON774VS5F/ 
Christoph Hellwig (2):
  iomap: rename the flags variable in __iomap_dio_rw
  iomap: pass a flags argument to iomap_dio_rw

Jens Axboe (3):
  iomap: cleanup up iomap_dio_bio_end_io()
  iomap: use an unsigned type for IOMAP_DIO_* defines
  iomap: add IOMAP_DIO_INLINE_COMP

Zhihao Cheng (2):
  iomap: Add a IOMAP_DIO_MAY_INLINE_COMP flag
  ext4: Optimize endio process for DIO overwrites


-- 
2.31.1
 
https://gitee.com/openeuler/kernel/issues/I90ZB5 
 
Link:https://gitee.com/openeuler/kernel/pulls/5720

 

Reviewed-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents e98cb787 6fac6d0e
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -8084,10 +8084,10 @@ ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
	 */
	if (current->journal_info)
		ret = iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops,
				   &btrfs_sync_dops, is_sync_kiocb(iocb));
				   &btrfs_sync_dops, 0);
	else
		ret = iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops,
				   &btrfs_dio_ops, is_sync_kiocb(iocb));
				   &btrfs_dio_ops, 0);

	if (ret == -ENOTBLK)
		ret = 0;
+9 −5
Original line number Diff line number Diff line
@@ -75,8 +75,7 @@ static ssize_t ext4_dio_read_iter(struct kiocb *iocb, struct iov_iter *to)
		return generic_file_read_iter(iocb, to);
	}

	ret = iomap_dio_rw(iocb, to, &ext4_iomap_ops, NULL,
			   is_sync_kiocb(iocb));
	ret = iomap_dio_rw(iocb, to, &ext4_iomap_ops, NULL, 0);
	inode_unlock_shared(inode);

	file_accessed(iocb->ki_filp);
@@ -490,8 +489,10 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
	loff_t offset = iocb->ki_pos;
	size_t count = iov_iter_count(from);
	const struct iomap_ops *iomap_ops = &ext4_iomap_ops;
	const struct iomap_dio_ops *iomap_dops = &ext4_dio_write_ops;
	bool extend = false, unaligned_io = false, unwritten = false;
	bool ilock_shared = true;
	int dio_flags = 0;

	/*
	 * We initially start with shared inode lock unless it is
@@ -584,10 +585,13 @@ static ssize_t ext4_dio_write_iter(struct kiocb *iocb, struct iov_iter *from)
		ext4_journal_stop(handle);
	}

	if (ilock_shared && !unwritten)
	if (ilock_shared && !unwritten) {
		iomap_ops = &ext4_iomap_overwrite_ops;
	ret = iomap_dio_rw(iocb, from, iomap_ops, &ext4_dio_write_ops,
			   is_sync_kiocb(iocb) || unaligned_io || extend);
		iomap_dops = NULL;
		dio_flags = IOMAP_DIO_MAY_INLINE_COMP;
	} else if (unaligned_io || extend)
		dio_flags |= IOMAP_DIO_FORCE_WAIT;
	ret = iomap_dio_rw(iocb, from, iomap_ops, iomap_dops, dio_flags);
	if (ret == -ENOTBLK)
		ret = 0;

+2 −5
Original line number Diff line number Diff line
@@ -798,9 +798,7 @@ static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to,
	if (ret)
		goto out_uninit;

	ret = iomap_dio_rw(iocb, to, &gfs2_iomap_ops, NULL,
			   is_sync_kiocb(iocb));

	ret = iomap_dio_rw(iocb, to, &gfs2_iomap_ops, NULL, 0);
	gfs2_glock_dq(gh);
out_uninit:
	gfs2_holder_uninit(gh);
@@ -834,8 +832,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from,
	if (offset + len > i_size_read(&ip->i_inode))
		goto out;

	ret = iomap_dio_rw(iocb, from, &gfs2_iomap_ops, NULL,
			   is_sync_kiocb(iocb));
	ret = iomap_dio_rw(iocb, from, &gfs2_iomap_ops, NULL, 0);
	if (ret == -ENOTBLK)
		ret = 0;
out:
+56 −28
Original line number Diff line number Diff line
@@ -18,10 +18,11 @@
 * Private flags for iomap_dio, must not overlap with the public ones in
 * iomap.h:
 */
#define IOMAP_DIO_WRITE_FUA	(1 << 28)
#define IOMAP_DIO_NEED_SYNC	(1 << 29)
#define IOMAP_DIO_WRITE		(1 << 30)
#define IOMAP_DIO_DIRTY		(1 << 31)
#define IOMAP_DIO_INLINE_COMP	(1U << 27)
#define IOMAP_DIO_WRITE_FUA	(1U << 28)
#define IOMAP_DIO_NEED_SYNC	(1U << 29)
#define IOMAP_DIO_WRITE		(1U << 30)
#define IOMAP_DIO_DIRTY		(1U << 31)

struct iomap_dio {
	struct kiocb		*iocb;
@@ -109,7 +110,8 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio)
	 * zeros from unwritten extents.
	 */
	if (!dio->error && dio->size &&
	    (dio->flags & IOMAP_DIO_WRITE) && inode->i_mapping->nrpages) {
	    (dio->flags & IOMAP_DIO_WRITE) && inode->i_mapping->nrpages &&
	    !(dio->flags & IOMAP_DIO_INLINE_COMP)) {
		int err;
		err = invalidate_inode_pages2_range(inode->i_mapping,
				offset >> PAGE_SHIFT,
@@ -123,8 +125,10 @@ ssize_t iomap_dio_complete(struct iomap_dio *dio)
	 * If this is a DSYNC write, make sure we push it to stable storage now
	 * that we've written data.
	 */
	if (ret > 0 && (dio->flags & IOMAP_DIO_NEED_SYNC))
	if (ret > 0 && (dio->flags & IOMAP_DIO_NEED_SYNC)) {
		WARN_ON_ONCE(dio->flags & IOMAP_DIO_INLINE_COMP);
		ret = generic_write_sync(iocb, ret);
	}

	kfree(dio);

@@ -154,25 +158,43 @@ static void iomap_dio_bio_end_io(struct bio *bio)
{
	struct iomap_dio *dio = bio->bi_private;
	bool should_dirty = (dio->flags & IOMAP_DIO_DIRTY);
	struct kiocb *iocb = dio->iocb;

	if (bio->bi_status)
		iomap_dio_set_error(dio, blk_status_to_errno(bio->bi_status));
	if (!atomic_dec_and_test(&dio->ref))
		goto release_bio;

	if (atomic_dec_and_test(&dio->ref)) {
	/*
	 * Synchronous dio, task itself will handle any completion work
	 * that needs after IO. All we need to do is wake the task.
	 */
	if (dio->wait_for_completion) {
		struct task_struct *waiter = dio->submit.waiter;

		WRITE_ONCE(dio->submit.waiter, NULL);
		blk_wake_io_task(waiter);
		} else if (dio->flags & IOMAP_DIO_WRITE) {
			struct inode *inode = file_inode(dio->iocb->ki_filp);
		goto release_bio;
	}

			INIT_WORK(&dio->aio.work, iomap_dio_complete_work);
			queue_work(inode->i_sb->s_dio_done_wq, &dio->aio.work);
		} else {
	/*
	 * Flagged with IOMAP_DIO_INLINE_COMP, we can complete it inline
	 */
	if (dio->flags & IOMAP_DIO_INLINE_COMP) {
		iomap_dio_complete_work(&dio->aio.work);
		}
		goto release_bio;
	}

	/*
	 * Async DIO completion that requires filesystem level completion work
	 * gets punted to a work queue to complete as the operation may require
	 * more IO to be issued to finalise filesystem metadata changes or
	 * guarantee data integrity.
	 */
	INIT_WORK(&dio->aio.work, iomap_dio_complete_work);
	queue_work(file_inode(iocb->ki_filp)->i_sb->s_dio_done_wq,
			&dio->aio.work);
release_bio:
	if (should_dirty) {
		bio_check_pages_dirty(bio);
	} else {
@@ -420,23 +442,22 @@ iomap_dio_actor(struct inode *inode, loff_t pos, loff_t length,
struct iomap_dio *
__iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
		const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
		bool wait_for_completion)
		unsigned int dio_flags)
{
	struct address_space *mapping = iocb->ki_filp->f_mapping;
	struct inode *inode = file_inode(iocb->ki_filp);
	size_t count = iov_iter_count(iter);
	loff_t pos = iocb->ki_pos;
	loff_t end = iocb->ki_pos + count - 1, ret = 0;
	unsigned int flags = IOMAP_DIRECT;
	bool wait_for_completion =
		is_sync_kiocb(iocb) || (dio_flags & IOMAP_DIO_FORCE_WAIT);
	unsigned int iomap_flags = IOMAP_DIRECT;
	struct blk_plug plug;
	struct iomap_dio *dio;

	if (!count)
		return NULL;

	if (WARN_ON(is_sync_kiocb(iocb) && !wait_for_completion))
		return ERR_PTR(-EIO);

	dio = kmalloc(sizeof(*dio), GFP_KERNEL);
	if (!dio)
		return ERR_PTR(-ENOMEM);
@@ -455,18 +476,25 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
	dio->submit.last_queue = NULL;

	if (iov_iter_rw(iter) == READ) {
		/* reads can always complete inline */
		dio->flags |= IOMAP_DIO_INLINE_COMP;

		if (pos >= dio->i_size)
			goto out_free_dio;

		if (iter_is_iovec(iter))
			dio->flags |= IOMAP_DIO_DIRTY;
	} else {
		flags |= IOMAP_WRITE;
		iomap_flags |= IOMAP_WRITE;
		dio->flags |= IOMAP_DIO_WRITE;

		/* for data sync or sync, we need sync completion processing */
		if (iocb->ki_flags & IOCB_DSYNC)
			dio->flags |= IOMAP_DIO_NEED_SYNC;
		else if (dio_flags & IOMAP_DIO_MAY_INLINE_COMP) {
			/* writes could complete inline */
			dio->flags |= IOMAP_DIO_INLINE_COMP;
		}

		/*
		 * For datasync only writes, we optimistically try using FUA for
@@ -483,7 +511,7 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
			ret = -EAGAIN;
			goto out_free_dio;
		}
		flags |= IOMAP_NOWAIT;
		iomap_flags |= IOMAP_NOWAIT;
	}

	ret = filemap_write_and_wait_range(mapping, pos, end);
@@ -514,7 +542,7 @@ __iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,

	blk_start_plug(&plug);
	do {
		ret = iomap_apply(inode, pos, count, flags, ops, dio,
		ret = iomap_apply(inode, pos, count, iomap_flags, ops, dio,
				iomap_dio_actor);
		if (ret <= 0) {
			/* magic error code to fall back to buffered I/O */
@@ -598,11 +626,11 @@ EXPORT_SYMBOL_GPL(__iomap_dio_rw);
ssize_t
iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
		const struct iomap_ops *ops, const struct iomap_dio_ops *dops,
		bool wait_for_completion)
		unsigned int dio_flags)
{
	struct iomap_dio *dio;

	dio = __iomap_dio_rw(iocb, iter, ops, dops, wait_for_completion);
	dio = __iomap_dio_rw(iocb, iter, ops, dops, dio_flags);
	if (IS_ERR_OR_NULL(dio))
		return PTR_ERR_OR_ZERO(dio);
	return iomap_dio_complete(dio);
+2 −3
Original line number Diff line number Diff line
@@ -263,8 +263,7 @@ xfs_file_dio_aio_read(
	ret = xfs_ilock_iocb(iocb, XFS_IOLOCK_SHARED);
	if (ret)
		return ret;
	ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL,
			is_sync_kiocb(iocb));
	ret = iomap_dio_rw(iocb, to, &xfs_read_iomap_ops, NULL, 0);
	xfs_iunlock(ip, XFS_IOLOCK_SHARED);

	return ret;
@@ -651,7 +650,7 @@ xfs_file_dio_aio_write(
	 */
	ret = iomap_dio_rw(iocb, from, &xfs_direct_write_iomap_ops,
			   &xfs_dio_write_ops,
			   is_sync_kiocb(iocb) || unaligned_io);
			   unaligned_io ? IOMAP_DIO_FORCE_WAIT : 0);
out:
	if (iolock)
		xfs_iunlock(ip, iolock);
Loading