Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp634816pxb; Tue, 5 Apr 2022 16:44:29 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyOflnioGjQdEofT7ZY0RJC+CG818A2pDGxRAe75nVfjB13y+fdsSk/FHhfwHPJf/X5MeOH X-Received: by 2002:a05:6a00:300d:b0:4fa:8327:88c7 with SMTP id ay13-20020a056a00300d00b004fa832788c7mr6160552pfb.16.1649202269068; Tue, 05 Apr 2022 16:44:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649202269; cv=none; d=google.com; s=arc-20160816; b=BgDANnsg5Wvmuyxt7xq3WtAHcw+9BN7sY9cgDmkpQfPk0KatFs2dh7KoePklxxU8/E Yv0fwCmeakClwfb9q7PI38qYm4hPypraBMO0qiMwt8gwjmtRmY6dwacLC1/kCmhAcuO6 d6EUYtRBggr4mSj+iysrcWRCjYvkt/gJe0u4K/lagu5tJNOptwhyxC7VfeBD2ddsb4g+ bBSeGj3ArMQkbCz3ht9tCtVQYF6EeOHWNpTUE049xnzgC1gmdsZlE1EzqNFBtQzj4L29 n8WVz2BaHWWdSsm8+wsVKCkxN2lCTICYxmMLrKZZWnt+Mn0kdAHdCldJhGS0Fko7BPvr +CxQ== 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=TA9AUp+6x4GmMzy+0eHATVqd491/2d7OWrBLQh26uyI=; b=d/90qHEMFA3kbpz1Fq9Noe0W9Cl50aOiNiNaFXKYm4rJ1fStMLBC28reDj39hJjIUj XsxZx7u1I1O0qbu5P9ctLANNOrACoLppjDSbYK+pWKm5ROTovVkFA5mf9iqj/n9GjlFw xj3AhoOhf2T3T3EUgbNNwOI4QgLVzcDFgfxZcJg4ujK7cKx7RncIxoHfLl30/Hf8AUry 0Fw/1KoWsUt6dQaPxN4/w4dXXP5hEDeKLEOtEM58tD+k3C4/UA/vTQUXrrcwDKMfCIKW ljJmC4QNcI5tteAQ6om2eISsmtrCIZ5+MBfna2Qdn4D3yfZ8Mt26kzfWRXJwkXpFo14M LxeA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=01aOA8Dx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1: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 lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id n126-20020a634084000000b0039aa750fe39si1204606pga.593.2022.04.05.16.44.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 05 Apr 2022 16:44:29 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=01aOA8Dx; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1: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: from out1.vger.email (out1.vger.email [IPv6:2620:137:e000::1:20]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 4CF5025D5F2; Tue, 5 Apr 2022 16:30:32 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1383532AbiDEMZ5 (ORCPT + 99 others); Tue, 5 Apr 2022 08:25:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:42510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241059AbiDEIs0 (ORCPT ); Tue, 5 Apr 2022 04:48:26 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8D4C328E36; Tue, 5 Apr 2022 01:36:42 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 279D861535; Tue, 5 Apr 2022 08:36:24 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 3837BC385A4; Tue, 5 Apr 2022 08:36:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1649147783; bh=ZxgY+DG0V/m8ix9O/dK77iX00sKsYy35vR68jBeaAoE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=01aOA8DxGXnYeC3GqxeFfAJEtjiZkj+5T7rrp1cqXM5gxHGF0pM0in/1FX9FDjg1W GCJwL/68KxwETN+q+rL8KOqiw1UWl2S7KRsAfwvKOk90mrECFLTWclj/hjdILNmknA 6Mrq+QULBGJ5allcfTi5uLDagdIp13bm4xm8n7as= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Mike Snitzer Subject: [PATCH 5.16 0121/1017] dm: fix double accounting of flush with data Date: Tue, 5 Apr 2022 09:17:14 +0200 Message-Id: <20220405070357.790035806@linuxfoundation.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220405070354.155796697@linuxfoundation.org> References: <20220405070354.155796697@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Mike Snitzer commit 8d394bc4adf588ca4a0650745167cb83f86c18c9 upstream. DM handles a flush with data by first issuing an empty flush and then once it completes the REQ_PREFLUSH flag is removed and the payload is issued. The problem fixed by this commit is that both the empty flush bio and the data payload will account the full extent of the data payload. Fix this by factoring out dm_io_acct() and having it wrap all IO accounting to set the size of bio with REQ_PREFLUSH to 0, account the IO, and then restore the original size. Cc: stable@vger.kernel.org Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-stats.c | 6 ++++-- drivers/md/dm-stats.h | 2 +- drivers/md/dm.c | 47 +++++++++++++++++++++++++++++++++-------------- 3 files changed, 38 insertions(+), 17 deletions(-) --- a/drivers/md/dm-stats.c +++ b/drivers/md/dm-stats.c @@ -644,13 +644,14 @@ static void __dm_stat_bio(struct dm_stat void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw, sector_t bi_sector, unsigned bi_sectors, bool end, - unsigned long duration_jiffies, + unsigned long start_time, struct dm_stats_aux *stats_aux) { struct dm_stat *s; sector_t end_sector; struct dm_stats_last_position *last; bool got_precise_time; + unsigned long duration_jiffies = 0; if (unlikely(!bi_sectors)) return; @@ -670,7 +671,8 @@ void dm_stats_account_io(struct dm_stats )); WRITE_ONCE(last->last_sector, end_sector); WRITE_ONCE(last->last_rw, bi_rw); - } + } else + duration_jiffies = jiffies - start_time; rcu_read_lock(); --- a/drivers/md/dm-stats.h +++ b/drivers/md/dm-stats.h @@ -31,7 +31,7 @@ int dm_stats_message(struct mapped_devic void dm_stats_account_io(struct dm_stats *stats, unsigned long bi_rw, sector_t bi_sector, unsigned bi_sectors, bool end, - unsigned long duration_jiffies, + unsigned long start_time, struct dm_stats_aux *aux); static inline bool dm_stats_used(struct dm_stats *st) --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -484,29 +484,48 @@ u64 dm_start_time_ns_from_clone(struct b } EXPORT_SYMBOL_GPL(dm_start_time_ns_from_clone); -static void start_io_acct(struct dm_io *io) +static bool bio_is_flush_with_data(struct bio *bio) { - struct mapped_device *md = io->md; - struct bio *bio = io->orig_bio; + return ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size); +} + +static void dm_io_acct(bool end, struct mapped_device *md, struct bio *bio, + unsigned long start_time, struct dm_stats_aux *stats_aux) +{ + bool is_flush_with_data; + unsigned int bi_size; + + /* If REQ_PREFLUSH set save any payload but do not account it */ + is_flush_with_data = bio_is_flush_with_data(bio); + if (is_flush_with_data) { + bi_size = bio->bi_iter.bi_size; + bio->bi_iter.bi_size = 0; + } + + if (!end) + bio_start_io_acct_time(bio, start_time); + else + bio_end_io_acct(bio, start_time); - bio_start_io_acct_time(bio, io->start_time); if (unlikely(dm_stats_used(&md->stats))) dm_stats_account_io(&md->stats, bio_data_dir(bio), bio->bi_iter.bi_sector, bio_sectors(bio), - false, 0, &io->stats_aux); + end, start_time, stats_aux); + + /* Restore bio's payload so it does get accounted upon requeue */ + if (is_flush_with_data) + bio->bi_iter.bi_size = bi_size; +} + +static void start_io_acct(struct dm_io *io) +{ + dm_io_acct(false, io->md, io->orig_bio, io->start_time, &io->stats_aux); } static void end_io_acct(struct mapped_device *md, struct bio *bio, unsigned long start_time, struct dm_stats_aux *stats_aux) { - unsigned long duration = jiffies - start_time; - - bio_end_io_acct(bio, start_time); - - if (unlikely(dm_stats_used(&md->stats))) - dm_stats_account_io(&md->stats, bio_data_dir(bio), - bio->bi_iter.bi_sector, bio_sectors(bio), - true, duration, stats_aux); + dm_io_acct(true, md, bio, start_time, stats_aux); } static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) @@ -835,7 +854,7 @@ void dm_io_dec_pending(struct dm_io *io, if (io_error == BLK_STS_DM_REQUEUE) return; - if ((bio->bi_opf & REQ_PREFLUSH) && bio->bi_iter.bi_size) { + if (bio_is_flush_with_data(bio)) { /* * Preflush done for flush with data, reissue * without REQ_PREFLUSH.