Linux-Fsdevel Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Jan Kara <jack@suse.cz>
To: Gabriel Krisman Bertazi <krisman@collabora.com>
Cc: viro@zeniv.linux.org.uk, jaegeuk@kernel.org, chao@kernel.org,
	linux-fsdevel@vger.kernel.org,
	linux-f2fs-devel@lists.sourceforge.net,
	Jamie Liu <jamieliu@google.com>,
	kernel@collabora.com
Subject: Re: [PATCH 1/2] direct-io: defer alignment check until after EOF check
Date: Wed, 26 Aug 2020 16:28:57 +0200	[thread overview]
Message-ID: <20200826142857.GA8760@quack2.suse.cz> (raw)
In-Reply-To: <20200819200731.2972195-2-krisman@collabora.com>

On Wed 19-08-20 16:07:30, Gabriel Krisman Bertazi wrote:
> From: Jamie Liu <jamieliu@google.com>
> 
> Prior to commit 9fe55eea7e4b ("Fix race when checking i_size on direct
> i/o read"), an unaligned direct read past end of file would trigger EOF,
> since generic_file_aio_read detected this read-at-EOF condition and
> skipped the direct IO read entirely, returning 0. After that change, the
> read now reaches dio_generic, which detects the misalignment and returns
> EINVAL.
> 
> This consolidates the generic direct-io to follow the same behavior of
> filesystems.  Apparently, this fix will only affect ocfs2 since other
> filesystems do this verification before calling do_blockdev_direct_IO,
> with the exception of f2fs, which has the same bug, but is fixed in the
> next patch.
> 
> it can be verified by a read loop on a file that does a partial read
> before EOF (On file that doesn't end at an aligned address).  The
> following code fails on an unaligned file on filesystems without
> prior validation without this patch, but not on btrfs, ext4, and xfs.
> 
>   while (done < total) {
>     ssize_t delta = pread(fd, buf + done, total - done, off + done);
>     if (!delta)
>       break;
>     ...
>   }
> 
> Fix this regression by moving the misalignment check to after the EOF
> check added by commit 74cedf9b6c60 ("direct-io: Fix negative return from
> dio read beyond eof").
> 
> Signed-off-by: Jamie Liu <jamieliu@google.com>
> Co-developed-by: Gabriel Krisman Bertazi <krisman@collabora.com>
> Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>

Looks sane to me but I'd note that your patch also makes unaligned 0-length
reads succeed (probably don't care). Also your patch makes unaligned DIO reads
write-out page cache before returning EINVAL - that actually looks a bit
strange. Not that it would be outright bug but it seems strange to wait
couple of seconds doing writeback only to return EINVAL... So I'd maybe
restructure the code like:

	if (dio->flags & DIO_LOCKING && iov_iter_rw(iter) == READ)
		inode_lock(inode)
	dio->i_size = i_size_read(inode);
	... i_size checks ...
	... alignment checks ...
	if (dio->flags & DIO_LOCKING && iov_iter_rw(iter) == READ)
		... writeout ...

What do you think?
								Honza

> ---
>  fs/direct-io.c | 31 ++++++++++++++++++-------------
>  1 file changed, 18 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/direct-io.c b/fs/direct-io.c
> index 183299892465..77400b033d63 100644
> --- a/fs/direct-io.c
> +++ b/fs/direct-io.c
> @@ -1160,19 +1160,6 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
>  	struct blk_plug plug;
>  	unsigned long align = offset | iov_iter_alignment(iter);
>  
> -	/*
> -	 * Avoid references to bdev if not absolutely needed to give
> -	 * the early prefetch in the caller enough time.
> -	 */
> -
> -	if (align & blocksize_mask) {
> -		if (bdev)
> -			blkbits = blksize_bits(bdev_logical_block_size(bdev));
> -		blocksize_mask = (1 << blkbits) - 1;
> -		if (align & blocksize_mask)
> -			goto out;
> -	}
> -
>  	/* watch out for a 0 len io from a tricksy fs */
>  	if (iov_iter_rw(iter) == READ && !count)
>  		return 0;
> @@ -1217,6 +1204,24 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,
>  		goto out;
>  	}
>  
> +	/*
> +	 * Avoid references to bdev if not absolutely needed to give
> +	 * the early prefetch in the caller enough time.
> +	 */
> +
> +	if (align & blocksize_mask) {
> +		if (bdev)
> +			blkbits = blksize_bits(bdev_logical_block_size(bdev));
> +		blocksize_mask = (1 << blkbits) - 1;
> +		if (align & blocksize_mask) {
> +			if (iov_iter_rw(iter) == READ && dio->flags & DIO_LOCKING)
> +				inode_unlock(inode);
> +			kmem_cache_free(dio_cache, dio);
> +			retval = -EINVAL;
> +			goto out;
> +		}
> +	}
> +
>  	/*
>  	 * For file extending writes updating i_size before data writeouts
>  	 * complete can expose uninitialized blocks in dumb filesystems.
> -- 
> 2.28.0
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR

  reply	other threads:[~2020-08-26 14:29 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-08-19 20:07 [PATCH 0/2] Consolidate DIO behavior on unaligned EOF read Gabriel Krisman Bertazi
2020-08-19 20:07 ` [PATCH 1/2] direct-io: defer alignment check until after EOF check Gabriel Krisman Bertazi
2020-08-26 14:28   ` Jan Kara [this message]
2020-08-19 20:07 ` [PATCH 2/2] f2fs: Return EOF on unaligned end of file DIO read Gabriel Krisman Bertazi
2020-08-20 16:13   ` Jaegeuk Kim
2020-08-21  1:37   ` Chao Yu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200826142857.GA8760@quack2.suse.cz \
    --to=jack@suse.cz \
    --cc=chao@kernel.org \
    --cc=jaegeuk@kernel.org \
    --cc=jamieliu@google.com \
    --cc=kernel@collabora.com \
    --cc=krisman@collabora.com \
    --cc=linux-f2fs-devel@lists.sourceforge.net \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    --subject='Re: [PATCH 1/2] direct-io: defer alignment check until after EOF check' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).