Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp2457208imj; Mon, 18 Feb 2019 06:22:52 -0800 (PST) X-Google-Smtp-Source: AHgI3IZlKoqK2Wu6b7iMYK/5Q1Fxr1d4V8Q538JFWlNSgjYFM5CXePkJQU5PMIuOeI2UtldF5wBE X-Received: by 2002:a17:902:298a:: with SMTP id h10mr25759732plb.312.1550499772462; Mon, 18 Feb 2019 06:22:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1550499772; cv=none; d=google.com; s=arc-20160816; b=x3bKmh6ZBhfM30XeyQA1MN9jr9w9yu7sOjSzdHHV2rs+vFmwhQFPIDjrors/tCQmtL j6Mq4pSwGJuhZE8TcYG1/jhvNoKq41H9d8jTpZch/NnhvhVGYc4mD/YkTQvgA7X9teAk DiegbvR4Eufi0zdtgjOB174quRB6YHJfSA5lZvvjfHf9RacQZoe4v5FOi7RZKr5U/d7x VaXZpcK6qf68sK6exjcaWUNOHwk8BsUzePJw2pJHvFDSXjFABW/asK2Bb3D7onZzzP9y whrb9KYxSSGzlWJOgMZf/jwuwRhmm5B4xP6yl5GobQ4+4k1nJWiotu8ZZfJLnbvo25xC n3zQ== 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=XAW+n6YHw5aZWIYQ1mKduU0iAd22INOZ65/4zvI/HTQ=; b=lGaFfv4XOs6fluFrZSX+q/Sz1C0J6rCmm4CGzSbrrZf2rfy6r3hIz8gcqnrkZHWW0Z 5JsH/CQR7VDjPLAGirQZHWuDOGW1oCD6jX5v5DjLu/V+gCHdL6/P3l0CYM3JVvzfrTAw coGQOx/LnFxlL/9bzDHxgQqs0CBx271nNuAN+R6AeB3yvE0rC3Ul5XVa+SBSthlxZcUx wWcy1FkfSSmcimU7PRtCbFGJEkpcxY60R/n+UcgeYnXc9+cBVihrVlXqRxdYRnmLYe+O b9veH7Rn+A7+ssZIpA4iYOCCRHwiDSHSOz4D+8JcONB5yGMaveTOPv4e31S1nYhcdUyf jDEQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=WoNL9+ku; 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 p12si11239835plk.77.2019.02.18.06.22.36; Mon, 18 Feb 2019 06:22:52 -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; dkim=pass header.i=@kernel.org header.s=default header.b=WoNL9+ku; 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 S2390563AbfBROHV (ORCPT + 99 others); Mon, 18 Feb 2019 09:07:21 -0500 Received: from mail.kernel.org ([198.145.29.99]:50446 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2390081AbfBROHU (ORCPT ); Mon, 18 Feb 2019 09:07:20 -0500 Received: from localhost (5356596B.cm-6-7b.dynamic.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 9E57721902; Mon, 18 Feb 2019 14:07:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1550498839; bh=l+m4a8ddwfslpPgU6B/qnhMAG0w0BsjXSRUy3zTV1cM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WoNL9+kusor8iE4DL3VOc4nGGTd68Ar51B2b4O+wjmSf/T0xKz6ylVDwxtyCrUvIF rvALxDz33TwoDr31x/od4a4SGbJBXExdTABMM3yjIsnpyPxgaqVdxVFCXZcvrLa3aP /ORfrd2RBNelANyFqnz+giFiXFB1gxj2dY8eDp/Y= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Nikos Tsironis , Joe Thornber , Mikulas Patocka , Mike Snitzer Subject: [PATCH 4.4 138/143] dm thin: fix bug where bio that overwrites thin block ignores FUA Date: Mon, 18 Feb 2019 14:44:26 +0100 Message-Id: <20190218133534.017054671@linuxfoundation.org> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190218133529.099444112@linuxfoundation.org> References: <20190218133529.099444112@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 4.4-stable review patch. If anyone has any objections, please let me know. ------------------ From: Nikos Tsironis commit 4ae280b4ee3463fa57bbe6eede26b97daff8a0f1 upstream. When provisioning a new data block for a virtual block, either because the block was previously unallocated or because we are breaking sharing, if the whole block of data is being overwritten the bio that triggered the provisioning is issued immediately, skipping copying or zeroing of the data block. When this bio completes the new mapping is inserted in to the pool's metadata by process_prepared_mapping(), where the bio completion is signaled to the upper layers. This completion is signaled without first committing the metadata. If the bio in question has the REQ_FUA flag set and the system crashes right after its completion and before the next metadata commit, then the write is lost despite the REQ_FUA flag requiring that I/O completion for this request must only be signaled after the data has been committed to non-volatile storage. Fix this by deferring the completion of overwrite bios, with the REQ_FUA flag set, until after the metadata has been committed. Cc: stable@vger.kernel.org Signed-off-by: Nikos Tsironis Acked-by: Joe Thornber Acked-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-thin.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 50 insertions(+), 5 deletions(-) --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -256,6 +256,7 @@ struct pool { spinlock_t lock; struct bio_list deferred_flush_bios; + struct bio_list deferred_flush_completions; struct list_head prepared_mappings; struct list_head prepared_discards; struct list_head active_thins; @@ -920,6 +921,39 @@ static void process_prepared_mapping_fai mempool_free(m, m->tc->pool->mapping_pool); } +static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio) +{ + struct pool *pool = tc->pool; + unsigned long flags; + + /* + * If the bio has the REQ_FUA flag set we must commit the metadata + * before signaling its completion. + */ + if (!bio_triggers_commit(tc, bio)) { + bio_endio(bio); + return; + } + + /* + * Complete bio with an error if earlier I/O caused changes to the + * metadata that can't be committed, e.g, due to I/O errors on the + * metadata device. + */ + if (dm_thin_aborted_changes(tc->td)) { + bio_io_error(bio); + return; + } + + /* + * Batch together any bios that trigger commits and then issue a + * single commit for them in process_deferred_bios(). + */ + spin_lock_irqsave(&pool->lock, flags); + bio_list_add(&pool->deferred_flush_completions, bio); + spin_unlock_irqrestore(&pool->lock, flags); +} + static void process_prepared_mapping(struct dm_thin_new_mapping *m) { struct thin_c *tc = m->tc; @@ -952,7 +986,7 @@ static void process_prepared_mapping(str */ if (bio) { inc_remap_and_issue_cell(tc, m->cell, m->data_block); - bio_endio(bio); + complete_overwrite_bio(tc, bio); } else { inc_all_io_entry(tc->pool, m->cell->holder); remap_and_issue(tc, m->cell->holder, m->data_block); @@ -2228,7 +2262,7 @@ static void process_deferred_bios(struct { unsigned long flags; struct bio *bio; - struct bio_list bios; + struct bio_list bios, bio_completions; struct thin_c *tc; tc = get_first_thin(pool); @@ -2239,26 +2273,36 @@ static void process_deferred_bios(struct } /* - * If there are any deferred flush bios, we must commit - * the metadata before issuing them. + * If there are any deferred flush bios, we must commit the metadata + * before issuing them or signaling their completion. */ bio_list_init(&bios); + bio_list_init(&bio_completions); + spin_lock_irqsave(&pool->lock, flags); bio_list_merge(&bios, &pool->deferred_flush_bios); bio_list_init(&pool->deferred_flush_bios); + + bio_list_merge(&bio_completions, &pool->deferred_flush_completions); + bio_list_init(&pool->deferred_flush_completions); spin_unlock_irqrestore(&pool->lock, flags); - if (bio_list_empty(&bios) && + if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) && !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool))) return; if (commit(pool)) { + bio_list_merge(&bios, &bio_completions); + while ((bio = bio_list_pop(&bios))) bio_io_error(bio); return; } pool->last_commit_jiffies = jiffies; + while ((bio = bio_list_pop(&bio_completions))) + bio_endio(bio); + while ((bio = bio_list_pop(&bios))) generic_make_request(bio); } @@ -2885,6 +2929,7 @@ static struct pool *pool_create(struct m INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout); spin_lock_init(&pool->lock); bio_list_init(&pool->deferred_flush_bios); + bio_list_init(&pool->deferred_flush_completions); INIT_LIST_HEAD(&pool->prepared_mappings); INIT_LIST_HEAD(&pool->prepared_discards); INIT_LIST_HEAD(&pool->active_thins);