From nobody Fri Apr 3 01:22:51 2026 Received: from mail-qt1-f170.google.com (mail-qt1-f170.google.com [209.85.160.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C67403A3831 for ; Wed, 25 Mar 2026 10:28:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.160.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774434489; cv=none; b=my1ntoRTHKXRox5dFgWRLqxcXAPyheNFenZEGlvf6JvyR7yqeFdu0JgLO0AlFkFufX8lBWu0dJINe3a4AI897Q4YNV7m9d7Gh+0NayiceCSypY+xiLWWqoIk/s12ZYTKAgsBfL1upZdyCYLRt3PM2GA2TzPG4AMHu4Mss2WfzkM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774434489; c=relaxed/simple; bh=tom43KEKyh2fvaci/YD62RwzIfn9WllCNjMC0bb/dl8=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=hiLjTfh8v2DAWuOlG+iNaUPNZviJ/WH2J5TKkJmrS8X5AvTLabaQPzemmdeX+EAPiMLPpffYJnXkqJlljjvIwo/wDHXbeVs4MUp9xdato+JGYtTLK/sAao+ykTWW1yxkSRDUQxY3ap2v4ohCW9mhG6AQ45JJSzXO4hTqUGW8X84= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com; spf=fail smtp.mailfrom=purestorage.com; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b=U1EYx8mA; arc=none smtp.client-ip=209.85.160.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=purestorage.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=purestorage.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=purestorage.com header.i=@purestorage.com header.b="U1EYx8mA" Received: by mail-qt1-f170.google.com with SMTP id d75a77b69052e-506362ac5f7so45098971cf.1 for ; Wed, 25 Mar 2026 03:28:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=purestorage.com; s=google2022; t=1774434487; x=1775039287; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=eW9ecECq1NUBzDLIkheZ6doi9a4ejV/IV7e6eOyQgdw=; b=U1EYx8mAIbQ8Q0/vKiylPJhGGtSflLfacHuqak0I8DFmOh8H6Ime+W8UUoFgJgAdV7 oA3DCi430IijAD4zXBkegn9YX5BJyQYH9NizectXUfgTj+VvcGTJPYVuPuYoqTFgfOJd CnXhBb83pRA/6+2zwGTgmv1qM3eUW3MqEFH5Tb/NG60/3PyBbVGIexYP2Nu1BfdNIq9V +A8cM4CVOKtu4i5cjaBZo7z6csrs5LAPQoUfxzg/AjSuhdEFNdtw7v7EaUINm2fIvKB8 xxqWcV3+LcCtOGKVyquw+JrOJEHUSLSxIombT+AbZapyeUlfkvpOfQH/uqSuozsokk4U StVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1774434487; x=1775039287; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=eW9ecECq1NUBzDLIkheZ6doi9a4ejV/IV7e6eOyQgdw=; b=RCiw3UPqH2tt9IdORu5b6iOuW+wtIxq0vYuCPeq2WRI3OwDo6GQta0fbrj3Y443CGt rYC0AvwkcgEA8wU4UOP820HzgQTRaJ0GiMcL+SKyBUrhF43kY16YVN+nUKpuT0rokaCW sDRlm1s6HS+wO3ImhYRws85DQ0UVCz6w79aVWiLVNAmCxmsOikn9OHJIw2dvw34tvVSc X/QUnqTofDxB1ZOtOd8S++iHx9yUTJSw2LGl0nHq4rA/zLS4mDTKY10lETufumWq33Cv cWcGvz8evcDlcE5XX5T17KUIYn3k7qUZoqYBLqejinhzdUFSLhA1XDP4lQ6uURk1sJvj XQZQ== X-Forwarded-Encrypted: i=1; AJvYcCV23jxFGqU6IIE9o7c9sauRovaFSq4AodM3xh1UADxmdLSa26oQGTJgHEmFd2Csd5D5O1shsWAmsJVK6KY=@vger.kernel.org X-Gm-Message-State: AOJu0Yzg1lkKYijlo7AwB4ZyzNrquFC3tmcGPxbCuQTX1ARkidRX+b1H IxUq4+ZOkB8K2Z7xUs7/t8A/14gKIVAVX8IJokPPfDjW0B1jkOsE114/f0rEmn94mnMXnjnhe+d nLD3e1Vw= X-Gm-Gg: ATEYQzyz+iKT65mMEdIqyWzA39MaewEcR2Ddqg1VUgmbU8kN7Kd5bEBrSmWc9wE9Rl/ Ay9gqEsxhwvrCfC1z8kiMMLguSsYQLc61ptIMySPLJUpXlHeTiN0/WlhSUIKNO83Zw3TpBbYEBq y26FWrcykGVJbUOGSjLWlHQU4LkaHE65I+vK9woJ2Won0FHjiF1Aroukpp6Hk0kLMfwsuYpzRo7 ZyvkyMmKh3XEj+R9lDom6hxvjrV3vTXUz/9MEMb+VZJmlSTiZbaI8uXPi/0g0NONlFJdYOw6Y4c tlDsFSc9DrW82anE14jrWFcBEPVEDNIlJcLrEdgLvwu4igfMD7ERE1LeCKEHafdgEAk8QXxeIAg YjB42hw1TLtIbv6iqnLwvTd88y2WKB92gKkMDnlfn5BoNxBDpLWpcWgx2/fGN1LEKZE5jY9XSPf wmFUGfEj34WyTbfCr4I+iJjdPH/AI1sVF5oYyOxke+ewY1TqP1wk5k+N2eu5UTOtNdx3okELMq X-Received: by 2002:a05:622a:1f8e:b0:50b:4d27:bebb with SMTP id d75a77b69052e-50b80ccc75fmr44824111cf.14.1774434486645; Wed, 25 Mar 2026 03:28:06 -0700 (PDT) Received: from vm-libchen-fa.tier4-kif-devvm.svc.slc-eng-prd2 ([208.88.159.129]) by smtp.googlemail.com with ESMTPSA id 6a1803df08f44-89c85361ac2sm132870796d6.41.2026.03.25.03.28.05 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 25 Mar 2026 03:28:06 -0700 (PDT) From: Libo Chen To: Alasdair Kergon , Mike Snitzer , Mikulas Patocka , Benjamin Marzinski Cc: dm-devel@lists.linux.dev, linux-kernel@vger.kernel.org, Yuanyuan Zhong , libochen@chenlibo.work Subject: [PATCH] dm: fix race between dm_mq_queue_rq and __dm_destroy Date: Wed, 25 Mar 2026 04:27:41 -0600 Message-Id: <20260325102741.293982-1-libchen@purestorage.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" The existing dm_get() calls BUG_ON if DMF_FREEING is already set. This can be triggered when a request is dispatched via blk_mq_requeue_work() racing with __dm_destroy(): CPU0 CPU1 ---- ---- __dm_destroy() set_bit(DMF_FREEING) blk_mq_requeue_work() dm_mq_queue_rq() dm_start_request() dm_get(md) BUG_ON(DMF_FREEING) <-- crash Introduce dm_try_get() which increments holders first, then checks DMF_FREEING. If set, it decrements holders and returns false. The smp_mb__after_atomic() ensures the increment is visible before reading the flag, providing correct synchronization with __dm_destroy(). dm_hold() was not used because it acquires the global _minor_lock, which would cause contention in the hot I/O path. Move dm_try_get() before blk_mq_start_request() in dm_start_request(). This ensures we don't start the block layer timer or mark the request MQ_RQ_IN_FLIGHT for a request that will immediately fail due to device destruction. If dm_try_get() fails, we return early without calling blk_mq_start_request(), providing cleaner error semantics. Signed-off-by: Libo Chen --- drivers/md/dm-rq.c | 26 ++++++++++++++++---------- drivers/md/dm.c | 12 ++++++++++++ include/linux/device-mapper.h | 1 + 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index a6ca92049c10..dc6ba46cad92 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -430,8 +430,20 @@ ssize_t dm_attr_rq_based_seq_io_merge_deadline_store(s= truct mapped_device *md, return count; } =20 -static void dm_start_request(struct mapped_device *md, struct request *ori= g) +static bool dm_start_request(struct mapped_device *md, struct request *ori= g) { + /* + * Hold the md reference here for the in-flight I/O. + * We can't rely on the reference count by device opener, + * because the device may be closed during the request completion + * when all bios are completed. + * See the comment in rq_completed() too. + * + * Fail if DMF_FREEING is set to avoid racing with __dm_destroy(). + */ + if (!dm_try_get(md)) + return false; + blk_mq_start_request(orig); =20 if (unlikely(dm_stats_used(&md->stats))) { @@ -444,14 +456,7 @@ static void dm_start_request(struct mapped_device *md,= struct request *orig) &tio->stats_aux); } =20 - /* - * Hold the md reference here for the in-flight I/O. - * We can't rely on the reference count by device opener, - * because the device may be closed during the request completion - * when all bios are completed. - * See the comment in rq_completed() too. - */ - dm_get(md); + return true; } =20 static int dm_mq_init_request(struct blk_mq_tag_set *set, struct request *= rq, @@ -508,7 +513,8 @@ static blk_status_t dm_mq_queue_rq(struct blk_mq_hw_ctx= *hctx, if (ti->type->busy && ti->type->busy(ti)) return BLK_STS_RESOURCE; =20 - dm_start_request(md, rq); + if (!dm_start_request(md, rq)) + return BLK_STS_IOERR; =20 /* Init tio using md established in .init_request */ init_tio(tio, rq, md); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 6c83ab940af7..bd75b34de333 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -2673,6 +2673,18 @@ void dm_get(struct mapped_device *md) BUG_ON(test_bit(DMF_FREEING, &md->flags)); } =20 +bool dm_try_get(struct mapped_device *md) +{ + atomic_inc(&md->holders); + smp_mb__after_atomic(); + + if (unlikely(test_bit(DMF_FREEING, &md->flags))) { + atomic_dec(&md->holders); + return false; + } + return true; +} + int dm_hold(struct mapped_device *md) { spin_lock(&_minor_lock); diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 84fdc3a6a19a..8df81c180f2f 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -500,6 +500,7 @@ int dm_create(int minor, struct mapped_device **md); */ struct mapped_device *dm_get_md(dev_t dev); void dm_get(struct mapped_device *md); +bool dm_try_get(struct mapped_device *md); int dm_hold(struct mapped_device *md); void dm_put(struct mapped_device *md); =20 --=20 2.34.1