[Devel] [PATCH RH7] memcg/kmem: don't show fake charge in usage and limits

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Thu Jul 23 12:54:40 MSK 2020


We've faced a problem with docker/containerd cgroups configuration code.
It does write 1(-1) to memory.kmem.limit_in_bytes of newly created
memory cgroup as a verification check that memory cgroup works (we've
already made a pull request to containerd to remove this strange check).
We have a fake charge of one page in each memory cgroup, so setting
limit to 1 returns EBUSY because limit < usage.

Let's add one page when updating kmem limit so that our fake charge does
not implicitly reduce the limit and then showing kmem limit we will
remove this fake page and show what was set originally.

Note: now when setting -1 to kmem limit it will convert to real pages
limit of PAGE_COUNTER_MAX+1, it looks like there is nothing bad in it,
but save it here for history.

Let's also remove one page when showing kmem usage and max usage, to
maintain consistency between limits and usage.

https://jira.sw.ru/browse/PSBM-106065

Co-Developed-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 mm/memcontrol.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index fa7b2cad93ad..9570e9d8487f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -4767,14 +4767,24 @@ static ssize_t mem_cgroup_read(struct cgroup *cont, struct cftype *cft,
 			val = (u64)mem_cgroup_usage(memcg, false) * PAGE_SIZE;
 		else if (counter == &memcg->memsw)
 			val = (u64)mem_cgroup_usage(memcg, true) * PAGE_SIZE;
+		else if (counter == &memcg->kmem)
+			 /* remove fake charge, see __memcg_activate_kmem() */
+			val = (u64)(page_counter_read(counter) - 1) * PAGE_SIZE;
 		else
 			val = (u64)page_counter_read(counter) * PAGE_SIZE;
 		break;
 	case RES_LIMIT:
-		val = (u64)counter->limit * PAGE_SIZE;
+		if (counter == &memcg->kmem)
+			/* remove fake charge from kmem limit, see __memcg_activate_kmem() */
+			val = (u64)(counter->limit - 1) * PAGE_SIZE;
+		else
+			val = (u64)counter->limit * PAGE_SIZE;
 		break;
 	case RES_MAX_USAGE:
 		val = (u64)counter->watermark * PAGE_SIZE;
+		 if (counter == &memcg->kmem)
+			 /* remove fake charge, see __memcg_activate_kmem() */
+			 val -= PAGE_SIZE;
 		break;
 	case RES_FAILCNT:
 		val = (u64)counter->failcnt;
@@ -4907,6 +4917,9 @@ static int memcg_update_kmem_limit(struct mem_cgroup *memcg,
 {
 	int ret;
 
+	/* add fake charge to kmem limit, see __memcg_activate_kmem() */
+	nr_pages++;
+
 	mutex_lock(&memcg_limit_mutex);
 	if (!memcg_kmem_is_active(memcg))
 		ret = memcg_activate_kmem(memcg, nr_pages);
-- 
2.24.1



More information about the Devel mailing list