Received: by 2002:a05:6a10:17d3:0:0:0:0 with SMTP id hz19csp38767pxb; Wed, 14 Apr 2021 08:56:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyuAWUWZArm7mO+KOnOmn1RqEDmA9zaq6wtJqh5SQRe4iR9m3Skjl8YX7yG9QDhA5A/0zW8 X-Received: by 2002:a05:6402:3550:: with SMTP id f16mr41502959edd.134.1618415796673; Wed, 14 Apr 2021 08:56:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1618415796; cv=none; d=google.com; s=arc-20160816; b=n6EU/X16XGI6eOCCR1NAxPLCu9JKE1icX+E5pZyWIA003XMaQR6SXMM0gEIMgyznca XeXQdXGVLcZn42v2mXyJSwYdbLW+N+h3B1SgIN+2TEyRJK/1mZO8OxchOAYkPQ/rSV2w JQ5QOICjOIkJMyTXvKGAeGKF9Eno8iR1q3KxjkymhKHTsP88+bTi+7F/kAozfZRFWbEr eXAe0hUVKH2UFFOOzuuPYWzsIE6xosjGFcJIVz6Dk6weCW0uERPgNJNrNExV0QK3z6jG L8dIzj2H+Mip7PRQhQlSGbYSpRD4+iscJuyNWpdFf1m2jehzr37OAy5hQBMYLWyPCuZN 1RJA== 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 :message-id:date:subject:cc:to:from; bh=EOLu1iqD8/0V/yolRh+4zt02Yfp3dlHIFO5JCkA02vM=; b=lBgdaRbfpmyAHz87AffTSOoksckWLPAz4c0tJl5dS4iexRgV70n8HQFgRym/M8SYII TuvGgT4iXzuMeZ42u+PmYZaNfLBQTmeUh7BfrT3iVObAWk3rYXqSQSIIUKZqO0p/jWDR XEF8qju6XqDa6HDW3sbffP6wy9YZTQOONNPSJjBBUfpJ6eh9V+NIH9DgJrphwWW1rS5+ td7xJu6CYbq9Rb+Pwc6mZFZc8wWVO5mNBZsArzA8rF0eIQGTsdznbxIundkIikmNN5En z8aQNDTZRf+doSnxpxkk88Z4rGLv73U7N8WTjBJZDY7o1aPnxLl3BnezLLWh0PkJRQNa rSwA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id r6si4309415ejr.189.2021.04.14.08.56.03; Wed, 14 Apr 2021 08:56:36 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-ext4-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-ext4-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1347105AbhDNNPj (ORCPT + 99 others); Wed, 14 Apr 2021 09:15:39 -0400 Received: from mx2.suse.de ([195.135.220.15]:32792 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243246AbhDNNPa (ORCPT ); Wed, 14 Apr 2021 09:15:30 -0400 X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id B4ABEAE03; Wed, 14 Apr 2021 13:15:08 +0000 (UTC) Received: by quack2.suse.cz (Postfix, from userid 1000) id 7EB281F2B5F; Wed, 14 Apr 2021 15:15:08 +0200 (CEST) From: Jan Kara To: Ted Tso Cc: , Eric Whitney , Jan Kara , stable@vger.kernel.org Subject: [PATCH v2] ext4: Fix occasional generic/418 failure Date: Wed, 14 Apr 2021 15:14:53 +0200 Message-Id: <20210414131453.4945-1-jack@suse.cz> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-ext4@vger.kernel.org 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-by: Eric Whitney Fixes: 378f32bab371 ("ext4: introduce direct I/O write using iomap infrastructure") CC: stable@vger.kernel.org Signed-off-by: Jan Kara --- fs/ext4/file.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) Eric, can you please try whether this patch fixes the failures you are occasionally seeing? Changes since v1: * Rewritten the fix to avoid the need for separate transaction handle for orphan list update diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 194f5d00fa32..be1e80af61be 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -371,15 +371,27 @@ static ssize_t ext4_handle_inode_extension(struct inode *inode, loff_t offset, 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. + */ + pos += size; + if (pos > i_size_read(inode)) + i_size_write(inode, pos); return 0; } -- 2.26.2