From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-by2nam03on0117.outbound.protection.outlook.com ([104.47.42.117]:22121 "EHLO NAM03-BY2-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729566AbeIQI2C (ORCPT ); Mon, 17 Sep 2018 04:28:02 -0400 From: Sasha Levin To: "stable@vger.kernel.org" , "linux-kernel@vger.kernel.org" CC: Andreas Gruenbacher , Christoph Hellwig , "Darrick J . Wong" , Sasha Levin Subject: [PATCH AUTOSEL 4.18 109/136] iomap: complete partial direct I/O writes synchronously Date: Mon, 17 Sep 2018 03:01:21 +0000 Message-ID: <20180917030006.245495-109-alexander.levin@microsoft.com> References: <20180917030006.245495-1-alexander.levin@microsoft.com> In-Reply-To: <20180917030006.245495-1-alexander.levin@microsoft.com> Content-Language: en-US Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Sender: stable-owner@vger.kernel.org List-ID: From: Andreas Gruenbacher [ Upstream commit ebf00be37de35788cad72f4f20b4a39e30c0be4a ] According to xfstest generic/240, applications seem to expect direct I/O writes to either complete as a whole or to fail; short direct I/O writes are apparently not appreciated. This means that when only part of an asynchronous direct I/O write succeeds, we can either fail the entire write, or we can wait for the partial write to complete and retry the remaining write as buffered I/O. The old __blockdev_direct_IO helper has code for waiting for partial writes to complete; the new iomap_dio_rw iomap helper does not. The above mentioned fallback mode is needed for gfs2, which doesn't allow block allocations under direct I/O to avoid taking cluster-wide exclusive locks. As a consequence, an asynchronous direct I/O write to a file range that contains a hole will result in a short write. In that case, wait for the short write to complete to allow gfs2 to recover. Signed-off-by: Andreas Gruenbacher Signed-off-by: Christoph Hellwig Reviewed-by: Darrick J. Wong Signed-off-by: Darrick J. Wong Signed-off-by: Sasha Levin --- fs/iomap.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/fs/iomap.c b/fs/iomap.c index 0d0bd8845586..af6144fd4919 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -811,6 +811,7 @@ struct iomap_dio { atomic_t ref; unsigned flags; int error; + bool wait_for_completion; =20 union { /* used during submission and for synchronous completion: */ @@ -914,9 +915,8 @@ static void iomap_dio_bio_end_io(struct bio *bio) iomap_dio_set_error(dio, blk_status_to_errno(bio->bi_status)); =20 if (atomic_dec_and_test(&dio->ref)) { - if (is_sync_kiocb(dio->iocb)) { + if (dio->wait_for_completion) { struct task_struct *waiter =3D dio->submit.waiter; - WRITE_ONCE(dio->submit.waiter, NULL); wake_up_process(waiter); } else if (dio->flags & IOMAP_DIO_WRITE) { @@ -1131,13 +1131,12 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *i= ter, dio->end_io =3D end_io; dio->error =3D 0; dio->flags =3D 0; + dio->wait_for_completion =3D is_sync_kiocb(iocb); =20 dio->submit.iter =3D iter; - if (is_sync_kiocb(iocb)) { - dio->submit.waiter =3D current; - dio->submit.cookie =3D BLK_QC_T_NONE; - dio->submit.last_queue =3D NULL; - } + dio->submit.waiter =3D current; + dio->submit.cookie =3D BLK_QC_T_NONE; + dio->submit.last_queue =3D NULL; =20 if (iov_iter_rw(iter) =3D=3D READ) { if (pos >=3D dio->i_size) @@ -1187,7 +1186,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *ite= r, dio_warn_stale_pagecache(iocb->ki_filp); ret =3D 0; =20 - if (iov_iter_rw(iter) =3D=3D WRITE && !is_sync_kiocb(iocb) && + if (iov_iter_rw(iter) =3D=3D WRITE && !dio->wait_for_completion && !inode->i_sb->s_dio_done_wq) { ret =3D sb_init_dio_done_wq(inode->i_sb); if (ret < 0) @@ -1202,8 +1201,10 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *it= er, iomap_dio_actor); if (ret <=3D 0) { /* magic error code to fall back to buffered I/O */ - if (ret =3D=3D -ENOTBLK) + if (ret =3D=3D -ENOTBLK) { + dio->wait_for_completion =3D true; ret =3D 0; + } break; } pos +=3D ret; @@ -1224,7 +1225,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *ite= r, dio->flags &=3D ~IOMAP_DIO_NEED_SYNC; =20 if (!atomic_dec_and_test(&dio->ref)) { - if (!is_sync_kiocb(iocb)) + if (!dio->wait_for_completion) return -EIOCBQUEUED; =20 for (;;) { --=20 2.17.1