From nobody Mon Apr 6 14:57:26 2026 Received: from outbound.baidu.com (mx15.baidu.com [111.202.115.100]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5D6433A3E7F for ; Thu, 19 Mar 2026 07:45:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=111.202.115.100 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773906341; cv=none; b=XUG/wum2D0VuhCMV7/2qx/Z7nEqeUnmkNoJADxT741Rla4hrNYREmHD8fV2TaLzKddAE8R0z6VMxMUse/2CR+8WJvXBX9JFZU8bs9Z9vp3T7LxM845VNQkUYUAL1l5qwWqpjT3QN34aH3ozYsPQE1iCEFFrUmHAB4rx3p3SgWJo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773906341; c=relaxed/simple; bh=t0kCcglzPWFSsaf0RDjlEHUAC2vqkYe4yPOzmNCxmBM=; h=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type; b=ugjYnb8hKIi5V0soh8g35zdcZ3N+du/sY+zBSBYJiK+KrO+B0YnkjKxuqQfIoY1AMPfyxxihM72No71JHbS+WvSuPmCBQzPy4leh1ZTp3mahbFcUzxmB7Hj599Jk/IrMhtGnbomovwCaE2Lz+qlRhHhJJnqSSUsyEKnSNJl5gvw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=baidu.com; spf=pass smtp.mailfrom=baidu.com; dkim=pass (2048-bit key) header.d=baidu.com header.i=@baidu.com header.b=aN+ebKE8; arc=none smtp.client-ip=111.202.115.100 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=baidu.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baidu.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baidu.com header.i=@baidu.com header.b="aN+ebKE8" X-MD-Sfrom: lirongqing@baidu.com X-MD-SrcIP: 172.31.50.47 From: lirongqing To: Andrew Morton , Uladzislau Rezki , , CC: Li RongQing Subject: [PATCH v2] mm/vmalloc: use dedicated unbound workqueue for vmap area draining Date: Thu, 19 Mar 2026 03:43:07 -0400 Message-ID: <20260319074307.2325-1-lirongqing@baidu.com> X-Mailer: git-send-email 2.17.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-ClientProxiedBy: bjhj-exc9.internal.baidu.com (172.31.3.19) To bjkjy-exc3.internal.baidu.com (172.31.50.47) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baidu.com; s=selector1; t=1773906197; bh=ZYaovtd9STTHHi4P6uKPiHfVgDEzzqsGQYk6Ozrb4I8=; h=From:To:CC:Subject:Date:Message-ID:Content-Type; b=aN+ebKE82vdqMrxigLnItga9lvCFA1/Kz7EzVZfUPuYgw50xOyMEWR1SD0cmZB1u5 QIDM29FnsrJU+p/Zz3PO4pv5NrsC5ZJfzhVMs2Da9vYgiHJnURIRucrF93X229fihi 3tWlUjiauWZ+9aGmmVLaQhBruvopuKLUsvwCe0sM8noi+fmTETJ3+WwYIj0c/VyZ2l KNZUzy8yJZnK9LNggOcsCMMNp7YKDPr2hM5DPIJ8BTjm6n2t9xwZss7Tq/CmKSeMVJ mRN1BchIqahlEcDuKJvFn23Dp6YKZnyVTFZPAporjjay2GOVRv5n750OHY7JO82brO W5bjxlyG7XTBw== Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Li RongQing The drain_vmap_area_work() function can take >10ms to complete when there are many accumulated vmap areas in a system with a high CPU count, causing workqueue watchdog warnings when run via schedule_work(): [ 2069.796205] workqueue: drain_vmap_area_work hogged CPU for >10000us 4 ti= mes, consider switching to WQ_UNBOUND [ 2192.823225] workqueue: drain_vmap_area_work hogged CPU for >10000us 5 ti= mes, consider switching to WQ_UNBOUND Switch to a dedicated WQ_UNBOUND workqueue to allow the scheduler to run this background task on any available CPU, improving responsiveness. Use WQ_MEM_RECLAIM to ensure forward progress under memory pressure. Create vmap_drain_wq in vmalloc_init_late() which is called after workqueue_init_early() in start_kernel() to avoid boot-time crashes. Suggested-by: Uladzislau Rezki Signed-off-by: Li RongQing --- Diff with v1: create dedicated unbound workqueue include/linux/vmalloc.h | 2 ++ init/main.c | 1 + mm/vmalloc.c | 14 +++++++++++++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index e8e94f9..c028603 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -301,11 +301,13 @@ static inline void set_vm_flush_reset_perms(void *add= r) if (vm) vm->flags |=3D VM_FLUSH_RESET_PERMS; } +void __init vmalloc_init_late(void); #else /* !CONFIG_MMU */ #define VMALLOC_TOTAL 0UL =20 static inline unsigned long vmalloc_nr_pages(void) { return 0; } static inline void set_vm_flush_reset_perms(void *addr) {} +static inline void __init vmalloc_init_late(void) {} #endif /* CONFIG_MMU */ =20 #if defined(CONFIG_MMU) && defined(CONFIG_SMP) diff --git a/init/main.c b/init/main.c index 1cb395d..50b497f 100644 --- a/init/main.c +++ b/init/main.c @@ -1099,6 +1099,7 @@ void start_kernel(void) * workqueue_init(). */ workqueue_init_early(); + vmalloc_init_late(); =20 rcu_init(); kvfree_rcu_init(); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 61caa55..a52ccd4 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1067,6 +1067,7 @@ static void reclaim_and_purge_vmap_areas(void); static BLOCKING_NOTIFIER_HEAD(vmap_notify_list); static void drain_vmap_area_work(struct work_struct *work); static DECLARE_WORK(drain_vmap_work, drain_vmap_area_work); +static struct workqueue_struct *vmap_drain_wq; =20 static __cacheline_aligned_in_smp atomic_long_t nr_vmalloc_pages; static __cacheline_aligned_in_smp atomic_long_t vmap_lazy_nr; @@ -2471,7 +2472,7 @@ static void free_vmap_area_noflush(struct vmap_area *= va) =20 /* After this point, we may free va at any time */ if (unlikely(nr_lazy > nr_lazy_max)) - schedule_work(&drain_vmap_work); + queue_work(vmap_drain_wq, &drain_vmap_work); } =20 /* @@ -5422,6 +5423,17 @@ vmap_node_shrink_scan(struct shrinker *shrink, struc= t shrink_control *sc) return SHRINK_STOP; } =20 +void __init vmalloc_init_late(void) +{ + vmap_drain_wq =3D alloc_workqueue("vmap_drain", + WQ_UNBOUND | WQ_MEM_RECLAIM, 0); + if (!vmap_drain_wq) { + pr_warn("vmap_drain_wq creation failed, using system_unbound_wq\n"); + vmap_drain_wq =3D system_unbound_wq; + } + +} + void __init vmalloc_init(void) { struct shrinker *vmap_node_shrinker; --=20 2.9.4