Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp705322pxb; Tue, 5 Apr 2022 19:34:49 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzwtVH/6b8/qzAeCNbMG7vxXs0lKz6UzHzRCVrUFeqWCoDdfR+hvf9RQwstliCSRwWRE1W4 X-Received: by 2002:a05:6a00:1391:b0:4fb:607d:4453 with SMTP id t17-20020a056a00139100b004fb607d4453mr6775950pfg.4.1649212373526; Tue, 05 Apr 2022 19:32:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649212373; cv=none; d=google.com; s=arc-20160816; b=tjXPo8aN28Q7jK7xKkB0zYw8GmgdNsnSOngOZb3njYaMAlqBcTKwxiU1zCT7MFKHDa p2Qk6MVWWqL6N1Fila3tNhUmYVLumgdT6zSaPTnWj5GSGrK33DaSHVu8kKtKPVFRmlGX rN5sqH/eh2aOAGQeHwp6GavGNwh1JsZ4qkpZUSu+jZTEcmMxNtPQ3YK10NwHpV/tdbKR mEl1F0QvRVaf3NyEFmTPW6r3ftfkTLyDN0j0lnHxM6HjOPtm21XP7/yDwLSsj7ePmdBT 300S2Yx5k+ebF2Ckvu5MfxovNkl6gblcRDZ3qt35FtAq4C2wji5xTnWjbn0diebpp6OC I96Q== 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=mI+h16DHrHcijUh6RWVxT9QRWglkszON9TU/lP3kvUI=; b=Pt8Guk7/1sudUmUQ0DkeNyHKnMfTxUmBAuSr6/mWQvqQ/7CKSYj5Y2/qRfWbRhYAde B/7/S7CXyjT/Hr6gdZmhtg99OoncyqC1gOfP7F4LxoM7CblfF7ya3ne4qX1aaXiQDGEL F2ZcLX9itiKk2xFu8Ziy1g/HRbkzCB4UQQ5WnuZd5aJ1zcjisoV+jQNq0Fmdj272tunO YSZ7e84ISirm9/kkMCDbG9xmBLMEmjhdmg1pAgBp7BUFXKQtfkjkeHT2ikclUpsuu3IS wyBW+ryYOfwfjya0tfiQflm0RwSW/sONpaXx/68vHpkx5Z5nVSX+twaBbIQrlXxGNaC3 CLhg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Lcvv2F42; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 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 out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id k68-20020a636f47000000b00382b76401ecsi16645532pgc.268.2022.04.05.19.32.38; Tue, 05 Apr 2022 19:32:53 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=Lcvv2F42; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 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 S1380511AbiDEMDE (ORCPT + 99 others); Tue, 5 Apr 2022 08:03:04 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41468 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S243308AbiDEIuV (ORCPT ); Tue, 5 Apr 2022 04:50:21 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [IPv6:2604:1380:4641:c500::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0F06BE097; Tue, 5 Apr 2022 01:38:38 -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 F1B6B6152C; Tue, 5 Apr 2022 08:38:09 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0AA6DC385A1; Tue, 5 Apr 2022 08:38:08 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1649147889; bh=2FjM/lj0fcJq0jHwEH+Am/vpGg0MEDZx4Nc772tYTu4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=Lcvv2F42S2+azgDa0ub0hoiHjEraduQROI9mrjnUpYrgeovrdMZ7JUd5gp5+OhVo7 +KMvAqqZJh/Q6Zk2QldTS9RfteRnjTeZdHQP7jxU7LkH97BSHRKGoUf1bloUTpZNtR X/wjxXhjDvW1IHyhJScViPo3l5pvMMZi1ZRkDP4A= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Mikulas Patocka , Mike Snitzer Subject: [PATCH 5.16 0120/1017] dm: interlock pending dm_io and dm_wait_for_bios_completion Date: Tue, 5 Apr 2022 09:17:13 +0200 Message-Id: <20220405070357.759928595@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=-7.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_HI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=ham 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 9f6dc633761006f974701d4c88da71ab68670749 upstream. Commit d208b89401e0 ("dm: fix mempool NULL pointer race when completing IO") didn't go far enough. When bio_end_io_acct ends the count of in-flight I/Os may reach zero and the DM device may be suspended. There is a possibility that the suspend races with dm_stats_account_io. Fix this by adding percpu "pending_io" counters to track outstanding dm_io. Move kicking of suspend queue to dm_io_dec_pending(). Also, rename md_in_flight_bios() to dm_in_flight_bios() and update it to iterate all pending_io counters. Fixes: d208b89401e0 ("dm: fix mempool NULL pointer race when completing IO") Cc: stable@vger.kernel.org Co-developed-by: Mikulas Patocka Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman --- drivers/md/dm-core.h | 2 ++ drivers/md/dm.c | 35 +++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) --- a/drivers/md/dm-core.h +++ b/drivers/md/dm-core.h @@ -65,6 +65,8 @@ struct mapped_device { struct gendisk *disk; struct dax_device *dax_dev; + unsigned long __percpu *pending_io; + /* * A list of ios that arrived while we were suspended. */ --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -507,10 +507,6 @@ static void end_io_acct(struct mapped_de dm_stats_account_io(&md->stats, bio_data_dir(bio), bio->bi_iter.bi_sector, bio_sectors(bio), true, duration, stats_aux); - - /* nudge anyone waiting on suspend queue */ - if (unlikely(wq_has_sleeper(&md->wait))) - wake_up(&md->wait); } static struct dm_io *alloc_io(struct mapped_device *md, struct bio *bio) @@ -531,6 +527,7 @@ static struct dm_io *alloc_io(struct map io->magic = DM_IO_MAGIC; io->status = 0; atomic_set(&io->io_count, 1); + this_cpu_inc(*md->pending_io); io->orig_bio = bio; io->md = md; spin_lock_init(&io->endio_lock); @@ -828,6 +825,12 @@ void dm_io_dec_pending(struct dm_io *io, stats_aux = io->stats_aux; free_io(md, io); end_io_acct(md, bio, start_time, &stats_aux); + smp_wmb(); + this_cpu_dec(*md->pending_io); + + /* nudge anyone waiting on suspend queue */ + if (unlikely(wq_has_sleeper(&md->wait))) + wake_up(&md->wait); if (io_error == BLK_STS_DM_REQUEUE) return; @@ -1689,6 +1692,11 @@ static void cleanup_mapped_device(struct blk_cleanup_disk(md->disk); } + if (md->pending_io) { + free_percpu(md->pending_io); + md->pending_io = NULL; + } + cleanup_srcu_struct(&md->io_barrier); mutex_destroy(&md->suspend_lock); @@ -1786,6 +1794,10 @@ static struct mapped_device *alloc_dev(i if (!md->wq) goto bad; + md->pending_io = alloc_percpu(unsigned long); + if (!md->pending_io) + goto bad; + dm_stats_init(&md->stats); /* Populate the mapping, nobody knows we exist yet */ @@ -2193,16 +2205,13 @@ void dm_put(struct mapped_device *md) } EXPORT_SYMBOL_GPL(dm_put); -static bool md_in_flight_bios(struct mapped_device *md) +static bool dm_in_flight_bios(struct mapped_device *md) { int cpu; - struct block_device *part = dm_disk(md)->part0; - long sum = 0; + unsigned long sum = 0; - for_each_possible_cpu(cpu) { - sum += part_stat_local_read_cpu(part, in_flight[0], cpu); - sum += part_stat_local_read_cpu(part, in_flight[1], cpu); - } + for_each_possible_cpu(cpu) + sum += *per_cpu_ptr(md->pending_io, cpu); return sum != 0; } @@ -2215,7 +2224,7 @@ static int dm_wait_for_bios_completion(s while (true) { prepare_to_wait(&md->wait, &wait, task_state); - if (!md_in_flight_bios(md)) + if (!dm_in_flight_bios(md)) break; if (signal_pending_state(task_state, current)) { @@ -2227,6 +2236,8 @@ static int dm_wait_for_bios_completion(s } finish_wait(&md->wait, &wait); + smp_rmb(); + return r; }