Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp3565283pxb; Mon, 1 Mar 2021 13:31:56 -0800 (PST) X-Google-Smtp-Source: ABdhPJxXKRNgGClZKgtMa8x2nbPADKgB84pZEH5ytAfrczU/7bbJxjVXBcuzdr+wcIMAMreZSLlg X-Received: by 2002:a17:907:ea3:: with SMTP id ho35mr17439067ejc.396.1614634316046; Mon, 01 Mar 2021 13:31:56 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1614634316; cv=none; d=google.com; s=arc-20160816; b=COUVN5Y/ub4fuG3fTqAGLlDSYiUTwSjIWK++W5XcM8yPqnP3bAr4bPdPICfBUVQ1VB 2Mxw/zU6vN6gZoPgdzNYRFWm+b6b/7sSsBayp6jjuYItDiW/PVJa8hlVtRtfxyfcsLRS itpnC7I0v7Qq94qAivaHEVwM+Scgb+zqJObszP2fnlwphE19Qd6RMyh/9PnOq3ck0C+s 3+i6EMHl5xPFlCnITccS6bdDCPpNVrCB26AfH9i1L7Nnja24tXlZjE8c0rmwh8zHCb8P ie4I2TBppGCc7QbsAlPPWVrebp/UVqbIxYQuN+RwkkBXn48F6Dir/LaKWTOOUzTM0Vjq 4uWQ== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=BWDxMSKXRmAyXGkpJv6IqxX+k7hXtRQ3YKbqBajVQTg=; b=Pf6sdm+SudsqXvmib80s1Jlvk0nhU2ijd+r44qxJ3CpFa3PCMF0COUAtAja8fCA16I rq3z+19HIzKMwKRf+L90fGpWXC6YAkrgjl72j2kVr1fOd6suwvirtjlSuI/ypamnqBh+ e8enUC3wTVbqQustmzq8gzo4EX36JlnSzgrdsf8v6Of7R7d8oak6cjB/c5MBgbh8gOpo SjcS5tJR1Kj/bJHdvr4xjKYrUhkeIRiBT3A9Nvx6H47WAvbZQ6TLzVkywT6+DlBEaqX5 bdjSUuWHzV+ZC6R7WlHuflfFKynV0nVcK0qgJoumfFL9D5Qi+VmEfNyeSEqSu25rp5Ul n36g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=YfcskZdb; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id s3si4979792edx.251.2021.03.01.13.31.33; Mon, 01 Mar 2021 13:31:56 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=YfcskZdb; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244269AbhCAV1M (ORCPT + 99 others); Mon, 1 Mar 2021 16:27:12 -0500 Received: from mail.kernel.org ([198.145.29.99]:57226 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237937AbhCARSU (ORCPT ); Mon, 1 Mar 2021 12:18:20 -0500 Received: by mail.kernel.org (Postfix) with ESMTPSA id 171A264DD2; Mon, 1 Mar 2021 16:47:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1614617225; bh=KjTGdvrTao/Hutl7akMMLjpuDKEy9Lb06Sp7O4eFGCI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=YfcskZdbKxNVGVHFEPQhdbPhQL6lDOg7nD8jyjzlI2+KJJ1en/aOBc78ZCt+kP+Ja Ad3IzGz2SSmIP3rTzc8TcU3zjm3L29ZRCBxP9CuK7zssgcjzfTPPF3VRJtpxT3KNCN nO2NviFZQ72thnB5dnGL4QSAD/Mshngzy77q/XEE= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Nikos Tsironis , Mike Snitzer Subject: [PATCH 4.19 246/247] dm era: Update in-core bitset after committing the metadata Date: Mon, 1 Mar 2021 17:14:26 +0100 Message-Id: <20210301161043.744201189@linuxfoundation.org> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210301161031.684018251@linuxfoundation.org> References: <20210301161031.684018251@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Nikos Tsironis commit 2099b145d77c1d53f5711f029c37cc537897cee6 upstream. In case of a system crash, dm-era might fail to mark blocks as written in its metadata, although the corresponding writes to these blocks were passed down to the origin device and completed successfully. Consider the following sequence of events: 1. We write to a block that has not been yet written in the current era 2. era_map() checks the in-core bitmap for the current era and sees that the block is not marked as written. 3. The write is deferred for submission after the metadata have been updated and committed. 4. The worker thread processes the deferred write (process_deferred_bios()) and marks the block as written in the in-core bitmap, **before** committing the metadata. 5. The worker thread starts committing the metadata. 6. We do more writes that map to the same block as the write of step (1) 7. era_map() checks the in-core bitmap and sees that the block is marked as written, **although the metadata have not been committed yet**. 8. These writes are passed down to the origin device immediately and the device reports them as completed. 9. The system crashes, e.g., power failure, before the commit from step (5) finishes. When the system recovers and we query the dm-era target for the list of written blocks it doesn't report the aforementioned block as written, although the writes of step (6) completed successfully. The issue is that era_map() decides whether to defer or not a write based on non committed information. The root cause of the bug is that we update the in-core bitmap, **before** committing the metadata. Fix this by updating the in-core bitmap **after** successfully committing the metadata. Fixes: eec40579d84873 ("dm: add era target") Cc: stable@vger.kernel.org # v3.15+ Signed-off-by: Nikos Tsironis Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-era-target.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) --- a/drivers/md/dm-era-target.c +++ b/drivers/md/dm-era-target.c @@ -134,7 +134,7 @@ static int writeset_test_and_set(struct { int r; - if (!test_and_set_bit(block, ws->bits)) { + if (!test_bit(block, ws->bits)) { r = dm_bitset_set_bit(info, ws->md.root, block, &ws->md.root); if (r) { /* FIXME: fail mode */ @@ -1240,8 +1240,10 @@ static void process_deferred_bios(struct int r; struct bio_list deferred_bios, marked_bios; struct bio *bio; + struct blk_plug plug; bool commit_needed = false; bool failed = false; + struct writeset *ws = era->md->current_writeset; bio_list_init(&deferred_bios); bio_list_init(&marked_bios); @@ -1251,9 +1253,11 @@ static void process_deferred_bios(struct bio_list_init(&era->deferred_bios); spin_unlock(&era->deferred_lock); + if (bio_list_empty(&deferred_bios)) + return; + while ((bio = bio_list_pop(&deferred_bios))) { - r = writeset_test_and_set(&era->md->bitset_info, - era->md->current_writeset, + r = writeset_test_and_set(&era->md->bitset_info, ws, get_block(era, bio)); if (r < 0) { /* @@ -1261,7 +1265,6 @@ static void process_deferred_bios(struct * FIXME: finish. */ failed = true; - } else if (r == 0) commit_needed = true; @@ -1277,9 +1280,19 @@ static void process_deferred_bios(struct if (failed) while ((bio = bio_list_pop(&marked_bios))) bio_io_error(bio); - else - while ((bio = bio_list_pop(&marked_bios))) + else { + blk_start_plug(&plug); + while ((bio = bio_list_pop(&marked_bios))) { + /* + * Only update the in-core writeset if the on-disk one + * was updated too. + */ + if (commit_needed) + set_bit(get_block(era, bio), ws->bits); generic_make_request(bio); + } + blk_finish_plug(&plug); + } } static void process_rpc_calls(struct era *era)