From patchwork Tue Jul 16 13:59:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Roberts X-Patchwork-Id: 13734540 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 09FFDC3DA59 for ; Tue, 16 Jul 2024 13:59:23 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 455CC6B00A8; Tue, 16 Jul 2024 09:59:22 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 3B84D6B00A9; Tue, 16 Jul 2024 09:59:22 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 1BE726B00AB; Tue, 16 Jul 2024 09:59:22 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id F0E466B00A8 for ; Tue, 16 Jul 2024 09:59:21 -0400 (EDT) Received: from smtpin13.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id AF03D14175D for ; Tue, 16 Jul 2024 13:59:21 +0000 (UTC) X-FDA: 82345772922.13.FCE907C Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf24.hostedemail.com (Postfix) with ESMTP id 0CC1C180027 for ; Tue, 16 Jul 2024 13:59:19 +0000 (UTC) Authentication-Results: imf24.hostedemail.com; dkim=none; spf=pass (imf24.hostedemail.com: domain of ryan.roberts@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=ryan.roberts@arm.com; dmarc=pass (policy=none) header.from=arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1721138321; 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-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pxlMlr8qsicJ+zV5KcAguJPe+H/TL/ukuh6IP8ASZSc=; b=hiHafcrvnDVeerf55sgVkSW48mKyZW5x72I3MfP5yL1UoboJrTuanEBk6QLvBIGCpuPaWc +eHwi4qEmiit6xcPk+jDk94k9gmy7aCGA9njmcK3iyAQmJnAwTbQQvS3DjDh+t4Cpz0KfB OTo/NZXmpg3m8FHGBF9PZNXzpb0Je+s= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1721138321; a=rsa-sha256; cv=none; b=LCZtgjWzBWJ2RsTOZFgA4+BRf1dIuW0K2SdjFTOq6DAfMVib0iJzM3oB0Kwel341+tyu0f 9BnJQX71UK1RST4oYWhKMZvh7atHVqRrRW0H9zUAN6nGPXWVT3i5rkPxMxIA/x74RppW3h 4g7+cYLOp9H7B2FdwzjspBQ1trxaH8s= ARC-Authentication-Results: i=1; imf24.hostedemail.com; dkim=none; spf=pass (imf24.hostedemail.com: domain of ryan.roberts@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=ryan.roberts@arm.com; dmarc=pass (policy=none) header.from=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 76C89113E; Tue, 16 Jul 2024 06:59:44 -0700 (PDT) Received: from e125769.cambridge.arm.com (e125769.cambridge.arm.com [10.1.196.27]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id ADBC33F762; Tue, 16 Jul 2024 06:59:17 -0700 (PDT) From: Ryan Roberts To: Andrew Morton , Hugh Dickins , Jonathan Corbet , "Matthew Wilcox (Oracle)" , David Hildenbrand , Barry Song , Lance Yang , Baolin Wang , Gavin Shan Cc: Ryan Roberts , linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH v2 2/3] mm: Tidy up shmem mTHP controls and stats Date: Tue, 16 Jul 2024 14:59:05 +0100 Message-ID: <20240716135907.4047689-3-ryan.roberts@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240716135907.4047689-1-ryan.roberts@arm.com> References: <20240716135907.4047689-1-ryan.roberts@arm.com> MIME-Version: 1.0 X-Stat-Signature: mntqoigu98oqddzrfa3rg6615scss389 X-Rspamd-Queue-Id: 0CC1C180027 X-Rspam-User: X-Rspamd-Server: rspam08 X-HE-Tag: 1721138359-878410 X-HE-Meta: U2FsdGVkX19OeQVk+WWDl53MIT0xLlT4on16y1111itaIbk19/EEjyC9TnUiUs8KHUrvCp184cs2e+EEIgdZh8z2TuchXcURqXsQXyZ0hbuPo8K2y2td+VCJlcLSDUJpwxBLItXtUrPwBuYyj2QFkj8Bbb03gGVbU1Mm1TiEnpNOBzJvDxHw7fsKre2h/CZZmiUM+yPlJ6SMFHWw82/LI3IxnFRE4c5xVOOeNp/11y8F0IFKC6aJUP0Ib26xfEc4JiVU6IX/fGb/sk1Wa5S3pk4lCFJPk2P2/EYGxcEh7M97lS9y/l3uz4dT8M3PpxPWR4f0sX3rgbQ1FokA8OKiWvx4lOS4dO57mQLueBKrVhn64okBMX8CCAia8Gfr6W6cFRNQpcQRFilPvlwNsDjIIsZZ7aVIhOwcZulDOYN3/CmeBjGloW+zs50NoFtB3DWS120pe8bQXpSuxRjeX4THJrEaLJZjusG0hhddjZYmykvEOQgGLwqhSjt0ya9EG9TCjM7W+7ZULGvgRXHJ6gQH3DkMEcHDzrGcBgUkIkpdUIk6KP9IyqLVKpyc4hDwve6mjLhwVZyNTgQ0VcQQjJbfyy/QmFJhTG/YDhZIwT4QT2+wDORCzbagpF5Vnbxhh6JbHGdFOh0tAruYgW8XJkX1SX41jujy8N+3XXcGIbUc+Y+rQRIQngIACVBl0ZJ6y2017nvjWSg0jSjKyNtEAR80tiXVlD9ZpwfVOfyueYepJxZNbfknMvPOY2hiA4IRsGFt3lVMgdbjkg5TfRMkbxubxaA3xdV3RDqyi3sKYOHJA8y3/ox+UVY8qYC9zonEkUnvgcmpQHbb/J0RWyLbNVvwqFt7Z2sD74zF1r4EyRrN9+MkoBC6X8F/L0uAILxBfM2uyoXPJVe04lOciVxXqv5MVY3pTPEW/EIfUO9/jBtvEzvscsd8wiaeY2ilPE6U9Vg8N2LEGqhPvG9nj1t1th/ VGELThPv FcsR+xcnCS0g+KCaKszo7VnamApuhL+3w0tHAVJsEk+iajyoJROPyOdyztXpR5qX/36v4go2j7WjkTrEllJbELfGBuZbyFEMm2UwUo8XjjY5r0L3sYMfZdaEy2bKxT7cJDRi/IXbFi0VokHmbmI/tYuYAaRET8qoxOqgm 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: Previously we had a situation where shmem mTHP controls and stats were not exposed for some supported sizes and were exposed for some unsupported sizes. So let's clean that up. Anon mTHP can support all large orders (2, PMD_ORDER). But shmem can support all large orders (1, MAX_PAGECACHE_ORDER). However, per-size shmem controls and stats were previously being exposed for all the anon mTHP orders, meaning order-1 was not present, and for arm64 64K base pages, orders 12 and 13 were exposed but were not supported internally. Tidy this all up by defining ctrl and stats attribute groups for anon and file separately. Anon ctrl and stats groups are populated for all orders in THP_ORDERS_ALL_ANON and file ctrl and stats groups are populated for all orders in THP_ORDERS_ALL_FILE_DEFAULT. The side-effect of all this is that different hugepage-*kB directories contain different sets of controls and stats, depending on which memory types support that size. This approach is preferred over the alternative, which is to populate dummy controls and stats for memory types that do not support a given size. Signed-off-by: Ryan Roberts --- mm/huge_memory.c | 110 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 80 insertions(+), 30 deletions(-) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index f4be468e06a4..578ac212c172 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -463,8 +463,8 @@ static void thpsize_release(struct kobject *kobj); static DEFINE_SPINLOCK(huge_anon_orders_lock); static LIST_HEAD(thpsize_list); -static ssize_t thpsize_enabled_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) +static ssize_t anon_enabled_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { int order = to_thpsize(kobj)->order; const char *output; @@ -481,9 +481,9 @@ static ssize_t thpsize_enabled_show(struct kobject *kobj, return sysfs_emit(buf, "%s\n", output); } -static ssize_t thpsize_enabled_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count) +static ssize_t anon_enabled_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) { int order = to_thpsize(kobj)->order; ssize_t ret = count; @@ -525,19 +525,27 @@ static ssize_t thpsize_enabled_store(struct kobject *kobj, return ret; } -static struct kobj_attribute thpsize_enabled_attr = - __ATTR(enabled, 0644, thpsize_enabled_show, thpsize_enabled_store); +static struct kobj_attribute anon_enabled_attr = + __ATTR(enabled, 0644, anon_enabled_show, anon_enabled_store); -static struct attribute *thpsize_attrs[] = { - &thpsize_enabled_attr.attr, +static struct attribute *anon_ctrl_attrs[] = { + &anon_enabled_attr.attr, + NULL, +}; + +static const struct attribute_group anon_ctrl_attr_grp = { + .attrs = anon_ctrl_attrs, +}; + +static struct attribute *file_ctrl_attrs[] = { #ifdef CONFIG_SHMEM &thpsize_shmem_enabled_attr.attr, #endif NULL, }; -static const struct attribute_group thpsize_attr_group = { - .attrs = thpsize_attrs, +static const struct attribute_group file_ctrl_attr_grp = { + .attrs = file_ctrl_attrs, }; static const struct kobj_type thpsize_ktype = { @@ -583,57 +591,99 @@ DEFINE_MTHP_STAT_ATTR(split, MTHP_STAT_SPLIT); DEFINE_MTHP_STAT_ATTR(split_failed, MTHP_STAT_SPLIT_FAILED); DEFINE_MTHP_STAT_ATTR(split_deferred, MTHP_STAT_SPLIT_DEFERRED); -static struct attribute *stats_attrs[] = { +static struct attribute *anon_stats_attrs[] = { &anon_fault_alloc_attr.attr, &anon_fault_fallback_attr.attr, &anon_fault_fallback_charge_attr.attr, &swpout_attr.attr, &swpout_fallback_attr.attr, - &shmem_alloc_attr.attr, - &shmem_fallback_attr.attr, - &shmem_fallback_charge_attr.attr, &split_attr.attr, &split_failed_attr.attr, &split_deferred_attr.attr, NULL, }; -static struct attribute_group stats_attr_group = { +static struct attribute_group anon_stats_attr_grp = { + .name = "stats", + .attrs = anon_stats_attrs, +}; + +static struct attribute *file_stats_attrs[] = { +#ifdef CONFIG_SHMEM + &shmem_alloc_attr.attr, + &shmem_fallback_attr.attr, + &shmem_fallback_charge_attr.attr, +#endif + NULL, +}; + +static struct attribute_group file_stats_attr_grp = { .name = "stats", - .attrs = stats_attrs, + .attrs = file_stats_attrs, }; +static int sysfs_add_group(struct kobject *kobj, + const struct attribute_group *grp) +{ + int ret = -ENOENT; + + /* + * If the group is named, try to merge first, assuming the subdirectory + * was already created. This avoids the warning emitted by + * sysfs_create_group() if the directory already exists. + */ + if (grp->name) + ret = sysfs_merge_group(kobj, grp); + if (ret) + ret = sysfs_create_group(kobj, grp); + + return ret; +} + static struct thpsize *thpsize_create(int order, struct kobject *parent) { unsigned long size = (PAGE_SIZE << order) / SZ_1K; struct thpsize *thpsize; - int ret; + int ret = -ENOMEM; thpsize = kzalloc(sizeof(*thpsize), GFP_KERNEL); if (!thpsize) - return ERR_PTR(-ENOMEM); + goto err; + + thpsize->order = order; ret = kobject_init_and_add(&thpsize->kobj, &thpsize_ktype, parent, "hugepages-%lukB", size); if (ret) { kfree(thpsize); - return ERR_PTR(ret); + goto err; } - ret = sysfs_create_group(&thpsize->kobj, &thpsize_attr_group); - if (ret) { - kobject_put(&thpsize->kobj); - return ERR_PTR(ret); + if (BIT(order) & THP_ORDERS_ALL_ANON) { + ret = sysfs_add_group(&thpsize->kobj, &anon_ctrl_attr_grp); + if (ret) + goto err_put; + + ret = sysfs_add_group(&thpsize->kobj, &anon_stats_attr_grp); + if (ret) + goto err_put; } - ret = sysfs_create_group(&thpsize->kobj, &stats_attr_group); - if (ret) { - kobject_put(&thpsize->kobj); - return ERR_PTR(ret); + if (BIT(order) & THP_ORDERS_ALL_FILE_DEFAULT) { + ret = sysfs_add_group(&thpsize->kobj, &file_ctrl_attr_grp); + if (ret) + goto err_put; + + ret = sysfs_add_group(&thpsize->kobj, &file_stats_attr_grp); + if (ret) + goto err_put; } - thpsize->order = order; return thpsize; +err_put: + kobject_put(&thpsize->kobj); +err: + return ERR_PTR(ret); } static void thpsize_release(struct kobject *kobj) @@ -673,7 +723,7 @@ static int __init hugepage_init_sysfs(struct kobject **hugepage_kobj) goto remove_hp_group; } - orders = THP_ORDERS_ALL_ANON; + orders = THP_ORDERS_ALL_ANON | THP_ORDERS_ALL_FILE_DEFAULT; order = highest_order(orders); while (orders) { thpsize = thpsize_create(order, *hugepage_kobj);