Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3334443imu; Sun, 11 Nov 2018 12:36:43 -0800 (PST) X-Google-Smtp-Source: AJdET5dqMgWOEJE1zcFawuJj3+7DyD8lMhX6UZWSjirw8TtfiltzNg0dqc1R7mN5b4ANOupbZ/WS X-Received: by 2002:a63:ae01:: with SMTP id q1mr14874155pgf.402.1541968603335; Sun, 11 Nov 2018 12:36:43 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1541968603; cv=none; d=google.com; s=arc-20160816; b=jFOgkY7d8/mX9MDhXV0KKXlKEaH8u6zjq6M4GWqV22lZUu7QdpYfuaAelImwndLXg5 ABh8oJje/ub8YgJaBXxMh8R8GET02+BMBLgW7tn4Jpkvdvo04KXKC7gxRMyTrmBVTs8n gM1KnbJ6q8GJXbY8tCm4OKrBfZZqlC636WcWK6htXbT+zW2aEw8u0yHps3pyiuiosp+2 dll1ApQrpcgFBzpznLnWgjQgbjYwl4QBt3qCb0SGeOJfgh36yTeYfIIcuxDAIQS+XBRP aTBTkUlbPTEQBt0RhbMIy9SDYc/vW/U58IhmU7kRMjVlO+rj4f1h6jHesYmnXn2CZswk cKKg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:in-reply-to:subject:message-id:date:cc:to :from:mime-version:content-transfer-encoding:content-disposition; bh=Ue/+trHRipMKAz5F7pC2CgMfn2rB937SYcPi8LoZCyg=; b=XMZ+zXHAXdb8TyJPspP7vQu1DnWmMd/KdB2HDZL2siV2GZTHjhqJtPS9tXtCerKTXC i+Ac5RPsBlMzzf1xgBWvNpPFF0I+4yUK5BZ7mivNEDXPYl2/x+JMz/5BdQ1UsDaRJNuY 5/JLTaepIK0eokdbXj2sb+vr9OhQlrG8vrgOsM72/jN36GnoreyQqlLAHz6kjlc0ftvD rfgYTmAQo41RZAYqQEBseJ+MHpdB0K7nRO0u6qslWjRj63tRwcbZczfSQ9KPlL9R6jlK 0Bb6wEE5mNX9EElrXMVu3B4q7jNG/uYfKbT0aDYQ4teZ8SDShOsSSZKYcO1b3AJB6f6r z2Jg== 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 k8-v6si14172103pgj.192.2018.11.11.12.36.28; Sun, 11 Nov 2018 12:36:43 -0800 (PST) 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 S1730841AbeKLGYW (ORCPT + 99 others); Mon, 12 Nov 2018 01:24:22 -0500 Received: from shadbolt.e.decadent.org.uk ([88.96.1.126]:49922 "EHLO shadbolt.e.decadent.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730200AbeKLFsN (ORCPT ); Mon, 12 Nov 2018 00:48:13 -0500 Received: from [192.168.4.242] (helo=deadeye) by shadbolt.decadent.org.uk with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1gLvsZ-0000lK-7w; Sun, 11 Nov 2018 19:58:43 +0000 Received: from ben by deadeye with local (Exim 4.91) (envelope-from ) id 1gLvsW-0001iU-5J; Sun, 11 Nov 2018 19:58:40 +0000 Content-Type: text/plain; charset="UTF-8" Content-Disposition: inline Content-Transfer-Encoding: 8bit MIME-Version: 1.0 From: Ben Hutchings To: linux-kernel@vger.kernel.org, stable@vger.kernel.org CC: akpm@linux-foundation.org, "Theodore Ts'o" Date: Sun, 11 Nov 2018 19:49:05 +0000 Message-ID: X-Mailer: LinuxStableQueue (scripts by bwh) Subject: [PATCH 3.16 244/366] ext4: fix inline data updates with checksums enabled In-Reply-To: X-SA-Exim-Connect-IP: 192.168.4.242 X-SA-Exim-Mail-From: ben@decadent.org.uk X-SA-Exim-Scanned: No (on shadbolt.decadent.org.uk); SAEximRunCond expanded to false Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 3.16.61-rc1 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 Signed-off-by: Ben Hutchings --- 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 @@ -681,6 +681,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); @@ -709,7 +713,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; @@ -751,6 +755,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; } @@ -911,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; @@ -931,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); @@ -949,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); @@ -962,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 @@ -1113,9 +1113,10 @@ static int ext4_write_end(struct file *f struct inode *inode = mapping->host; 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) { @@ -1141,7 +1142,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)) @@ -1214,6 +1215,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); @@ -1221,7 +1223,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) { @@ -1249,7 +1251,7 @@ static int ext4_journalled_write_end(str unlock_page(page); page_cache_release(page); - if (size_changed) { + if (size_changed || inline_data) { ret2 = ext4_mark_inode_dirty(handle, inode); if (!ret) ret = ret2; @@ -1856,11 +1858,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);