Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp4143979pxb; Mon, 27 Sep 2021 10:16:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyo8k9RMyh2lkZzCnhuqhttMLQpSzjMUyJlB0tEm4i2cjuqnosHendzY9siUiFemhA72AgP X-Received: by 2002:a17:90a:1a19:: with SMTP id 25mr255665pjk.34.1632762987011; Mon, 27 Sep 2021 10:16:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1632762987; cv=none; d=google.com; s=arc-20160816; b=u/PxmYrJi/l7S57BcpLzM8pmqzaNVbRJ8UD5MXKzcLteStGv2nqYF02IbTUi8JxvG1 V0muG8uOKunOf4mDju7DDr+VlDSafJ40fZDXIEbqIrtse023qm83QQ6ohfKRaBoNakbY nPQu09YOc58Qt8Xd4BfjPEB5D3+W3R1J+QTMGmAu16qHa3Zf6ZrbMvHfW4Mto5cpIfZI jcBKXagh3C8XzhqRdzPat5HGa6GBbI/jhA83dxO+9zM05D3NXu6X+vpQdvPD4M7oYLj/ fc/q5bP5uxcH0gxyg8q+CgSXhH6vb7srrIOU7IHOaiKOVMSCx+hflm/r7fjQYzLM+DKx DUKA== 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=mWMn2V4GVCKA+8aLGS9N3pIqOF2LeDXc+7gnyV7hO+s=; b=HgbCwdfHrGPQg2estPvC2N4K7nPQqXovE87LHSQkgtCzNR5zJ9UtQiGweg1WDvDUNe mAM48XCFtRED4ohTrQ0qv+kvuWu467F+mK0MfRMc5jJCTPBbeOMU+XtkicpBg1f1IbED /EyW9e8NrAUnBpPVLapKqJObZg5wu1PYrK0GISDZU6wF4W4sM3znnYzW+9P69zXH+/IN E5TSmy3/aAvdJWU8wb/HtCWQ8+e8pkhuyy0QxVTrhk7uK0V8CRaA6Nml5+RoSn323vsA mzb7Ym49GqCRvZBi27EUz2TAVMfP9WBh1x4ACDkB6ga7/PC4id7h5mYJgZcq/dudtWhD KoDg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=iAUwQLVP; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.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 vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id e14si25927161plh.325.2021.09.27.10.16.14; Mon, 27 Sep 2021 10:16:27 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=iAUwQLVP; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.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: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236678AbhI0RRG (ORCPT + 99 others); Mon, 27 Sep 2021 13:17:06 -0400 Received: from mail.kernel.org ([198.145.29.99]:55390 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237162AbhI0ROA (ORCPT ); Mon, 27 Sep 2021 13:14:00 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id D5EAF61354; Mon, 27 Sep 2021 17:09:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1632762591; bh=R5tkoAJguWBSO1Mo9YcE7AYzzLvlyQoGMQLWrIEZEY0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=iAUwQLVPOXiIDWy1h2eGmOrbusYXbm6tLTXs/yEs/FXuvG+aYsupbHKVcgayaXJi6 d4oogGxCgjXjhTbGnChuJ7xjkKYVKnXUH30YM1UQi9zwNjS6YzQu1Jso6LmXNa+NGg RZ9xqwetwzT5Euu5KdfksldJEmNJGZBE9gMxhPPQ= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jan Beulich , Juergen Gross , Boris Ostrovsky , Sasha Levin Subject: [PATCH 5.10 081/103] xen/balloon: use a kernel thread instead a workqueue Date: Mon, 27 Sep 2021 19:02:53 +0200 Message-Id: <20210927170228.563007086@linuxfoundation.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927170225.702078779@linuxfoundation.org> References: <20210927170225.702078779@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Juergen Gross [ Upstream commit 8480ed9c2bbd56fc86524998e5f2e3e22f5038f6 ] Today the Xen ballooning is done via delayed work in a workqueue. This might result in workqueue hangups being reported in case of large amounts of memory are being ballooned in one go (here 16GB): BUG: workqueue lockup - pool cpus=6 node=0 flags=0x0 nice=0 stuck for 64s! Showing busy workqueues and worker pools: workqueue events: flags=0x0 pwq 12: cpus=6 node=0 flags=0x0 nice=0 active=2/256 refcnt=3 in-flight: 229:balloon_process pending: cache_reap workqueue events_freezable_power_: flags=0x84 pwq 12: cpus=6 node=0 flags=0x0 nice=0 active=1/256 refcnt=2 pending: disk_events_workfn workqueue mm_percpu_wq: flags=0x8 pwq 12: cpus=6 node=0 flags=0x0 nice=0 active=1/256 refcnt=2 pending: vmstat_update pool 12: cpus=6 node=0 flags=0x0 nice=0 hung=64s workers=3 idle: 2222 43 This can easily be avoided by using a dedicated kernel thread for doing the ballooning work. Reported-by: Jan Beulich Signed-off-by: Juergen Gross Reviewed-by: Boris Ostrovsky Link: https://lore.kernel.org/r/20210827123206.15429-1-jgross@suse.com Signed-off-by: Juergen Gross Signed-off-by: Sasha Levin --- drivers/xen/balloon.c | 62 +++++++++++++++++++++++++++++++------------ 1 file changed, 45 insertions(+), 17 deletions(-) diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index b57b2067ecbf..65fcbc1e076e 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -115,7 +117,7 @@ static struct ctl_table xen_root[] = { #define EXTENT_ORDER (fls(XEN_PFN_PER_PAGE) - 1) /* - * balloon_process() state: + * balloon_thread() state: * * BP_DONE: done or nothing to do, * BP_WAIT: wait to be rescheduled, @@ -130,6 +132,8 @@ enum bp_state { BP_ECANCELED }; +/* Main waiting point for xen-balloon thread. */ +static DECLARE_WAIT_QUEUE_HEAD(balloon_thread_wq); static DEFINE_MUTEX(balloon_mutex); @@ -144,10 +148,6 @@ static xen_pfn_t frame_list[PAGE_SIZE / sizeof(xen_pfn_t)]; static LIST_HEAD(ballooned_pages); static DECLARE_WAIT_QUEUE_HEAD(balloon_wq); -/* Main work function, always executed in process context. */ -static void balloon_process(struct work_struct *work); -static DECLARE_DELAYED_WORK(balloon_worker, balloon_process); - /* When ballooning out (allocating memory to return to Xen) we don't really want the kernel to try too hard since that can trigger the oom killer. */ #define GFP_BALLOON \ @@ -366,7 +366,7 @@ static void xen_online_page(struct page *page, unsigned int order) static int xen_memory_notifier(struct notifier_block *nb, unsigned long val, void *v) { if (val == MEM_ONLINE) - schedule_delayed_work(&balloon_worker, 0); + wake_up(&balloon_thread_wq); return NOTIFY_OK; } @@ -491,18 +491,43 @@ static enum bp_state decrease_reservation(unsigned long nr_pages, gfp_t gfp) } /* - * As this is a work item it is guaranteed to run as a single instance only. + * Stop waiting if either state is not BP_EAGAIN and ballooning action is + * needed, or if the credit has changed while state is BP_EAGAIN. + */ +static bool balloon_thread_cond(enum bp_state state, long credit) +{ + if (state != BP_EAGAIN) + credit = 0; + + return current_credit() != credit || kthread_should_stop(); +} + +/* + * As this is a kthread it is guaranteed to run as a single instance only. * We may of course race updates of the target counts (which are protected * by the balloon lock), or with changes to the Xen hard limit, but we will * recover from these in time. */ -static void balloon_process(struct work_struct *work) +static int balloon_thread(void *unused) { enum bp_state state = BP_DONE; long credit; + unsigned long timeout; + + set_freezable(); + for (;;) { + if (state == BP_EAGAIN) + timeout = balloon_stats.schedule_delay * HZ; + else + timeout = 3600 * HZ; + credit = current_credit(); + wait_event_interruptible_timeout(balloon_thread_wq, + balloon_thread_cond(state, credit), timeout); + + if (kthread_should_stop()) + return 0; - do { mutex_lock(&balloon_mutex); credit = current_credit(); @@ -529,12 +554,7 @@ static void balloon_process(struct work_struct *work) mutex_unlock(&balloon_mutex); cond_resched(); - - } while (credit && state == BP_DONE); - - /* Schedule more work if there is some still to be done. */ - if (state == BP_EAGAIN) - schedule_delayed_work(&balloon_worker, balloon_stats.schedule_delay * HZ); + } } /* Resets the Xen limit, sets new target, and kicks off processing. */ @@ -542,7 +562,7 @@ void balloon_set_new_target(unsigned long target) { /* No need for lock. Not read-modify-write updates. */ balloon_stats.target_pages = target; - schedule_delayed_work(&balloon_worker, 0); + wake_up(&balloon_thread_wq); } EXPORT_SYMBOL_GPL(balloon_set_new_target); @@ -647,7 +667,7 @@ void free_xenballooned_pages(int nr_pages, struct page **pages) /* The balloon may be too large now. Shrink it if needed. */ if (current_credit()) - schedule_delayed_work(&balloon_worker, 0); + wake_up(&balloon_thread_wq); mutex_unlock(&balloon_mutex); } @@ -679,6 +699,8 @@ static void __init balloon_add_region(unsigned long start_pfn, static int __init balloon_init(void) { + struct task_struct *task; + if (!xen_domain()) return -ENODEV; @@ -722,6 +744,12 @@ static int __init balloon_init(void) } #endif + task = kthread_run(balloon_thread, NULL, "xen-balloon"); + if (IS_ERR(task)) { + pr_err("xen-balloon thread could not be started, ballooning will not work!\n"); + return PTR_ERR(task); + } + /* Init the xen-balloon driver. */ xen_balloon_init(); -- 2.33.0