All of lore.kernel.org
 help / color / mirror / Atom feed
From: "David Hildenbrand (Red Hat)" <david@kernel.org>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org, linuxppc-dev@lists.ozlabs.org,
	"Broadcom internal kernel review list"
	<bcm-kernel-feedback-list@broadcom.com>,
	linux-doc@vger.kernel.org, virtualization@lists.linux.dev,
	"David Hildenbrand (Red Hat)" <david@kernel.org>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Oscar Salvador" <osalvador@suse.de>,
	"Lorenzo Stoakes" <lorenzo.stoakes@oracle.com>,
	"Liam R. Howlett" <Liam.Howlett@oracle.com>,
	"Vlastimil Babka" <vbabka@suse.cz>,
	"Mike Rapoport" <rppt@kernel.org>,
	"Suren Baghdasaryan" <surenb@google.com>,
	"Michal Hocko" <mhocko@suse.com>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Madhavan Srinivasan" <maddy@linux.ibm.com>,
	"Michael Ellerman" <mpe@ellerman.id.au>,
	"Nicholas Piggin" <npiggin@gmail.com>,
	"Christophe Leroy" <christophe.leroy@csgroup.eu>,
	"Arnd Bergmann" <arnd@arndb.de>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Jerrin Shaji George" <jerrin.shaji-george@broadcom.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	"Jason Wang" <jasowang@redhat.com>,
	"Xuan Zhuo" <xuanzhuo@linux.alibaba.com>,
	"Eugenio Pérez" <eperezma@redhat.com>, "Zi Yan" <ziy@nvidia.com>
Subject: [PATCH v2 08/23] mm/balloon_compaction: remove dependency on page lock
Date: Thu, 15 Jan 2026 10:19:58 +0100	[thread overview]
Message-ID: <20260115092015.3928975-9-david@kernel.org> (raw)
In-Reply-To: <20260115092015.3928975-1-david@kernel.org>

Let's stop using the page lock in balloon code and instead use only the
balloon_device_lock.

As soon as we set the PG_movable_ops flag, we might now get isolation
callbacks for that page as we are no longer holding the page lock. In
there, we'll simply synchronize using the balloon_device_lock.

So in balloon_page_isolate() lookup the balloon_dev_info through
page->private under balloon_device_lock.

It's crucial that we update page->private under the balloon_device_lock,
so the isolation callback can properly deal with concurrent deflation.

Consequently, make sure that balloon_page_finalize() is called under
balloon_device_lock as we remove a page from the list and clear
page->private. balloon_page_insert() is already called with the
balloon_device_lock held.

Note that the core will still lock the pages, for example in
isolate_movable_ops_page(). The lock is there still relevant for
handling the PageMovableOpsIsolated flag, but that can be later changed
to use an atomic test-and-set instead, or moved into the movable_ops
backends.

Signed-off-by: David Hildenbrand (Red Hat) <david@kernel.org>
---
 include/linux/balloon_compaction.h | 25 ++++++++++----------
 mm/balloon_compaction.c            | 38 ++++++++++--------------------
 2 files changed, 25 insertions(+), 38 deletions(-)

diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
index 9a8568fcd477d..ad594af6ed100 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -12,25 +12,27 @@
  * is derived from the page type (PageOffline()) combined with the
  * PG_movable_ops flag (PageMovableOps()).
  *
+ * Once the page type and the PG_movable_ops are set, migration code
+ * can initiate page isolation by invoking the
+ * movable_operations()->isolate_page() callback
+ *
+ * As long as page->private is set, the page is either on the balloon list
+ * or isolated for migration. If page->private is not set, the page is
+ * either still getting inflated, or was deflated to be freed by the balloon
+ * driver soon. Isolation is impossible in both cases.
+ *
  * As the page isolation scanning step a compaction thread does is a lockless
  * procedure (from a page standpoint), it might bring some racy situations while
  * performing balloon page compaction. In order to sort out these racy scenarios
  * and safely perform balloon's page compaction and migration we must, always,
  * ensure following these simple rules:
  *
- *   i. Setting the PG_movable_ops flag and page->private with the following
- *	lock order
- *	    +-page_lock(page);
- *	      +--spin_lock_irq(&balloon_pages_lock);
+ *   i. Inflation/deflation must set/clear page->private under the
+ *      balloon_pages_lock
  *
  *  ii. isolation or dequeueing procedure must remove the page from balloon
  *      device page list under balloon_pages_lock
  *
- * The functions provided by this interface are placed to help on coping with
- * the aforementioned balloon page corner case, as well as to ensure the simple
- * set of exposed rules are satisfied while we are dealing with balloon pages
- * compaction / migration.
- *
  * Copyright (C) 2012, Red Hat, Inc.  Rafael Aquini <aquini@redhat.com>
  */
 #ifndef _LINUX_BALLOON_COMPACTION_H
@@ -93,8 +95,7 @@ static inline struct balloon_dev_info *balloon_page_device(struct page *page)
  * @balloon : pointer to balloon device
  * @page    : page to be assigned as a 'balloon page'
  *
- * Caller must ensure the page is locked and the spin_lock protecting balloon
- * pages list is held before inserting a page into the balloon device.
+ * Caller must ensure the balloon_pages_lock is held.
  */
 static inline void balloon_page_insert(struct balloon_dev_info *balloon,
 				       struct page *page)
@@ -119,7 +120,7 @@ static inline gfp_t balloon_mapping_gfp_mask(void)
  *			   balloon list for release to the page allocator
  * @page: page to be released to the page allocator
  *
- * Caller must ensure that the page is locked.
+ * Caller must ensure the balloon_pages_lock is held.
  */
 static inline void balloon_page_finalize(struct page *page)
 {
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index 97e838795354d..28ef0cb6b3bbc 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -20,15 +20,7 @@ static DEFINE_SPINLOCK(balloon_pages_lock);
 static void balloon_page_enqueue_one(struct balloon_dev_info *b_dev_info,
 				     struct page *page)
 {
-	/*
-	 * Block others from accessing the 'page' when we get around to
-	 * establishing additional references. We should be the only one
-	 * holding a reference to the 'page' at this point. If we are not, then
-	 * memory corruption is possible and we should stop execution.
-	 */
-	BUG_ON(!trylock_page(page));
 	balloon_page_insert(b_dev_info, page);
-	unlock_page(page);
 	if (b_dev_info->adjust_managed_page_count)
 		adjust_managed_page_count(page, -1);
 	__count_vm_event(BALLOON_INFLATE);
@@ -93,22 +85,12 @@ size_t balloon_page_list_dequeue(struct balloon_dev_info *b_dev_info,
 	list_for_each_entry_safe(page, tmp, &b_dev_info->pages, lru) {
 		if (n_pages == n_req_pages)
 			break;
-
-		/*
-		 * Block others from accessing the 'page' while we get around to
-		 * establishing additional references and preparing the 'page'
-		 * to be released by the balloon driver.
-		 */
-		if (!trylock_page(page))
-			continue;
-
 		list_del(&page->lru);
 		if (b_dev_info->adjust_managed_page_count)
 			adjust_managed_page_count(page, 1);
 		balloon_page_finalize(page);
 		__count_vm_event(BALLOON_DEFLATE);
 		list_add(&page->lru, pages);
-		unlock_page(page);
 		dec_node_page_state(page, NR_BALLOON_PAGES);
 		n_pages++;
 	}
@@ -213,13 +195,19 @@ EXPORT_SYMBOL_GPL(balloon_page_dequeue);
 static bool balloon_page_isolate(struct page *page, isolate_mode_t mode)
 
 {
-	struct balloon_dev_info *b_dev_info = balloon_page_device(page);
+	struct balloon_dev_info *b_dev_info;
 	unsigned long flags;
 
-	if (!b_dev_info)
-		return false;
-
 	spin_lock_irqsave(&balloon_pages_lock, flags);
+	b_dev_info = balloon_page_device(page);
+	if (!b_dev_info) {
+		/*
+		 * The page already got deflated and removed from the
+		 * balloon list.
+		 */
+		spin_unlock_irqrestore(&balloon_pages_lock, flags);
+		return false;
+	}
 	list_del(&page->lru);
 	b_dev_info->isolated_pages++;
 	spin_unlock_irqrestore(&balloon_pages_lock, flags);
@@ -249,9 +237,6 @@ static int balloon_page_migrate(struct page *newpage, struct page *page,
 	unsigned long flags;
 	int rc;
 
-	VM_BUG_ON_PAGE(!PageLocked(page), page);
-	VM_BUG_ON_PAGE(!PageLocked(newpage), newpage);
-
 	/* Isolated balloon pages cannot get deflated. */
 	if (WARN_ON_ONCE(!b_dev_info))
 		return -EAGAIN;
@@ -291,10 +276,11 @@ static int balloon_page_migrate(struct page *newpage, struct page *page,
 	}
 
 	b_dev_info->isolated_pages--;
-	spin_unlock_irqrestore(&balloon_pages_lock, flags);
 
 	/* Free the now-deflated page we isolated in balloon_page_isolate(). */
 	balloon_page_finalize(page);
+	spin_unlock_irqrestore(&balloon_pages_lock, flags);
+
 	put_page(page);
 
 	return 0;
-- 
2.52.0


  parent reply	other threads:[~2026-01-15  9:21 UTC|newest]

Thread overview: 65+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-01-15  9:19 [PATCH v2 00/23] mm: balloon infrastructure cleanups David Hildenbrand (Red Hat)
2026-01-15  9:19 ` [PATCH v2 01/23] vmw_balloon: adjust BALLOON_DEFLATE when deflating while migrating David Hildenbrand (Red Hat)
2026-01-15  9:56   ` Lorenzo Stoakes
2026-01-15  9:19 ` [PATCH v2 02/23] vmw_balloon: remove vmballoon_compaction_init() David Hildenbrand (Red Hat)
2026-01-15 11:20   ` Lorenzo Stoakes
2026-01-15  9:19 ` [PATCH v2 03/23] powerpc/pseries/cmm: remove cmm_balloon_compaction_init() David Hildenbrand (Red Hat)
2026-01-15 11:46   ` Lorenzo Stoakes
2026-01-19 22:44     ` David Hildenbrand (Red Hat)
2026-01-15  9:19 ` [PATCH v2 04/23] mm/balloon_compaction: centralize basic page migration handling David Hildenbrand (Red Hat)
2026-01-15 12:18   ` Lorenzo Stoakes
2026-01-15 12:57     ` David Hildenbrand (Red Hat)
2026-01-19 22:22   ` David Hildenbrand (Red Hat)
2026-01-19 22:25     ` David Hildenbrand (Red Hat)
2026-01-15  9:19 ` [PATCH v2 05/23] mm/balloon_compaction: centralize adjust_managed_page_count() handling David Hildenbrand (Red Hat)
2026-01-15 14:06   ` Liam R. Howlett
2026-01-15  9:19 ` [PATCH v2 06/23] vmw_balloon: stop using the balloon_dev_info lock David Hildenbrand (Red Hat)
2026-01-15 12:21   ` Lorenzo Stoakes
2026-01-15 12:26     ` David Hildenbrand (Red Hat)
2026-01-15  9:19 ` [PATCH v2 07/23] mm/balloon_compaction: use a device-independent balloon (list) lock David Hildenbrand (Red Hat)
2026-01-15  9:19 ` David Hildenbrand (Red Hat) [this message]
2026-01-15  9:19 ` [PATCH v2 09/23] mm/balloon_compaction: make balloon_mops static David Hildenbrand (Red Hat)
2026-01-15 12:22   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 10/23] mm/balloon_compaction: drop fs.h include from balloon_compaction.h David Hildenbrand (Red Hat)
2026-01-15 12:25   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 11/23] drivers/virtio/virtio_balloon: stop using balloon_page_push/pop() David Hildenbrand (Red Hat)
2026-01-15 12:28   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 12/23] mm/balloon_compaction: remove balloon_page_push/pop() David Hildenbrand (Red Hat)
2026-01-15 12:29   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 13/23] mm/balloon_compaction: fold balloon_mapping_gfp_mask() into balloon_page_alloc() David Hildenbrand (Red Hat)
2026-01-15 12:30   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 14/23] mm/balloon_compaction: move internal helpers to balloon_compaction.c David Hildenbrand (Red Hat)
2026-01-15 12:32   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 15/23] mm/balloon_compaction: assert that the balloon_pages_lock is held David Hildenbrand (Red Hat)
2026-01-15 12:32   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 16/23] mm/balloon_compaction: mark remaining functions for having proper kerneldoc David Hildenbrand (Red Hat)
2026-01-15 12:33   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 17/23] mm/balloon_compaction: remove "extern" from functions David Hildenbrand (Red Hat)
2026-01-15 12:34   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 18/23] mm/vmscan: drop inclusion of balloon_compaction.h David Hildenbrand (Red Hat)
2026-01-15 13:42   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 19/23] mm: rename balloon_compaction.(c|h) to balloon.(c|h) David Hildenbrand (Red Hat)
2026-01-15 13:45   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 20/23] mm/kconfig: make BALLOON_COMPACTION depend on MIGRATION David Hildenbrand (Red Hat)
2026-01-15 13:47   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 21/23] mm: rename CONFIG_BALLOON_COMPACTION to CONFIG_BALLOON_MIGRATION David Hildenbrand (Red Hat)
2026-01-15 13:52   ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 22/23] mm: rename CONFIG_MEMORY_BALLOON -> CONFIG_BALLOON David Hildenbrand (Red Hat)
2026-01-15 13:55   ` Lorenzo Stoakes
2026-01-15 16:33     ` David Hildenbrand (Red Hat)
2026-01-15 16:50       ` Michael S. Tsirkin
2026-01-15 16:53       ` Michael S. Tsirkin
2026-01-15 16:56         ` David Hildenbrand (Red Hat)
2026-01-15 16:57       ` Lorenzo Stoakes
2026-01-15  9:20 ` [PATCH v2 23/23] MAINTAINERS: move memory balloon infrastructure to "MEMORY MANAGEMENT - BALLOON" David Hildenbrand (Red Hat)
2026-01-15  9:32   ` Michael S. Tsirkin
2026-01-15 11:21     ` David Hildenbrand (Red Hat)
2026-01-15  9:38   ` Lance Yang
2026-01-15 11:22     ` David Hildenbrand (Red Hat)
2026-01-15  9:39   ` Lorenzo Stoakes
2026-01-15 11:25     ` David Hildenbrand (Red Hat)
2026-01-15 12:01       ` Vlastimil Babka
2026-01-15  9:32 ` [PATCH v2 00/23] mm: balloon infrastructure cleanups Michael S. Tsirkin
2026-01-15 11:26   ` David Hildenbrand (Red Hat)
2026-01-15 18:49 ` Andrew Morton
2026-01-15 19:47   ` David Hildenbrand (Red Hat)

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260115092015.3928975-9-david@kernel.org \
    --to=david@kernel.org \
    --cc=Liam.Howlett@oracle.com \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=bcm-kernel-feedback-list@broadcom.com \
    --cc=christophe.leroy@csgroup.eu \
    --cc=corbet@lwn.net \
    --cc=eperezma@redhat.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jasowang@redhat.com \
    --cc=jerrin.shaji-george@broadcom.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=lorenzo.stoakes@oracle.com \
    --cc=maddy@linux.ibm.com \
    --cc=mhocko@suse.com \
    --cc=mpe@ellerman.id.au \
    --cc=mst@redhat.com \
    --cc=npiggin@gmail.com \
    --cc=osalvador@suse.de \
    --cc=rppt@kernel.org \
    --cc=surenb@google.com \
    --cc=vbabka@suse.cz \
    --cc=virtualization@lists.linux.dev \
    --cc=xuanzhuo@linux.alibaba.com \
    --cc=ziy@nvidia.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.