From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4990135E93C for ; Fri, 24 Apr 2026 11:26:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777030003; cv=none; b=I9P4G3jMhgWwBjCvVnm5M4JD7qfnuhn0FVomz4NJ0j+UOfNw1ixU8ZNgH1BxTavbMMycQsmBS/hOy98zXQ6nKSXw1vgqqZIhY6Irzr6ZpwMp0ePZyfbRT4oneQYx95I7CjhAaIib8fJByu2HCTN7bMMUhFQrkWxaoYk6LK/PxlQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777030003; c=relaxed/simple; bh=BLauuSDU9q2hNlHnwGzJsqz/KReSztervXoU1Q8mtdQ=; h=Date:From:To:Cc:Subject:Message-Id:In-Reply-To:References: Mime-Version:Content-Type; b=Jl3BY/xEEudIqzakSSoLl5BGVDiyCmmRNPeQzvIdKfG1D9bRxnbbWGE7k+0lm3i9YpA4jEfSWXQQPLjO2T3yoq8hQMyrZdfnVsn6DQtntMPkGKftEEk5cTMSB9AV+duIA23DXcczZ1nfJ157wpEtnF+l4CHyaXlucipVvqWCHuo= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b=wHC15HWJ; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux-foundation.org header.i=@linux-foundation.org header.b="wHC15HWJ" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 86105C19425; Fri, 24 Apr 2026 11:26:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linux-foundation.org; s=korg; t=1777030002; bh=BLauuSDU9q2hNlHnwGzJsqz/KReSztervXoU1Q8mtdQ=; h=Date:From:To:Cc:Subject:In-Reply-To:References:From; b=wHC15HWJH70pwZVT4mBhRwouJo6dUkrGPs8WSCHi+btdzTMV6hRori3PN9WacSL7H i6wnbivYhphjMCko0pezCYFON1UdrkZ9ZGTr1I7iu/i5ZIm8CZLy3x36vEbH7tlHWh Wqozdp5kmQH382gFcY/0iSclSbvAqFk80Ef6y0jw= Date: Fri, 24 Apr 2026 04:26:41 -0700 From: Andrew Morton To: Zhen Ni Cc: vbabka@kernel.org, surenb@google.com, mhocko@suse.com, jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH v2 3/3] mm/page_owner: add NUMA node filter with nodelist support Message-Id: <20260424042641.b2fbe039ffef2935326077ee@linux-foundation.org> In-Reply-To: <20260419155540.376847-4-zhen.ni@easystack.cn> References: <20260419155540.376847-1-zhen.ni@easystack.cn> <20260419155540.376847-4-zhen.ni@easystack.cn> X-Mailer: Sylpheed 3.8.0beta1 (GTK+ 2.24.33; x86_64-pc-linux-gnu) Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit On Sun, 19 Apr 2026 23:55:40 +0800 Zhen Ni wrote: > Add NUMA node filtering functionality to page_owner to allow > filtering pages by specific NUMA node(s) using nodelist format. > > The filter allows users to focus on pages from specific NUMA nodes, > which is useful for NUMA-aware memory allocation analysis and debugging. > > Supported input formats: > - Single node: echo "2" > nid > - Multiple nodes: echo "0,2,3" > nid > - Node range: echo "0-3" > nid > - Mixed format: echo "0,2-4,7" > nid > - Disable filter: echo "-1" > nid > > ... > > --- a/mm/page_owner.c > +++ b/mm/page_owner.c > @@ -707,6 +707,7 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) > * user through copy_to_user() or GFP_KERNEL allocations. > */ > struct page_owner page_owner_tmp; > + nodemask_t mask; > > /* > * If the new page is in a new MAX_ORDER_NR_PAGES area, > @@ -730,6 +731,15 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) > if (unlikely(!page_ext)) > continue; > > + /* NUMA node filter using bitmask */ > + mask = READ_ONCE(owner_filter.nid_mask); > + if (!nodes_empty(mask)) { > + int nid = page_to_nid(page); > + > + if (!node_isset(nid, mask)) > + goto ext_put_continue; > + } > + > /* > * Some pages could be missed by concurrent allocation or free, > * because we don't hold the zone lock. > @@ -1009,6 +1019,70 @@ DEFINE_SIMPLE_ATTRIBUTE(page_owner_print_mode_fops, > &page_owner_print_mode_get, > &page_owner_print_mode_set, "%lld"); > > +static ssize_t nid_filter_write(struct file *file, > + const char __user *buf, > + size_t count, loff_t *ppos) > +{ > + char *kbuf; > + nodemask_t mask; > + int ret; > + > + /* Limit input size to handle worst-case nodelist (all nodes) */ > + if (count > (100 + 6 * MAX_NUMNODES)) > + return -EINVAL; I'm wondering how that expression was arrived at ;) Perhaps a little comment explaining? Or can we simply use strnlen_user() here? > + kbuf = kmalloc(count + 1, GFP_KERNEL); > + if (!kbuf) > + return -ENOMEM; > + > + if (copy_from_user(kbuf, buf, count)) { > + ret = -EFAULT; > + goto out_free; > + } > + kbuf[count] = '\0'; Can we use strncpy_from_user() here? In fact I thought that we had a strdup_from_user() thing which does the kmalloc also, but maybe I dreamed it. And memdup_user_nul() could perhaps be used in here. Nothing really fits. We need a char *strdup_user(const void __user *src); (Probably it's OK to assume GFP_KERNEL) (Maybe needs a size_t max_len arg) > + /* Support: "-1" to clear, or nodelist format like "0", "0,2", "0-3" */ > + if (strcmp(kbuf, "-1\n") == 0 || strcmp(kbuf, "-1") == 0) Maybe if (kstrtoll(kbuf) == -1) (we have lots of goodies in /lib!)