diff --git a/include/linux/swap.h b/include/linux/swap.h
index fec6647a289a..f768171c2dc2 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -416,6 +416,12 @@ extern unsigned long try_to_free_pages(struct zonelist *zonelist, int order,

 #define MEMCG_RECLAIM_MAY_SWAP (1 << 1)
 #define MEMCG_RECLAIM_PROACTIVE (1 << 2)
+#define MEMCG_RECLAIM_MAY_DEMOTE (1 << 3)
+#define MEMCG_RECLAIM_ONLY_DEMOTE (1 << 4)
+#define MEMCG_RECLAIM_DEFAULT \
+	(MEMCG_RECLAIM_MAY_SWAP | MEMCG_RECLAIM_MAY_DEMOTE)
+#define MEMCG_RECLAIM_NO_SWAP (MEMCG_RECLAIM_DEFAULT & ~MEMCG_RECLAIM_MAY_SWAP)
+
 extern unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
 						  unsigned long nr_pages,
 						  gfp_t gfp_mask,
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index f412c903ee4f..fd4ff1c865a2 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -2392,7 +2392,7 @@ static unsigned long reclaim_high(struct mem_cgroup *memcg,
 		psi_memstall_enter(&pflags);
 		nr_reclaimed += try_to_free_mem_cgroup_pages(memcg, nr_pages,
 							gfp_mask,
-							MEMCG_RECLAIM_MAY_SWAP);
+							MEMCG_RECLAIM_DEFAULT);
 		psi_memstall_leave(&pflags);
 	} while ((memcg = parent_mem_cgroup(memcg)) &&
 		 !mem_cgroup_is_root(memcg));
@@ -2637,7 +2637,7 @@ static int try_charge_memcg(struct mem_cgroup *memcg, gfp_t gfp_mask,
 	struct page_counter *counter;
 	unsigned long nr_reclaimed;
 	bool passed_oom = false;
-	unsigned int reclaim_options = MEMCG_RECLAIM_MAY_SWAP;
+	unsigned int reclaim_options = MEMCG_RECLAIM_DEFAULT;
 	bool drained = false;
 	bool raised_max_event = false;
 	unsigned long pflags;
@@ -3503,7 +3503,8 @@ static int mem_cgroup_resize_max(struct mem_cgroup *memcg,
 		}

 		if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL,
-					memsw ? 0 : MEMCG_RECLAIM_MAY_SWAP)) {
+					memsw ? MEMCG_RECLAIM_NO_SWAP :
+						MEMCG_RECLAIM_DEFAULT)) {
 			ret = -EBUSY;
 			break;
 		}
@@ -3614,7 +3615,7 @@ static int mem_cgroup_force_empty(struct mem_cgroup *memcg)
 			return -EINTR;

 		if (!try_to_free_mem_cgroup_pages(memcg, 1, GFP_KERNEL,
-						  MEMCG_RECLAIM_MAY_SWAP))
+						  MEMCG_RECLAIM_DEFAULT))
 			nr_retries--;
 	}

@@ -6407,7 +6408,7 @@ static ssize_t memory_high_write(struct kernfs_open_file *of,
 		}

 		reclaimed = try_to_free_mem_cgroup_pages(memcg, nr_pages - high,
-					GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP);
+					GFP_KERNEL, MEMCG_RECLAIM_DEFAULT);

 		if (!reclaimed && !nr_retries--)
 			break;
@@ -6456,7 +6457,7 @@ static ssize_t memory_max_write(struct kernfs_open_file *of,

 		if (nr_reclaims) {
 			if (!try_to_free_mem_cgroup_pages(memcg, nr_pages - max,
-					GFP_KERNEL, MEMCG_RECLAIM_MAY_SWAP))
+					GFP_KERNEL, MEMCG_RECLAIM_DEFAULT))
 				nr_reclaims--;
 			continue;
 		}
@@ -6593,7 +6594,8 @@ static ssize_t memory_reclaim(struct kernfs_open_file *of, char *buf,
 	if (err)
 		return err;

-	reclaim_options	= MEMCG_RECLAIM_MAY_SWAP | MEMCG_RECLAIM_PROACTIVE;
+	reclaim_options = MEMCG_RECLAIM_DEFAULT | MEMCG_RECLAIM_PROACTIVE;
+	reclaim_options &= ~MEMCG_RECLAIM_MAY_DEMOTE;
 	while (nr_reclaimed < nr_to_reclaim) {
 		unsigned long reclaimed;

diff --git a/mm/vmscan.c b/mm/vmscan.c
index d8751e403599..dea05ad8ece5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -132,8 +132,14 @@ struct scan_control {
 	/* The file folios on the current node are dangerously low */
 	unsigned int file_is_tiny:1;

-	/* Always discard instead of demoting to lower tier memory */
-	unsigned int no_demotion:1;
+	/*
+	 * Configure discard instead of demoting to lower tier memory:
+	 *
+	 * demotion = 0 -> no demotion
+	 * demotion = 1 -> may demote
+	 * demotion = 2 -> only demote
+	 */
+	unsigned int demotion;

 #ifdef CONFIG_LRU_GEN
 	/* help kswapd make better choices among multiple memcgs */
@@ -542,7 +548,7 @@ static bool can_demote(int nid, struct scan_control *sc)
 {
 	if (!numa_demotion_enabled)
 		return false;
-	if (sc && sc->no_demotion)
+	if (sc && !sc->demotion)
 		return false;
 	if (next_demotion_node(nid) == NUMA_NO_NODE)
 		return false;
@@ -2674,7 +2680,7 @@ static unsigned int reclaim_folio_list(struct list_head *folio_list,
 		.may_writepage = 1,
 		.may_unmap = 1,
 		.may_swap = 1,
-		.no_demotion = 1,
+		.demotion = 0,
 	};

 	nr_reclaimed = shrink_folio_list(folio_list, pgdat, &sc, &dummy_stat, false);
@@ -6726,6 +6732,13 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
 	 */
 	struct zonelist *zonelist = node_zonelist(numa_node_id(), sc.gfp_mask);

+	if (reclaim_options & MEMCG_RECLAIM_ONLY_DEMOTE)
+		sc.demotion = 2;
+	else if (reclaim_options & MEMCG_RECLAIM_MAY_DEMOTE)
+		sc.demotion = 1;
+	else
+		sc.demotion = 0;
+
 	set_task_reclaim_state(current, &sc.reclaim_state);
 	trace_mm_vmscan_memcg_reclaim_begin(0, sc.gfp_mask);
 	noreclaim_flag = memalloc_noreclaim_save();
