Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp1005793yba; Thu, 4 Apr 2019 02:14:33 -0700 (PDT) X-Google-Smtp-Source: APXvYqyCAIMAkLOZ7IPk9KTa6M+kmwaiajR8BZ7UyLXbnDO98bQn8MW60hZWTE72a2Hns+4wEgiF X-Received: by 2002:a17:902:421:: with SMTP id 30mr5063417ple.142.1554369273418; Thu, 04 Apr 2019 02:14:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554369273; cv=none; d=google.com; s=arc-20160816; b=mCfKotVbMxojlUVDd+2nlwtf3udL9+vPK9JwVnUP7ESW1IqWMl6xde6QKiMbQAah/u zB6Bz9eczxUtE4IsSZKjBzj/tH3Bi1YecdV0LOzI8JRTuZYfvJcOOcMbwQRwnM6zEpIY M7VXqozapHwAjcEw5IH/NX6G7I+dxUDz5SZEC0uq9uy536fVw3Ue0TshG+/iymkMqKGC 2dzZOy4ys0G0LRNQT6EgiMG3u+07eXC9Usq3nrcGSAglGwsutPbkyR8cuG2q+ten4jfx aDXsC6u2Xn5qZb+0f7zAuuIe1G37A6ltvAxuwuE+AQcnvN/nCvCBUt7Pt1OTR8qEAPN3 EcaQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=c9E9NhphVM0bFun8It6kjNh2uE6Y2tQcRgZEVfXNtbQ=; b=Ef9gzsjqeLBKSbKUh5tKMQZ8Rvx9vgSDcMM2L3QxZ4C35MXhSws/numBKhJNuDgy+S QI8enFd8e2a53/LJYPfo6RbrBZJ4pBZvz0X9wlY0P0oL+urFwWHikNQ7G5nhwuXadm+1 9Fomg0PJWx6wC6PD7hi9ae2ird5hH2R68URs31Qjdzba/wadBaJyz8q3SHYeM9vchIme EiiymHyFQVuwW+JuQ9agZZNjZRJ2HslBe5wJKaymeW579OWn8pBs0ucYGFT329GiyPIl VLmPCccbj7Y8YyShU9KkMf1g1qMygsFtJ71NHg01f3FuI+3QvyqXGxw9Y/45ls8u3WWW PQGA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=SahIUcU7; 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 y2si5665947pgq.170.2019.04.04.02.14.18; Thu, 04 Apr 2019 02:14:33 -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; dkim=pass header.i=@kernel.org header.s=default header.b=SahIUcU7; 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 S2387403AbfDDJNp (ORCPT + 99 others); Thu, 4 Apr 2019 05:13:45 -0400 Received: from mail.kernel.org ([198.145.29.99]:54080 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387580AbfDDJNm (ORCPT ); Thu, 4 Apr 2019 05:13:42 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id CFBA520693; Thu, 4 Apr 2019 09:13:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1554369221; bh=vhMfuiXPE7LO67tSsLVrWOAcOBf7nfYtFSozhSe986M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=SahIUcU7kYHuzxyQC+mfNwivmJhKmPExiScYnpRC+pUdUpuwbmek2QF3+t6fMTTuv wQzSaoMbiITpJpmHYG73pU3WN4yrK2ZLnmU3s08ZyJMPPH85Z/BtMf6Dy8DG7bQ2Xh VK9S0Nb1U7tjy6SHbkA2oF2esmwtTFmZOkW3J4W0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, "zhangyi (F)" , Jan Kara , Theodore Tso , Sasha Levin Subject: [PATCH 5.0 129/246] jbd2: fix race when writing superblock Date: Thu, 4 Apr 2019 10:47:09 +0200 Message-Id: <20190404084623.674471160@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190404084619.236418459@linuxfoundation.org> References: <20190404084619.236418459@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 5.0-stable review patch. If anyone has any objections, please let me know. ------------------ [ Upstream commit 538bcaa6261b77e71d37f5596c33127c1a3ec3f7 ] The jbd2 superblock is lockless now, so there is probably a race condition between writing it so disk and modifing contents of it, which may lead to checksum error. The following race is the one case that we have captured. jbd2 fsstress jbd2_journal_commit_transaction jbd2_journal_update_sb_log_tail jbd2_write_superblock jbd2_superblock_csum_set jbd2_journal_revoke jbd2_journal_set_features(revork) modify superblock submit_bh(checksum incorrect) Fix this by locking the buffer head before modifing it. We always write the jbd2 superblock after we modify it, so this just means calling the lock_buffer() a little earlier. This checksum corruption problem can be reproduced by xfstests generic/475. Reported-by: zhangyi (F) Suggested-by: Jan Kara Signed-off-by: Theodore Ts'o Signed-off-by: Sasha Levin --- fs/jbd2/journal.c | 52 ++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 8ef6b6daaa7a..88f2a49338a1 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1356,6 +1356,10 @@ static int journal_reset(journal_t *journal) return jbd2_journal_start_thread(journal); } +/* + * This function expects that the caller will have locked the journal + * buffer head, and will return with it unlocked + */ static int jbd2_write_superblock(journal_t *journal, int write_flags) { struct buffer_head *bh = journal->j_sb_buffer; @@ -1365,7 +1369,6 @@ static int jbd2_write_superblock(journal_t *journal, int write_flags) trace_jbd2_write_superblock(journal, write_flags); if (!(journal->j_flags & JBD2_BARRIER)) write_flags &= ~(REQ_FUA | REQ_PREFLUSH); - lock_buffer(bh); if (buffer_write_io_error(bh)) { /* * Oh, dear. A previous attempt to write the journal @@ -1424,6 +1427,7 @@ int jbd2_journal_update_sb_log_tail(journal_t *journal, tid_t tail_tid, jbd_debug(1, "JBD2: updating superblock (start %lu, seq %u)\n", tail_block, tail_tid); + lock_buffer(journal->j_sb_buffer); sb->s_sequence = cpu_to_be32(tail_tid); sb->s_start = cpu_to_be32(tail_block); @@ -1454,18 +1458,17 @@ static void jbd2_mark_journal_empty(journal_t *journal, int write_op) journal_superblock_t *sb = journal->j_superblock; BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); - read_lock(&journal->j_state_lock); - /* Is it already empty? */ - if (sb->s_start == 0) { - read_unlock(&journal->j_state_lock); + lock_buffer(journal->j_sb_buffer); + if (sb->s_start == 0) { /* Is it already empty? */ + unlock_buffer(journal->j_sb_buffer); return; } + jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n", journal->j_tail_sequence); sb->s_sequence = cpu_to_be32(journal->j_tail_sequence); sb->s_start = cpu_to_be32(0); - read_unlock(&journal->j_state_lock); jbd2_write_superblock(journal, write_op); @@ -1488,9 +1491,8 @@ void jbd2_journal_update_sb_errno(journal_t *journal) journal_superblock_t *sb = journal->j_superblock; int errcode; - read_lock(&journal->j_state_lock); + lock_buffer(journal->j_sb_buffer); errcode = journal->j_errno; - read_unlock(&journal->j_state_lock); if (errcode == -ESHUTDOWN) errcode = 0; jbd_debug(1, "JBD2: updating superblock error (errno %d)\n", errcode); @@ -1894,28 +1896,27 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, sb = journal->j_superblock; + /* Load the checksum driver if necessary */ + if ((journal->j_chksum_driver == NULL) && + INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) { + journal->j_chksum_driver = crypto_alloc_shash("crc32c", 0, 0); + if (IS_ERR(journal->j_chksum_driver)) { + printk(KERN_ERR "JBD2: Cannot load crc32c driver.\n"); + journal->j_chksum_driver = NULL; + return 0; + } + /* Precompute checksum seed for all metadata */ + journal->j_csum_seed = jbd2_chksum(journal, ~0, sb->s_uuid, + sizeof(sb->s_uuid)); + } + + lock_buffer(journal->j_sb_buffer); + /* If enabling v3 checksums, update superblock */ if (INCOMPAT_FEATURE_ON(JBD2_FEATURE_INCOMPAT_CSUM_V3)) { sb->s_checksum_type = JBD2_CRC32C_CHKSUM; sb->s_feature_compat &= ~cpu_to_be32(JBD2_FEATURE_COMPAT_CHECKSUM); - - /* Load the checksum driver */ - if (journal->j_chksum_driver == NULL) { - journal->j_chksum_driver = crypto_alloc_shash("crc32c", - 0, 0); - if (IS_ERR(journal->j_chksum_driver)) { - printk(KERN_ERR "JBD2: Cannot load crc32c " - "driver.\n"); - journal->j_chksum_driver = NULL; - return 0; - } - - /* Precompute checksum seed for all metadata */ - journal->j_csum_seed = jbd2_chksum(journal, ~0, - sb->s_uuid, - sizeof(sb->s_uuid)); - } } /* If enabling v1 checksums, downgrade superblock */ @@ -1927,6 +1928,7 @@ int jbd2_journal_set_features (journal_t *journal, unsigned long compat, sb->s_feature_compat |= cpu_to_be32(compat); sb->s_feature_ro_compat |= cpu_to_be32(ro); sb->s_feature_incompat |= cpu_to_be32(incompat); + unlock_buffer(journal->j_sb_buffer); return 1; #undef COMPAT_FEATURE_ON -- 2.19.1