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 C5B39C10DC1 for ; Thu, 7 Dec 2023 00:28:17 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 1D49D6B0074; Wed, 6 Dec 2023 19:28:16 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id 15DE36B0075; Wed, 6 Dec 2023 19:28:16 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id EA38F6B0078; Wed, 6 Dec 2023 19:28:15 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id D24E76B0074 for ; Wed, 6 Dec 2023 19:28:15 -0500 (EST) Received: from smtpin06.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id AEE0A40200 for ; Thu, 7 Dec 2023 00:28:15 +0000 (UTC) X-FDA: 81538135350.06.FFD324B Received: from mail-yw1-f194.google.com (mail-yw1-f194.google.com [209.85.128.194]) by imf15.hostedemail.com (Postfix) with ESMTP id B2AA4A000C for ; Thu, 7 Dec 2023 00:28:12 +0000 (UTC) Authentication-Results: imf15.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=KHpeH7s0; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf15.hostedemail.com: domain of gourry.memverge@gmail.com designates 209.85.128.194 as permitted sender) smtp.mailfrom=gourry.memverge@gmail.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1701908892; 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:dkim-signature; bh=K9wIViZkBU87Y2XRyOX6ijFii9lZTEeqQT/4TV/pkeE=; b=baAjx0Dg2g3I8TICpiep4tUfYNB7UuFeujZQ6d1glA0h3YZnHPqqFLxr9VIqbA+kI/LWCu 1Xi4WD4wyB4WFBS29zEw+4jFHEe3Mkk+Euje618hu6/qZg3RevvUo7hAQ6iujU14cjKePS hjiNP528zg5Ev0KOA25cHwSoiMGxLP4= ARC-Authentication-Results: i=1; imf15.hostedemail.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=KHpeH7s0; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (imf15.hostedemail.com: domain of gourry.memverge@gmail.com designates 209.85.128.194 as permitted sender) smtp.mailfrom=gourry.memverge@gmail.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1701908892; a=rsa-sha256; cv=none; b=h3G+5Morrzm8joRIQ8f2V5J5szwyoGQiXv2+CFzV809kAMSNGs3fUzm4ITFb3lunkc2NBU fx8N8uqdbjW7ZiEFEBLjb7hUIawJQq5RaP7FDODG58xUTVuC64fDrJylkHG5z2m46bVyWV EX8wpe+yc2EJBOV9emwEaVpO3VV2SUE= Received: by mail-yw1-f194.google.com with SMTP id 00721157ae682-5dd3affae03so1136527b3.1 for ; Wed, 06 Dec 2023 16:28:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1701908892; x=1702513692; darn=kvack.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=K9wIViZkBU87Y2XRyOX6ijFii9lZTEeqQT/4TV/pkeE=; b=KHpeH7s0knpubNbOJ4qrwmogbnmGvqqov0cyqOUOGn8LObHV8aY1ZSlY+Z+KsSbLEK 9Bn8a6hmNUlI8lOJtB0x19bzSi0mBEIU2JSXwrJS9JgLs/k+uhcQq4Rm+MS2SLmgSFsv PYnQhDuy/CP2hxkbZTA9oem9P2WQ9SuLU0/BLsYctZbyA/uZ2zETpAi0yqHOwfdvqpYK 68aZM16nMe64/ah8qFAjXLCosgNVSeBUXBSmZqsML4CMfXJzDGZt2PTHk6MoVdlK0Qjo 2w0bSoFgHhFEt6AnnwplMTs5nNqjscPSzeNfQFiPJufIRaV6xlZAQUlECmiyzGCNXxFh QEvw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701908892; x=1702513692; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=K9wIViZkBU87Y2XRyOX6ijFii9lZTEeqQT/4TV/pkeE=; b=lovtDVPHaAIlINC1Oy0VFty2OklpYN0Tp3EEi2OeL4EPG0dPtlJF4642PH0XfqLT3c qzHhBWqu8SrUJGGDROV0bZ3LS+PiGLVOd/+ASxytel9I5TGbCqb4kGS/meAXwIqCM2ck MAS0/5sHGwvtCbFX6MkGHGDbLzgiawq6y9725cE9Jjv31UEgYl7IbZ8Uq0ZRgcZakGV8 qpA1ap1DwxWDS2b9J+eVMvQafZlzHmlkdkNPuQprvSxALLbxSFbxiV8ZiMUuKljfOIPO 9h3X+oqAY00UvJ17IdJBFCmEjLWYHXz291Z1zVHt71A3lVczB+p0CVGbykSnVrg183Se Vv7A== X-Gm-Message-State: AOJu0YzMZGg1CVLT8Oz4gYVYgvj41cxmBaYuVirsCo4BRJCWeKVQ81cz ERHpjd9pZlphsZ/p/M3cCFnhkNOuunj7 X-Google-Smtp-Source: AGHT+IFsypp4HiyFtXvyk2o+SL5aq0zamwJAkzXlggLGMQm5qgsPFIqsLXEuF5xWNcgX6pcVEg7qoA== X-Received: by 2002:a05:690c:3612:b0:5d7:1940:b37f with SMTP id ft18-20020a05690c361200b005d71940b37fmr1838437ywb.75.1701908891675; Wed, 06 Dec 2023 16:28:11 -0800 (PST) Received: from fedora.mshome.net (pool-173-79-56-208.washdc.fios.verizon.net. [173.79.56.208]) by smtp.gmail.com with ESMTPSA id x145-20020a81a097000000b005d82fc8cc92sm19539ywg.105.2023.12.06.16.28.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Dec 2023 16:28:11 -0800 (PST) From: Gregory Price X-Google-Original-From: Gregory Price To: linux-mm@kvack.org, jgroves@micron.com, ravis.opensrc@micron.com, sthanneeru@micron.com, emirakhur@micron.com, Hasan.Maruf@amd.com Cc: linux-doc@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org, linux-arch@vger.kernel.org, linux-kernel@vger.kernel.org, akpm@linux-foundation.org, arnd@arndb.de, tglx@linutronix.de, luto@kernel.org, mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com, x86@kernel.org, hpa@zytor.com, mhocko@kernel.org, tj@kernel.org, ying.huang@intel.com, gregory.price@memverge.com, corbet@lwn.net, rakie.kim@sk.com, hyeongtak.ji@sk.com, honggyu.kim@sk.com, vtavarespetr@micron.com, peterz@infradead.org Subject: [RFC PATCH 01/11] mm/mempolicy: implement the sysfs-based weighted_interleave interface Date: Wed, 6 Dec 2023 19:27:49 -0500 Message-Id: <20231207002759.51418-2-gregory.price@memverge.com> X-Mailer: git-send-email 2.39.1 In-Reply-To: <20231207002759.51418-1-gregory.price@memverge.com> References: <20231207002759.51418-1-gregory.price@memverge.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: B2AA4A000C X-Stat-Signature: nas51dya3g5aiks8jt31exd9rrmua9xg X-HE-Tag: 1701908892-941718 X-HE-Meta: U2FsdGVkX18AEUr6nedmLg/Hy974Lt5t0rZZS55MXC03TLC7nsbAwtQSdcS09v5iD+yIXPiymMROjitMVlEh774mVzmeUQIYBVnIeauB/QmrOVao50yYC49dbGr4lw0Mz9kXuaik7Ss1fZs0aB8UHkoS3sZex8HvglFJ3xgIRUxp+9GlQ69A3j3pFNIEwGZf9Ob8MuJalFesRjBMDy0z8VqlFTkgAil6JIPCfqGW0XjdPvAHlgvjRj7P3E1IpjX7GtbWCqkmwkac59QlsH/gcGLGwwJRWHDhIU+eNzxSBIOs64TrCTSCRS5SWak//SOuJWpgEhAgGskm26bgOyfE/zEtWWh+Dneo3aA7TManhHtfM7wVnuf7Cfa1TW14FA9FG+3FFUm+injCSMXRwW5VEcRbbi1x8xn0PdS5V/cTefIj8yG5q05AnxVFdIAEtfa2Tnh50hw34ux8qzyb2hFGIxOnH+n8ccVFgnQRrG4VmVFnXWlOAgx/blNKqy+v0wwMVfcyFGu/yl4TlazIrLALymtxQUKE2IOZIG3J0Ftl22wZEEo7LQoAj26t74zJA22bXoit4E01zofx3S+pqyRkug6np2OIyxOYRymHYOTectQBBVt1t/pivfpH3Sfv/o+RFS2FsDpNVq3+OqJX6sJqPfnuS3o1QjWM/n808btV88neplPl0clre5gQT+8VApCMY0WMSfu6Sd+15vI2LrAEH9WKcklqHJRGIbAq6/BaQ5F3MzRi74dmzgZHoVJYpOmtptGE5R+SVKsWM/FyhRrkZLdxEFNS3ZQ8n0FM2jtqiwl8ys5F8V3NSkiqXB0SIk08NLSQk6CNQPEgxp8joM8x6AsLzruJDQFavl3hlsc5vvHUpHdfwcqOEUd6VXkVGVJV26N93it1p1SYN3uD770LOc1W+VyatKjYZHxcNrXZSJljoKe1pPXMCLNVcYx4nVPeBArm3blYPfCXm/65Ooj M8FJjjlc vlyQhaxsG0JWfYtlUO70UaENNRSx6P4/Fzt9O9+fAgTZlxealGQQOlsD3e3UJrW62lGmrETfOcOTxmc8U33yIP/kvDV/QPjXZdqjObIk8FUmwR3Gv9OgyF9EW7hYjXEGOP9GT0oHsLBioDb9WI89Jp50z/0jJbRWpLEHr+C5tjw2CF1GnP7ILDUCvZqfD9OZjJP+/RlktLvaXNK6LIgZOi9gFl7uJEXKwsqIWIozR8ffZ4kqpLJ8kR/0esxYQ32KeH/OgIy9gYnFUyWcZSCRGiHRfiLE/1+i5ItaVgnKRa2ndy81mZhueQf72CKB1IkB19wkZDrmsK7ipxdLeDmD9WhZhzoIx8EZxQzkiI8MDOKh7ehjiWKfE6ZfInqXoPfRSp21u5epMDUGsC9Yrubxq+K9HDFQLdli64Ko5lZWdt2XEGHnx9XbqNyRV8Dr+Msm8L7McrFi2LZ3apSydetToS1GhBoIZ+10MjUfPW/Ipgm4/ZLd0exqrkQSv3HMoDcgbDr4ZshsuLJGUfciPs0oJIFY25jwmk1+WcOAXDS175U9guEbjHjXIckPha37Sv2tzRnTyEcKZgVfQLBg+VUr8Nv83ROyhskZWoNkIILTkDGbt0z657+UTRNGtec3j38/poLCaG586zvGAzPrGVic+41lNRrryDyt2Y52LmlxGNCtoauU= 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: From: Rakie Kim This patch provides a way to set interleave weight information under sysfs at /sys/kernel/mm/mempolicy/weighted_interleave/node*/node*/weight The sysfs structure is designed as follows. $ tree /sys/kernel/mm/mempolicy/ /sys/kernel/mm/mempolicy/ [1] ├── cpu_nodes [2] ├── possible_nodes [3] └── weighted_interleave [4] ├── node0 [5] │  ├── node0 [6] │  │ └── weight [7] │  └── node1 │  └── weight └── node1   ├── node0   │ └── weight   └── node1   └── weight Each file above can be explained as follows. [1] mm/mempolicy: configuration interface for mempolicy subsystem [2] cpu_nodes: list of cpu nodes information interface which is used to describe which nodes may generate sub-folders under each policy interface. For example, the weighted_interleave policy generates a nodeN folder for each cpu node. [3] possible_nodes: list of possible nodes informational interface which may be used across multiple memory policy configurations. Lists the `possible` nodes for which configurations may be required. A `possible` node is one which has been reserved by the kernel at boot, but may or may not be online. For example, the weighted_interleave policy generates a nodeN/nodeM folder for each cpu node and memory node combination [N,M]. [4] weighted_interleave/: config interface for weighted interleave policy [5] weighted_interleave/nodeN/: initiator node configurations Each CPU node receives its own weighting table, allowing for (src,dst) weighting to be accomplished, where src is the cpu node the task is running on, and dst is an index into the array of weights for that source node. [6] weighted_interleave/nodeN/nodeM/: memory node configurations [7] weighted_interleave/nodeN/nodeM/weight: weight for [N,M] The weight table for nodeN which can be programmed to weight each target (nodeM) differently. This is important for allowing re-weight to occur automatically on a task migration event, either via scheduler initiated migration or a cgroup.cpusets/mems_allowed policy change. Signed-off-by: Rakie Kim Signed-off-by: Honggyu Kim Co-developed-by: Gregory Price Signed-off-by: Gregory Price Co-developed-by: Hyeongtak Ji Signed-off-by: Hyeongtak Ji --- .../ABI/testing/sysfs-kernel-mm-mempolicy | 33 +++ ...fs-kernel-mm-mempolicy-weighted-interleave | 35 +++ mm/mempolicy.c | 226 ++++++++++++++++++ 3 files changed, 294 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-kernel-mm-mempolicy create mode 100644 Documentation/ABI/testing/sysfs-kernel-mm-mempolicy-weighted-interleave diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-mempolicy b/Documentation/ABI/testing/sysfs-kernel-mm-mempolicy new file mode 100644 index 000000000000..8dc1129d4ab1 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-mm-mempolicy @@ -0,0 +1,33 @@ +What: /sys/kernel/mm/mempolicy/ +Date: December 2023 +Contact: Linux memory management mailing list +Description: Interface for Mempolicy + +What: /sys/kernel/mm/mempolicy/cpu_nodes +Date: December 2023 +Contact: Linux memory management mailing list +Description: The numa nodes from which accesses can be generated + + A cpu numa node is one which has at least 1 CPU. These nodes + are capable of generating accesses to memory numa nodes, and + will have an interleave weight table. + + Example output: + + ===== ================================================= + "0,1" nodes 0 and 1 have CPUs which may generate access + ===== ================================================= + +What: /sys/kernel/mm/mempolicy/possible_nodes +Date: December 2023 +Contact: Linux memory management mailing list +Description: The numa nodes which are possible to come online + + A possible numa node is one which has been reserved by the + system at boot, but may or may not be online at runtime. + + Example output: + + ========= ======================================== + "0,1,2,3" nodes 0-3 are possibly online or offline + ========= ======================================== diff --git a/Documentation/ABI/testing/sysfs-kernel-mm-mempolicy-weighted-interleave b/Documentation/ABI/testing/sysfs-kernel-mm-mempolicy-weighted-interleave new file mode 100644 index 000000000000..75554895ede3 --- /dev/null +++ b/Documentation/ABI/testing/sysfs-kernel-mm-mempolicy-weighted-interleave @@ -0,0 +1,35 @@ +What: /sys/kernel/mm/mempolicy/weighted_interleave/ +Date: December 2023 +Contact: Linux memory management mailing list +Description: Configuration Interface for the Weighted Interleave policy + +What: /sys/kernel/mm/mempolicy/weighted_interleave/nodeN/ +Date: December 2023 +Contact: Linux memory management mailing list +Description: Configuration interface for accesses initiated from nodeN + + The directory to configure access initiator weights for nodeN. + + Possible numa nodes which have not been marked as a CPU node + at boot will not have a nodeN directory made for them at boot. + Hotplug for CPU nodes is not supported. + +What: /sys/kernel/mm/mempolicy/weighted_interleave/nodeN/nodeM + /sys/kernel/mm/mempolicy/weighted_interleave/nodeN/nodeM/weight +Date: December 2023 +Contact: Linux memory management mailing list +Description: Configuration interface for target nodes accessed from nodeNN + + The interleave weight for a memory node (M) from initiating + node (N). These weights are utilized by processes which have set + the mempolicy to MPOL_WEIGHTED_INTERLEAVE and have opted into + global weights by omitting a task-local weight array. + + These weights only affect new allocations, and changes at runtime + will not cause migrations on already allocated pages. + + If the weight of 0 is desired, the appropriate way to do this is + by removing the node from the weighted interleave nodemask. + + Minimum weight: 1 + Maximum weight: 255 diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 10a590ee1c89..ce332b5e7a03 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -131,6 +131,11 @@ static struct mempolicy default_policy = { static struct mempolicy preferred_node_policy[MAX_NUMNODES]; +struct interleave_weight_table { + unsigned char weights[MAX_NUMNODES]; +}; +static struct interleave_weight_table *iw_table; + /** * numa_nearest_node - Find nearest node by state * @node: Node id to start the search @@ -3067,3 +3072,224 @@ void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) p += scnprintf(p, buffer + maxlen - p, ":%*pbl", nodemask_pr_args(&nodes)); } + +struct iw_node_info { + struct kobject kobj; + int src; + int dst; +}; + +static ssize_t node_weight_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + struct iw_node_info *node_info = container_of(kobj, struct iw_node_info, + kobj); + return sysfs_emit(buf, "%d\n", + iw_table[node_info->src].weights[node_info->dst]); +} + +static ssize_t node_weight_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned char weight = 0; + struct iw_node_info *node_info = NULL; + + node_info = container_of(kobj, struct iw_node_info, kobj); + + if (kstrtou8(buf, 0, &weight) || !weight) + return -EINVAL; + + iw_table[node_info->src].weights[node_info->dst] = weight; + + return count; +} + +static struct kobj_attribute node_weight = + __ATTR(weight, 0664, node_weight_show, node_weight_store); + +static struct attribute *dst_node_attrs[] = { + &node_weight.attr, + NULL, +}; + +static struct attribute_group dst_node_attr_group = { + .attrs = dst_node_attrs, +}; + +static const struct attribute_group *dst_node_attr_groups[] = { + &dst_node_attr_group, + NULL, +}; + +static const struct kobj_type dst_node_kobj_ktype = { + .sysfs_ops = &kobj_sysfs_ops, + .default_groups = dst_node_attr_groups, +}; + +static int add_dst_node(int src, int dst, struct kobject *src_kobj) +{ + struct iw_node_info *node_info = NULL; + int ret; + + node_info = kzalloc(sizeof(struct iw_node_info), GFP_KERNEL); + if (!node_info) + return -ENOMEM; + node_info->src = src; + node_info->dst = dst; + + kobject_init(&node_info->kobj, &dst_node_kobj_ktype); + ret = kobject_add(&node_info->kobj, src_kobj, "node%d", dst); + if (ret) { + pr_err("kobject_add error [%d-node%d]: %d", src, dst, ret); + kobject_put(&node_info->kobj); + } + return ret; +} + +static int add_src_node(int src, struct kobject *root_kobj) +{ + int err, dst; + struct kobject *src_kobj; + char name[24]; + + snprintf(name, 24, "node%d", src); + src_kobj = kobject_create_and_add(name, root_kobj); + if (!src_kobj) { + pr_err("failed to create source node kobject\n"); + return -ENOMEM; + } + for_each_node_state(dst, N_POSSIBLE) { + err = add_dst_node(src, dst, src_kobj); + if (err) + break; + } + if (err) + kobject_put(src_kobj); + return err; +} + +static int add_weighted_interleave_group(struct kobject *root_kobj) +{ + struct kobject *wi_kobj; + int nid, err; + + wi_kobj = kobject_create_and_add("weighted_interleave", root_kobj); + if (!wi_kobj) { + pr_err("failed to create node kobject\n"); + return -ENOMEM; + } + + for_each_node_state(nid, N_CPU) { + err = add_src_node(nid, wi_kobj); + if (err) { + pr_err("failed to add sysfs [node%d]\n", nid); + break; + } + } + if (err) + kobject_put(wi_kobj); + return 0; + +} + +static ssize_t cpu_nodes_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int nid, next_nid; + int len = 0; + + for_each_node_state(nid, N_CPU) { + len += sysfs_emit_at(buf, len, "%d", nid); + next_nid = next_node(nid, node_states[N_CPU]); + if (next_nid < MAX_NUMNODES) + len += sysfs_emit_at(buf, len, ","); + } + len += sysfs_emit_at(buf, len, "\n"); + + return len; +} + +static ssize_t possible_nodes_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int nid, next_nid; + int len = 0; + + for_each_node_state(nid, N_POSSIBLE) { + len += sysfs_emit_at(buf, len, "%d", nid); + next_nid = next_node(nid, node_states[N_POSSIBLE]); + if (next_nid < MAX_NUMNODES) + len += sysfs_emit_at(buf, len, ","); + } + len += sysfs_emit_at(buf, len, "\n"); + + return len; +} + +static struct kobj_attribute cpu_nodes_attr = __ATTR_RO(cpu_nodes); +static struct kobj_attribute possible_nodes_attr = __ATTR_RO(possible_nodes); + +static struct attribute *mempolicy_attrs[] = { + &cpu_nodes_attr.attr, + &possible_nodes_attr.attr, + NULL, +}; + +static const struct attribute_group mempolicy_attr_group = { + .attrs = mempolicy_attrs, + NULL, +}; + +static void mempolicy_kobj_release(struct kobject *kobj) +{ + kfree(kobj); + kfree(iw_table); +} + +static const struct kobj_type mempolicy_kobj_ktype = { + .release = mempolicy_kobj_release, + .sysfs_ops = &kobj_sysfs_ops, +}; + +static int __init mempolicy_sysfs_init(void) +{ + int err, nid; + int cpunodes = 0; + struct kobject *root_kobj; + + for_each_node_state(nid, N_CPU) + cpunodes += 1; + iw_table = kmalloc_array(cpunodes, sizeof(*iw_table), GFP_KERNEL); + if (!iw_table) { + pr_err("failed to create interleave weight table\n"); + err = -ENOMEM; + goto fail_obj; + } + memset(iw_table, 1, cpunodes * sizeof(*iw_table)); + + root_kobj = kzalloc(sizeof(struct kobject), GFP_KERNEL); + if (!root_kobj) + return -ENOMEM; + + kobject_init(root_kobj, &mempolicy_kobj_ktype); + err = kobject_add(root_kobj, mm_kobj, "mempolicy"); + if (err) { + pr_err("failed to add kobject to the system\n"); + goto fail_obj; + } + + err = sysfs_create_group(root_kobj, &mempolicy_attr_group); + if (err) { + pr_err("failed to register mempolicy group\n"); + goto fail_obj; + } + + err = add_weighted_interleave_group(root_kobj); +fail_obj: + if (err) + kobject_put(root_kobj); + return err; + +} +late_initcall(mempolicy_sysfs_init); -- 2.39.1