Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp1115126imm; Wed, 1 Aug 2018 10:25:39 -0700 (PDT) X-Google-Smtp-Source: AAOMgpeJFAEz7vPNKMy7GQsmtdBfa2ILod4+bvulRp0VP6ZueeLyeTpr18oNQiXS5vWwZjyjoXSp X-Received: by 2002:a62:dc1d:: with SMTP id t29-v6mr28006280pfg.244.1533144339833; Wed, 01 Aug 2018 10:25:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533144339; cv=none; d=google.com; s=arc-20160816; b=AHmTrNrL6HY/rfZBgIYqQigs5h2dUgTMddeLPghLw42CNQ7xws3lBH+WfoCrvttYiA Zg87v9mDX9UOzrNEGR8jPMuDMI300c2U3tAoOScUXL0TuGU+WA/FCxl0i0WOziboJXW2 jYA/6qiM9saiJ6RkKJYnDs6w1+/YCy9SCYvCwO6pjZ4s+oY3ZT578WtL2HIcvarvnDko rAbswVtbIPQxob4pMZYKtfVtINh4Nak7vpvetfklyw15YRoON8VYzvbgWnyavf4yELEQ 42NnzcfdvI7EGDbeukJxFrLxHzFLQfkdwOV/uMZX2wsVf8txn7RmPqFKbZtbG+mqtNaS Eghw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=axa+oG8eaWjKl3ldlOzXtKL2TZLe3n8m3jlEJsSSzbo=; b=NPGLZ1BFb6nJaX/6caa4sf6ig493iRVRgU1rUx6iY8YUf+a2GtKhLmCKaGH070qkAz v3IrjZLxCO6lH9C5ebFYdQy7VywF8Wi2/wcmbFNeK6JDiNz9lpD3u6wigBrLZ1K9Qu02 i49ilWvnlXFT167bPGjyes8MT0TflfKN+Kgypt/SrbDW0NhU5VYCcNMgitvLGgMTPnGS VfVzuX1C1v1lqfPFCFmFgiG5aoHUp47GNVtfQVX2n5lcRJhGTWWmNd81oGv34EcZdjy2 eCrzw4/vclN7CmutEZdT1watfcqLU/Vr+9vuuHHcxdHSTKAY25fdwhlhjEGDADU8dhaH I3jw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 29-v6si16775737pgv.292.2018.08.01.10.25.25; Wed, 01 Aug 2018 10:25:39 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406315AbeHATJi (ORCPT + 99 others); Wed, 1 Aug 2018 15:09:38 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:50812 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390400AbeHATJh (ORCPT ); Wed, 1 Aug 2018 15:09:37 -0400 Received: from localhost (D57E6652.static.ziggozakelijk.nl [213.126.102.82]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 6B0E8D2F; Wed, 1 Aug 2018 17:22:55 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Theodore Tso Subject: [PATCH 4.14 220/246] ext4: fix inline data updates with checksums enabled Date: Wed, 1 Aug 2018 18:52:10 +0200 Message-Id: <20180801165022.238556471@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180801165011.700991984@linuxfoundation.org> References: <20180801165011.700991984@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Theodore Ts'o commit 362eca70b53389bddf3143fe20f53dcce2cfdf61 upstream. The inline data code was updating the raw inode directly; this is problematic since if metadata checksums are enabled, ext4_mark_inode_dirty() must be called to update the inode's checksum. In addition, the jbd2 layer requires that get_write_access() be called before the metadata buffer is modified. Fix both of these problems. https://bugzilla.kernel.org/show_bug.cgi?id=200443 Signed-off-by: Theodore Ts'o Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman --- fs/ext4/inline.c | 19 +++++++++++-------- fs/ext4/inode.c | 16 +++++++--------- 2 files changed, 18 insertions(+), 17 deletions(-) --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c @@ -688,6 +688,10 @@ int ext4_try_to_write_inline_data(struct goto convert; } + ret = ext4_journal_get_write_access(handle, iloc.bh); + if (ret) + goto out; + flags |= AOP_FLAG_NOFS; page = grab_cache_page_write_begin(mapping, 0, flags); @@ -716,7 +720,7 @@ int ext4_try_to_write_inline_data(struct out_up_read: up_read(&EXT4_I(inode)->xattr_sem); out: - if (handle) + if (handle && (ret != 1)) ext4_journal_stop(handle); brelse(iloc.bh); return ret; @@ -758,6 +762,7 @@ int ext4_write_inline_data_end(struct in ext4_write_unlock_xattr(inode, &no_expand); brelse(iloc.bh); + mark_inode_dirty(inode); out: return copied; } @@ -904,7 +909,6 @@ retry_journal: goto out; } - page = grab_cache_page_write_begin(mapping, 0, flags); if (!page) { ret = -ENOMEM; @@ -922,6 +926,9 @@ retry_journal: if (ret < 0) goto out_release_page; } + ret = ext4_journal_get_write_access(handle, iloc.bh); + if (ret) + goto out_release_page; up_read(&EXT4_I(inode)->xattr_sem); *pagep = page; @@ -942,7 +949,6 @@ int ext4_da_write_inline_data_end(struct unsigned len, unsigned copied, struct page *page) { - int i_size_changed = 0; int ret; ret = ext4_write_inline_data_end(inode, pos, len, copied, page); @@ -960,10 +966,8 @@ int ext4_da_write_inline_data_end(struct * But it's important to update i_size while still holding page lock: * page writeout could otherwise come in and zero beyond i_size. */ - if (pos+copied > inode->i_size) { + if (pos+copied > inode->i_size) i_size_write(inode, pos+copied); - i_size_changed = 1; - } unlock_page(page); put_page(page); @@ -973,8 +977,7 @@ int ext4_da_write_inline_data_end(struct * ordering of page lock and transaction start for journaling * filesystems. */ - if (i_size_changed) - mark_inode_dirty(inode); + mark_inode_dirty(inode); return copied; } --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1388,9 +1388,10 @@ static int ext4_write_end(struct file *f loff_t old_size = inode->i_size; int ret = 0, ret2; int i_size_changed = 0; + int inline_data = ext4_has_inline_data(inode); trace_ext4_write_end(inode, pos, len, copied); - if (ext4_has_inline_data(inode)) { + if (inline_data) { ret = ext4_write_inline_data_end(inode, pos, len, copied, page); if (ret < 0) { @@ -1418,7 +1419,7 @@ static int ext4_write_end(struct file *f * ordering of page lock and transaction start for journaling * filesystems. */ - if (i_size_changed) + if (i_size_changed || inline_data) ext4_mark_inode_dirty(handle, inode); if (pos + len > inode->i_size && ext4_can_truncate(inode)) @@ -1492,6 +1493,7 @@ static int ext4_journalled_write_end(str int partial = 0; unsigned from, to; int size_changed = 0; + int inline_data = ext4_has_inline_data(inode); trace_ext4_journalled_write_end(inode, pos, len, copied); from = pos & (PAGE_SIZE - 1); @@ -1499,7 +1501,7 @@ static int ext4_journalled_write_end(str BUG_ON(!ext4_handle_valid(handle)); - if (ext4_has_inline_data(inode)) { + if (inline_data) { ret = ext4_write_inline_data_end(inode, pos, len, copied, page); if (ret < 0) { @@ -1530,7 +1532,7 @@ static int ext4_journalled_write_end(str if (old_size < pos) pagecache_isize_extended(inode, old_size, pos); - if (size_changed) { + if (size_changed || inline_data) { ret2 = ext4_mark_inode_dirty(handle, inode); if (!ret) ret = ret2; @@ -2027,11 +2029,7 @@ static int __ext4_journalled_writepage(s } if (inline_data) { - BUFFER_TRACE(inode_bh, "get write access"); - ret = ext4_journal_get_write_access(handle, inode_bh); - - err = ext4_handle_dirty_metadata(handle, inode, inode_bh); - + ret = ext4_mark_inode_dirty(handle, inode); } else { ret = ext4_walk_page_buffers(handle, page_bufs, 0, len, NULL, do_journal_get_write_access);