Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp2556161pxj; Mon, 10 May 2021 05:52:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyzNJK3JqzMFhYzvzr1Vd5+S8xjcl+8atbi/kowmUNt+/YwnsLD4tqM6AhbdVzUAMD7mhJO X-Received: by 2002:a17:906:1794:: with SMTP id t20mr25712028eje.119.1620651124417; Mon, 10 May 2021 05:52:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620651124; cv=none; d=google.com; s=arc-20160816; b=0VxAVByLXrR0yRF2EulxNjFRNvNDYDGgHgQF82KsiNBPFvIZ+k1T4QKuYI5Xlc5HIu lbEnrN79EOiQXDk8yBwiHtFRDqqJF+JiRcJHoi3WypY0O8IMB195vllDKGZDF5Ga07Rb sSHaAnaxWx5o0CYHQjyke/E20d+GYKFgvM3lqo3lLBR8/JlactfKYyR3jpEz5a49zkj8 NbVDHiggZebOCxrABDSBPX8HbRC9d0qL5ikkImyTc1P1Ss4Bu/3GwrRcAWv1d9hNuwbb eGae3upGoEtnPbdjtjkBZ6fRlhJGs3QghRiXcOH55nD5dnr86v6F3YGwBD6UHkXYzet0 NU4A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=4HrEA2lK7XxdoEPybTYzX5mrHjW26D29OTJsEPWstIc=; b=wd4O3qM3Ag8rPhWNKlfWMYmduEP0gw9kl4zwUGJi6t+gR1GVsNFk04/StvH9GoC1Ii cnCzHK+XIDmPTEmlyNLGvAqgdCHVDKjhvKCHKZEJUutjkzZbqG5ImqPMa7LWbkkQFgw4 NL1DK1jOaSEXLOI9yUUzHvQR2eK9YbYsrLkDiAwWaiZtny+3LQwIDXRvySg53aBEvI+d UHIXg18TfMBd8JkVdV6HR4pDyHZf6KDaM7bjawZsY9tOosy9OBZtTzrRqEhpyoAyOJfr oao7dQoFl6X0Hant3t5cqKAtcXj9o8uCfKWyPTj40UC2QDWphWY1+jFJfZYKr+mYDJ1z zqWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=xy6xSYBt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id y11si12294439edv.309.2021.05.10.05.51.40; Mon, 10 May 2021 05:52:04 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=xy6xSYBt; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346615AbhEJMpX (ORCPT + 99 others); Mon, 10 May 2021 08:45:23 -0400 Received: from mail.kernel.org ([198.145.29.99]:34880 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238192AbhEJLRN (ORCPT ); Mon, 10 May 2021 07:17:13 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 320C6617C9; Mon, 10 May 2021 11:12:47 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1620645167; bh=6/u0QOMQDWtozjw/I88axVNFLSUoHDVCC2plP3hy8OY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=xy6xSYBt4Hcp9GNfd+oaKDbtvmR47kHCdqvxfvHEyxWAiHyL0WClvXzdvrmZXnW6p MT75Rs3+obypcFCkSCRVl4nJLN2aGIphlgbqP/GT0pwt5KJoAdqjA90iWtbl4loowC NoQdNRCBJiyufODraPL9CfuQ4j5UB2BrvN667RY4= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jan Kara , Dave Chinner , Theodore Tso , Eric Whitney Subject: [PATCH 5.12 345/384] ext4: Fix occasional generic/418 failure Date: Mon, 10 May 2021 12:22:14 +0200 Message-Id: <20210510102026.143638843@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210510102014.849075526@linuxfoundation.org> References: <20210510102014.849075526@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jan Kara commit 5899593f51e63dde2f07c67358bd65a641585abb upstream. Eric has noticed that after pagecache read rework, generic/418 is occasionally failing for ext4 when blocksize < pagesize. In fact, the pagecache rework just made hard to hit race in ext4 more likely. The problem is that since ext4 conversion of direct IO writes to iomap framework (commit 378f32bab371), we update inode size after direct IO write only after invalidating page cache. Thus if buffered read sneaks at unfortunate moment like: CPU1 - write at offset 1k CPU2 - read from offset 0 iomap_dio_rw(..., IOMAP_DIO_FORCE_WAIT); ext4_readpage(); ext4_handle_inode_extension() the read will zero out tail of the page as it still sees smaller inode size and thus page cache becomes inconsistent with on-disk contents with all the consequences. Fix the problem by moving inode size update into end_io handler which gets called before the page cache is invalidated. Reported-and-tested-by: Eric Whitney Fixes: 378f32bab371 ("ext4: introduce direct I/O write using iomap infrastructure") CC: stable@vger.kernel.org Signed-off-by: Jan Kara Acked-by: Dave Chinner Link: https://lore.kernel.org/r/20210415155417.4734-1-jack@suse.cz Signed-off-by: Theodore Ts'o Signed-off-by: Greg Kroah-Hartman --- fs/ext4/file.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -371,15 +371,32 @@ truncate: static int ext4_dio_write_end_io(struct kiocb *iocb, ssize_t size, int error, unsigned int flags) { - loff_t offset = iocb->ki_pos; + loff_t pos = iocb->ki_pos; struct inode *inode = file_inode(iocb->ki_filp); if (error) return error; - if (size && flags & IOMAP_DIO_UNWRITTEN) - return ext4_convert_unwritten_extents(NULL, inode, - offset, size); + if (size && flags & IOMAP_DIO_UNWRITTEN) { + error = ext4_convert_unwritten_extents(NULL, inode, pos, size); + if (error < 0) + return error; + } + /* + * If we are extending the file, we have to update i_size here before + * page cache gets invalidated in iomap_dio_rw(). Otherwise racing + * buffered reads could zero out too much from page cache pages. Update + * of on-disk size will happen later in ext4_dio_write_iter() where + * we have enough information to also perform orphan list handling etc. + * Note that we perform all extending writes synchronously under + * i_rwsem held exclusively so i_size update is safe here in that case. + * If the write was not extending, we cannot see pos > i_size here + * because operations reducing i_size like truncate wait for all + * outstanding DIO before updating i_size. + */ + pos += size; + if (pos > i_size_read(inode)) + i_size_write(inode, pos); return 0; }