Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp4137556pxb; Mon, 27 Sep 2021 10:08:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxTaGjvBTzxOjIFKZb5bUAuVX3ZWR+3PjYN0sJoDcgX5Ge4I5eybJCS+4syv+ATgxwDV1U0 X-Received: by 2002:a63:da54:: with SMTP id l20mr610426pgj.341.1632762536347; Mon, 27 Sep 2021 10:08:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1632762536; cv=none; d=google.com; s=arc-20160816; b=jIEC5j+EVroUYnvcObM+tHe3JhcxYNFI3J/b+1R8TEQk/LHRWYpxR2WCbGhorkskDH GoKOjM60ajElCOM/fdMue0rq7eA/4KHy5jsJF8YjKvfgu7wCNEMFxvDe2FM6sEfyNMJm VKzg6BWlb6dF+BbTjCu7lxQbTqIW7AaWbMs9AuBPlNYv0HHXu/kiDUbqR+vJtSY00FLB AWl1pX5XuAnrCeayVzW/vIxtqvAZnBqGj0Si7BGrHHL/5yu6W3qA/DMUCbqvdVZL5bwJ Xj+FvhcPX7wC/TTdvdlzIa6Eknh2/V5hbN1BPI8aQip8zzAVlZlJWrPN9/VpaU5V51Ix 3ZNg== 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=nZwzEBsKsILmDnIiDGq3V4DH1M9BTiNXpKgCAcCWTp0=; b=GdnbcwfIhfmQ3TPbOiKV9gf/hBpCCXoKv/EOVcdTduvQ1FyChunRhJTxZLlSgPXhpG NZA8d+06A9j3Ne4MQfyFd8L/GSId4K6TVYo/leezOZuCbhrvEfXporoy0ut38xLk2rzy 19iZfJTGsG2NsV5viHF2PcfcPDdBx47afI5tjC3zDSnQ+wUMWrzLWuuXtEJqpqgp/6p7 BzzueKde/jeEIk6Op8mAVYnBQW7ZOidsWE1SLqt49nqLm46jp1agp7pJGPBZELLF5mUL NDiSHbX3y8G77SWGNQnCFFXsAQTNv2+gMee8y8jrRzAmvsHS5iHdQtHR+qVz8ow4DhKd r40w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=a3wP7iYy; 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 w23si22393136plk.177.2021.09.27.10.08.43; Mon, 27 Sep 2021 10:08:56 -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=a3wP7iYy; 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 S236052AbhI0RIM (ORCPT + 99 others); Mon, 27 Sep 2021 13:08:12 -0400 Received: from mail.kernel.org ([198.145.29.99]:47110 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236150AbhI0RHM (ORCPT ); Mon, 27 Sep 2021 13:07:12 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id F1808611CE; Mon, 27 Sep 2021 17:05:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1632762334; bh=YVQHPEcFz7G1/CMdqLPH6z69fDvW0MaMnm/sUqCGdfE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a3wP7iYyf/Do2EMjRgelaYnVS673mLGnLzdhTwk5klOj67OfgDyTlJmt5afCKP2P4 XDqJ94CHSSWC2C4potzAo1KjHkTDeJwSprQ7MMHjDruZnRVW29RYbmDYyRM8qcTBlo y+27i8wjzuZWEcYYPZftjZANK4GxvorPSLQaNGms= 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.4 51/68] xen/balloon: use a kernel thread instead a workqueue Date: Mon, 27 Sep 2021 19:02:47 +0200 Message-Id: <20210927170221.723839763@linuxfoundation.org> X-Mailer: git-send-email 2.33.0 In-Reply-To: <20210927170219.901812470@linuxfoundation.org> References: <20210927170219.901812470@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 ebb05517b6aa..2762d246991b 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include #include #include @@ -117,7 +119,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, @@ -132,6 +134,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); @@ -146,10 +150,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 \ @@ -383,7 +383,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; } @@ -508,18 +508,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(); @@ -546,12 +571,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. */ @@ -559,7 +579,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); @@ -664,7 +684,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); } @@ -696,6 +716,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; @@ -739,6 +761,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