From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6AFE9C3DA4A for ; Fri, 9 Aug 2024 12:29:47 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 034F26B008C; Fri, 9 Aug 2024 08:29:47 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id F25D36B0092; Fri, 9 Aug 2024 08:29:46 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id DEDD76B0095; Fri, 9 Aug 2024 08:29:46 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0012.hostedemail.com [216.40.44.12]) by kanga.kvack.org (Postfix) with ESMTP id C05176B008C for ; Fri, 9 Aug 2024 08:29:46 -0400 (EDT) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 6F547140E7A for ; Fri, 9 Aug 2024 12:29:46 +0000 (UTC) X-FDA: 82432638372.25.C8746D0 Received: from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255]) by imf17.hostedemail.com (Postfix) with ESMTP id D064540027 for ; Fri, 9 Aug 2024 12:29:42 +0000 (UTC) Authentication-Results: imf17.hostedemail.com; dkim=none; spf=pass (imf17.hostedemail.com: domain of linyunsheng@huawei.com designates 45.249.212.255 as permitted sender) smtp.mailfrom=linyunsheng@huawei.com; dmarc=pass (policy=quarantine) header.from=huawei.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1723206552; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jziwBibNizqYEOMZWNND7x7PeMptFtg0juDHweXDW38=; b=tPAsVSKOzrkZWxJUcthq/DP/1XwD/eyF+2zyKbGVIx6Duekpcf7kXKLLuykKN2JmecbsAJ n92/AptFGWZoS8hz4RkuzRhoY4f1hPAAYZkyqQ1lXlpGtpamYgkn6oKnV+xtVGv5nXvcrv M051P8ND6tuaKKwK6ytY7it4mqSq/nY= ARC-Authentication-Results: i=1; imf17.hostedemail.com; dkim=none; spf=pass (imf17.hostedemail.com: domain of linyunsheng@huawei.com designates 45.249.212.255 as permitted sender) smtp.mailfrom=linyunsheng@huawei.com; dmarc=pass (policy=quarantine) header.from=huawei.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1723206552; a=rsa-sha256; cv=none; b=kIfRf99BQqa9vziYyYAPZzKx2CedyMYoilSj8GSlONxlpFJ44G1q3f/zA2P6eXXcgqskCk UDTspGsuUHXSC6xOvRZwrhWDbKIZl5UeyLZ/cCNbhIi6sw3SGFK2m7quk+w3pi/K+9oHuO meaRMT5IlsxTAvQwAVWGIA0BFP9+2d4= Received: from mail.maildlp.com (unknown [172.19.163.174]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4WgNWZ4mMnz1T6t6; Fri, 9 Aug 2024 20:29:14 +0800 (CST) Received: from dggpemf200006.china.huawei.com (unknown [7.185.36.61]) by mail.maildlp.com (Postfix) with ESMTPS id E4DEB140121; Fri, 9 Aug 2024 20:29:37 +0800 (CST) Received: from [10.67.120.129] (10.67.120.129) by dggpemf200006.china.huawei.com (7.185.36.61) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.11; Fri, 9 Aug 2024 20:29:37 +0800 Message-ID: Date: Fri, 9 Aug 2024 20:29:37 +0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH net-next v13 01/14] mm: page_frag: add a test module for page_frag To: Muhammad Usama Anjum , , , CC: , , Alexander Duyck , Andrew Morton , Shuah Khan , , References: <20240808123714.462740-1-linyunsheng@huawei.com> <20240808123714.462740-2-linyunsheng@huawei.com> <0ec39cb0-5213-4468-8e61-2fc349531ae3@collabora.com> Content-Language: en-US From: Yunsheng Lin In-Reply-To: <0ec39cb0-5213-4468-8e61-2fc349531ae3@collabora.com> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Originating-IP: [10.67.120.129] X-ClientProxiedBy: dggems704-chm.china.huawei.com (10.3.19.181) To dggpemf200006.china.huawei.com (7.185.36.61) X-Rspamd-Server: rspam03 X-Rspam-User: X-Rspamd-Queue-Id: D064540027 X-Stat-Signature: eenbtbjfe44kipw53ugjzj61xs1mkufg X-HE-Tag: 1723206582-815832 X-HE-Meta: U2FsdGVkX189S6oY4wsGVbTdEaPNN5X7vtRdi8aJkcqUvdbnFk154JEr32hM9omxK0uisUOWuo+9cMWB1A6u+4+hLUY8uMlrAcJaIl8LjBE3BWgNdIKQc/hYsjK4xIkmYWBrtnfGVBbwuvwtwe/a99+R0Xhcxj2uD1wwh5wcIrlCJ8ayzabA9F7UTcvH0cVe3H6obsVtTftsKBgWEiIiMv3WS1lrtU2uLwlxK5USnQZjWdOQxI0MHwioaYrBE2z4cS059HDRoD8rLCo/yYx+8M5phD9Fb51es+0wuQUbfIHZzO35V/7MnGnZvwEZrQDzJy6WelscxrbAfnacz59a1SuTeQKYThl4V/+Jw9Imt1VFPJ5kp91XlB3Gfe9JmLXrcC2lm5pJK5gBs7VTtqbyh9K3b3hbYYpWjDKFEoJYJGCCutCSVzft3iwjCAUW6INWTzi9sxLHykpuMmEAFV7RAkGme/9vIazd4x19iTgM5QPm3ks0U7frc2lwqJA6fl8vhfS5apewi/I5nE/KpsB/MSEP18wfk0sQFLKfi598qua0o4aPNgwxBjGyE554ilniCNCDT0eXcpItCJaYN0bBR3ObWrhcqyP1VYkEc++kpBfjfVV+kLrGZllGPHq5tHh7yJE2JDMg4h6EbY+xKA4WNXFdQYrnvEtVXsxk8UwFrKhc+NcZAoQSzuzvDjWvlZzGNRgBxv2cWstoKmAhsnEK9VCDmnk7/5oSHZQMARKQjGEvD4o+TL5FTvse1503d6OHkAtGrBELsvs8gEIa9zGppm78ojw5n8m6SGRh8JDSMW56VQ15saJyplGP1JmElNHMyZF20qFoqx9nY+wc4wDZy3ena9ONDxhDuqa/BY54GaIhStG1d1LiBRB69IqTTz5ej50yaisGHbCxuJCgYE/9qy49EDAmfroXDR34LTm6pWt+r3btUFXuAI32p2YRP++mDRpVQsIReeKUKmB/sns A1PkvNKK ZRdeXYtvejREqV/SzxC+e8vSbjyVzPTUK579CAuFI6t2+drdl/T+Rs6d0pCTMe2I0yFeJMzZ+KlvCoQaipTrvuR4JsupObhDEhQ2YlxznXO4L8+8fX5ckVjsF/VpabDjIzeCExUzyFkVP/R0Cx7rsT3L5H3KYEG+jZAJR6VXqzibpJClYwUhGOKyaeoLnUu2vP/7X3NJkw8yWlFVsgnbIngmTzmcuhbwAlnGgDx6JArFk2AgkMWGGPSYHEH/3KAs+GxySBH3ITSG1KO3MHZVwEGiGMhzuZZUbErawrffYVRE8BcZM1SHecGV4HCZftW7rGMnb9CtXyv2Ggh0t2DIOVKHj6tD1p42zvlqo58NRpG93P75MjBkp9ZwLS6JnfWuW43xJOEu3S5v+IOA= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: On 2024/8/9 19:08, Muhammad Usama Anjum wrote: > On 8/8/24 5:37 PM, Yunsheng Lin wrote: >> The testing is done by ensuring that the fragment allocated >> from a frag_frag_cache instance is pushed into a ptr_ring >> instance in a kthread binded to a specified cpu, and a kthread >> binded to a specified cpu will pop the fragment from the >> ptr_ring and free the fragment. >> >> CC: Alexander Duyck >> Signed-off-by: Yunsheng Lin >> --- >> tools/testing/selftests/mm/Makefile | 2 + >> tools/testing/selftests/mm/page_frag/Makefile | 18 ++ >> .../selftests/mm/page_frag/page_frag_test.c | 170 ++++++++++++++++++ > Why are you adding a test module in kselftests? Have you considered > adding Kunit instead? Kunit is more suited to test kernel's internal > APIs which aren't exposed to userspace. The main intent is to do performance impact of changing related to page_frag, which is very much performance sensitive, so I am guessing Kunit is not a right choice here if I am understanding it correctly. > >> tools/testing/selftests/mm/run_vmtests.sh | 9 +- >> 4 files changed, 198 insertions(+), 1 deletion(-) >> create mode 100644 tools/testing/selftests/mm/page_frag/Makefile >> create mode 100644 tools/testing/selftests/mm/page_frag/page_frag_test.c >> >> diff --git a/tools/testing/selftests/mm/Makefile b/tools/testing/selftests/mm/Makefile >> index 901e0d07765b..e91ed29378fc 100644 >> --- a/tools/testing/selftests/mm/Makefile >> +++ b/tools/testing/selftests/mm/Makefile >> @@ -36,6 +36,8 @@ MAKEFLAGS += --no-builtin-rules >> CFLAGS = -Wall -I $(top_srcdir) $(EXTRA_CFLAGS) $(KHDR_INCLUDES) $(TOOLS_INCLUDES) >> LDLIBS = -lrt -lpthread -lm >> >> +TEST_GEN_MODS_DIR := page_frag >> + >> TEST_GEN_FILES = cow >> TEST_GEN_FILES += compaction_test >> TEST_GEN_FILES += gup_longterm >> diff --git a/tools/testing/selftests/mm/page_frag/Makefile b/tools/testing/selftests/mm/page_frag/Makefile >> new file mode 100644 >> index 000000000000..58dda74d50a3 >> --- /dev/null >> +++ b/tools/testing/selftests/mm/page_frag/Makefile >> @@ -0,0 +1,18 @@ >> +PAGE_FRAG_TEST_DIR := $(realpath $(dir $(abspath $(lastword $(MAKEFILE_LIST))))) >> +KDIR ?= $(abspath $(PAGE_FRAG_TEST_DIR)/../../../../..) >> + >> +ifeq ($(V),1) >> +Q = >> +else >> +Q = @ >> +endif >> + >> +MODULES = page_frag_test.ko >> + >> +obj-m += page_frag_test.o >> + >> +all: >> + +$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) modules >> + >> +clean: >> + +$(Q)make -C $(KDIR) M=$(PAGE_FRAG_TEST_DIR) clean >> diff --git a/tools/testing/selftests/mm/page_frag/page_frag_test.c b/tools/testing/selftests/mm/page_frag/page_frag_test.c >> new file mode 100644 >> index 000000000000..0e803db1ad79 >> --- /dev/null >> +++ b/tools/testing/selftests/mm/page_frag/page_frag_test.c >> @@ -0,0 +1,170 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> + >> +/* >> + * Test module for page_frag cache >> + * >> + * Copyright: linyunsheng@huawei.com >> + */ >> + >> +#include >> +#include >> +#include >> +#include >> +#include >> +#include >> + >> +static struct ptr_ring ptr_ring; >> +static int nr_objs = 512; >> +static atomic_t nthreads; >> +static struct completion wait; >> +static struct page_frag_cache test_frag; >> + >> +static int nr_test = 5120000; >> +module_param(nr_test, int, 0); >> +MODULE_PARM_DESC(nr_test, "number of iterations to test"); >> + >> +static bool test_align; >> +module_param(test_align, bool, 0); >> +MODULE_PARM_DESC(test_align, "use align API for testing"); >> + >> +static int test_alloc_len = 2048; >> +module_param(test_alloc_len, int, 0); >> +MODULE_PARM_DESC(test_alloc_len, "alloc len for testing"); >> + >> +static int test_push_cpu; >> +module_param(test_push_cpu, int, 0); >> +MODULE_PARM_DESC(test_push_cpu, "test cpu for pushing fragment"); >> + >> +static int test_pop_cpu; >> +module_param(test_pop_cpu, int, 0); >> +MODULE_PARM_DESC(test_pop_cpu, "test cpu for popping fragment"); >> + >> +static int page_frag_pop_thread(void *arg) >> +{ >> + struct ptr_ring *ring = arg; >> + int nr = nr_test; >> + >> + pr_info("page_frag pop test thread begins on cpu %d\n", >> + smp_processor_id()); >> + >> + while (nr > 0) { >> + void *obj = __ptr_ring_consume(ring); >> + >> + if (obj) { >> + nr--; >> + page_frag_free(obj); >> + } else { >> + cond_resched(); >> + } >> + } >> + >> + if (atomic_dec_and_test(&nthreads)) >> + complete(&wait); >> + >> + pr_info("page_frag pop test thread exits on cpu %d\n", >> + smp_processor_id()); >> + >> + return 0; >> +} >> + >> +static int page_frag_push_thread(void *arg) >> +{ >> + struct ptr_ring *ring = arg; >> + int nr = nr_test; >> + >> + pr_info("page_frag push test thread begins on cpu %d\n", >> + smp_processor_id()); >> + >> + while (nr > 0) { >> + void *va; >> + int ret; >> + >> + if (test_align) { >> + va = page_frag_alloc_align(&test_frag, test_alloc_len, >> + GFP_KERNEL, SMP_CACHE_BYTES); >> + >> + WARN_ONCE((unsigned long)va & (SMP_CACHE_BYTES - 1), >> + "unaligned va returned\n"); >> + } else { >> + va = page_frag_alloc(&test_frag, test_alloc_len, GFP_KERNEL); >> + } >> + >> + if (!va) >> + continue; >> + >> + ret = __ptr_ring_produce(ring, va); >> + if (ret) { >> + page_frag_free(va); >> + cond_resched(); >> + } else { >> + nr--; >> + } >> + } >> + >> + pr_info("page_frag push test thread exits on cpu %d\n", >> + smp_processor_id()); >> + >> + if (atomic_dec_and_test(&nthreads)) >> + complete(&wait); >> + >> + return 0; >> +} >> + >> +static int __init page_frag_test_init(void) >> +{ >> + struct task_struct *tsk_push, *tsk_pop; >> + ktime_t start; >> + u64 duration; >> + int ret; >> + >> + test_frag.va = NULL; >> + atomic_set(&nthreads, 2); >> + init_completion(&wait); >> + >> + if (test_alloc_len > PAGE_SIZE || test_alloc_len <= 0 || >> + !cpu_active(test_push_cpu) || !cpu_active(test_pop_cpu)) >> + return -EINVAL; >> + >> + ret = ptr_ring_init(&ptr_ring, nr_objs, GFP_KERNEL); >> + if (ret) >> + return ret; >> + >> + tsk_push = kthread_create_on_cpu(page_frag_push_thread, &ptr_ring, >> + test_push_cpu, "page_frag_push"); >> + if (IS_ERR(tsk_push)) >> + return PTR_ERR(tsk_push); >> + >> + tsk_pop = kthread_create_on_cpu(page_frag_pop_thread, &ptr_ring, >> + test_pop_cpu, "page_frag_pop"); >> + if (IS_ERR(tsk_pop)) { >> + kthread_stop(tsk_push); >> + return PTR_ERR(tsk_pop); >> + } >> + >> + start = ktime_get(); >> + wake_up_process(tsk_push); >> + wake_up_process(tsk_pop); >> + >> + pr_info("waiting for test to complete\n"); >> + wait_for_completion(&wait); >> + >> + duration = (u64)ktime_us_delta(ktime_get(), start); >> + pr_info("%d of iterations for %s testing took: %lluus\n", nr_test, >> + test_align ? "aligned" : "non-aligned", duration); >> + >> + ptr_ring_cleanup(&ptr_ring, NULL); >> + page_frag_cache_drain(&test_frag); >> + >> + return -EAGAIN; >> +} >> + >> +static void __exit page_frag_test_exit(void) >> +{ >> +} >> + >> +module_init(page_frag_test_init); >> +module_exit(page_frag_test_exit); >> + >> +MODULE_LICENSE("GPL"); >> +MODULE_AUTHOR("Yunsheng Lin "); >> +MODULE_DESCRIPTION("Test module for page_frag"); >> diff --git a/tools/testing/selftests/mm/run_vmtests.sh b/tools/testing/selftests/mm/run_vmtests.sh >> index 03ac4f2e1cce..3636d984b786 100755 >> --- a/tools/testing/selftests/mm/run_vmtests.sh >> +++ b/tools/testing/selftests/mm/run_vmtests.sh >> @@ -75,6 +75,8 @@ separated by spaces: >> read-only VMAs >> - mdwe >> test prctl(PR_SET_MDWE, ...) >> +- page_frag >> + test handling of page fragment allocation and freeing >> >> example: ./run_vmtests.sh -t "hmm mmap ksm" >> EOF >> @@ -231,7 +233,8 @@ run_test() { >> ("$@" 2>&1) | tap_prefix >> local ret=${PIPESTATUS[0]} >> count_total=$(( count_total + 1 )) >> - if [ $ret -eq 0 ]; then >> + # page_frag_test.ko returns 11(EAGAIN) when insmod'ing to avoid rmmod >> + if [ $ret -eq 0 ] | [ $ret -eq 11 -a ${CATEGORY} == "page_frag" ]; then >> count_pass=$(( count_pass + 1 )) >> echo "[PASS]" | tap_prefix >> echo "ok ${count_total} ${test}" | tap_output >> @@ -453,6 +456,10 @@ CATEGORY="mkdirty" run_test ./mkdirty >> >> CATEGORY="mdwe" run_test ./mdwe_test >> >> +CATEGORY="page_frag" run_test insmod ./page_frag/page_frag_test.ko >> + >> +CATEGORY="page_frag" run_test insmod ./page_frag/page_frag_test.ko test_alloc_len=12 test_align=1 >> + > You are loading the test module. How will we verify if the test passed > or failed? There must be a way to mark the test passed or failed after I am not sure that matter that much for page_frag_test module as it already return -EAGAIN for normal case as mentioned in: https://patchwork.kernel.org/project/netdevbpf/patch/20240731124505.2903877-2-linyunsheng@huawei.com/#25960885 > running it. You can definitely parse the dmesg to get results. But it > would be complex to do it. KUnit is way to go as all such tools are > already present there.