Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp1381029imm; Sat, 4 Aug 2018 02:13:20 -0700 (PDT) X-Google-Smtp-Source: AAOMgpfYD89oYXcSxyFf1NdTddEYVaqcAujMkJqD7w0y8zvguZD433pigaibGSstn2/PIxp+BHEo X-Received: by 2002:a63:fb57:: with SMTP id w23-v6mr6985305pgj.441.1533374000208; Sat, 04 Aug 2018 02:13:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533374000; cv=none; d=google.com; s=arc-20160816; b=TdOMpARRoETWgGgyr4mOeOu13mkeE1+vV9D0cTjt4Kf1kmij5sYW6ITJDBXjxqjsYt FWeMVU8AvYd2X5Nhz5Fieh3mSl0UjXi3EtwwzpDy+6xsoZWfBYvlLRstrIgrvle2fmy/ wiWY8CJhAwkUD7dbpSEFsdKTizn7M0llQLSPWGCzrrlaHgUPD3Ry6fmnCr98O5o2zVGz 0jYVgUwt39HuTCtbHJ+sDAUqlmy0v6MeVwi7an7eN//XCq3DtNcuV8Hz0BX+SCg0rQIP CDnoqh1vDf6pOd5CA51N0qLaLlclL/TD7M6LMeqzFC3tqsRhFpRVcpsyMUO7lIg4Bz6+ BsvQ== 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=HHqMl9hBbzLXjPIzZNKfv/bhFRI55iJBUkSWywQLqbc=; b=Nsyju7MvmgDTqo8CkIq1KLyQlJCs5z/L3W0gtrnrwjQQxS/rnaYBPtwX2fOglnCqzd pBQM4jMqLgfuIm8r0Jn6xUcB15r0ECJGiawtZf+ajkVK313Kf238gZkKzp4VYcUN8ohk bWeumzwfc+3qBGfmsNsdAka5xeTOQ1NiWO2SUNKjkFOfR1Zfmc0XDo+bb90TaAXEIcpN pEYHVdfoBtIXpf/+1sez3LWNpQUQoMiE2ZVy3TlS9Qc64qaS9I9PYygqEEX1YK+3EN6d Ojp0bk6v8KJPx1EcGRM2eGvyLo08sl3clsVG3D4c4LnS9hlsjWCUEcOtZeRX1pd/ZOU6 hWEg== 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 g6-v6si5800457pgq.240.2018.08.04.02.13.05; Sat, 04 Aug 2018 02:13:20 -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 S2389166AbeHDLLY (ORCPT + 99 others); Sat, 4 Aug 2018 07:11:24 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:50226 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732670AbeHDLLX (ORCPT ); Sat, 4 Aug 2018 07:11:23 -0400 Received: from localhost (D57E6652.static.ziggozakelijk.nl [213.126.102.82]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id B6D7BBC6; Sat, 4 Aug 2018 09:11:22 +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.4 098/124] ext4: fix inline data updates with checksums enabled Date: Sat, 4 Aug 2018 11:01:27 +0200 Message-Id: <20180804082706.142180092@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180804082702.434482435@linuxfoundation.org> References: <20180804082702.434482435@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.4-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 @@ -678,6 +678,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); @@ -706,7 +710,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; @@ -748,6 +752,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; } @@ -894,7 +899,6 @@ retry_journal: goto out; } - page = grab_cache_page_write_begin(mapping, 0, flags); if (!page) { ret = -ENOMEM; @@ -912,6 +916,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; @@ -932,7 +939,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); @@ -950,10 +956,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); page_cache_release(page); @@ -963,8 +967,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 @@ -1164,9 +1164,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) { @@ -1194,7 +1195,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)) @@ -1268,6 +1269,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_CACHE_SIZE - 1); @@ -1275,7 +1277,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) { @@ -1306,7 +1308,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; @@ -1804,11 +1806,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);