LKML Archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH v1 1/1] memory: export symbols for process memory related functions
       [not found] <20230609110902.13799-1-Wei-chin.Tsai@mediatek.com>
@ 2023-06-09 11:20 ` Russell King (Oracle)
  2023-06-09 16:09   ` Wei-chin Tsai (蔡維晉)
  0 siblings, 1 reply; 5+ messages in thread
From: Russell King (Oracle) @ 2023-06-09 11:20 UTC (permalink / raw)
  To: jim.tsai
  Cc: linux-kernel, Matthias Brugger, AngeloGioacchino Del Regno,
	wsd_upstream, mel.lee, ivan.tseng, linux-arm-kernel,
	linux-fsdevel, linux-mediatek

On Fri, Jun 09, 2023 at 07:09:00PM +0800, jim.tsai wrote:
> Export symbols for arch_vma_name and smap_gather_stats
> functions so that we can detect the memory leak issues.
> Besides, we can know which memory type is leaked, too.

This commit description doesn't give enough information. How does
exporting arch_vma_name() help with detecting memory leak issues?

You haven't included any users of these new exports, so the initial
reaction is going to be negative - please include the users of these
new symbols in your patch set.

Thanks.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v1 1/1] memory: export symbols for process memory related functions
  2023-06-09 11:20 ` [PATCH v1 1/1] memory: export symbols for process memory related functions Russell King (Oracle)
@ 2023-06-09 16:09   ` Wei-chin Tsai (蔡維晉)
  2023-06-10  0:21     ` Matthew Wilcox
  0 siblings, 1 reply; 5+ messages in thread
From: Wei-chin Tsai (蔡維晉) @ 2023-06-09 16:09 UTC (permalink / raw)
  To: linux@armlinux.org.uk
  Cc: linux-kernel@vger.kernel.org, Mel Lee (李奇錚),
	linux-mediatek@lists.infradead.org, wsd_upstream,
	linux-arm-kernel@lists.infradead.org,
	linux-fsdevel@vger.kernel.org, matthias.bgg@gmail.com,
	Ivan Tseng (曾志軒),
	angelogioacchino.delregno@collabora.com

On Fri, 2023-06-09 at 12:20 +0100, Russell King (Oracle) wrote:
>  	 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>  On Fri, Jun 09, 2023 at 07:09:00PM +0800, jim.tsai wrote:
> > Export symbols for arch_vma_name and smap_gather_stats
> > functions so that we can detect the memory leak issues.
> > Besides, we can know which memory type is leaked, too.
> 
> This commit description doesn't give enough information. How does
> exporting arch_vma_name() help with detecting memory leak issues?
> 
> You haven't included any users of these new exports, so the initial
> reaction is going to be negative - please include the users of these
> new symbols in your patch set.
> 
> Thanks.
> 
> -- 
> RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
> FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!


Hi Russell,

arch_vma_name() is to get the heap infromation from a user process.

We use these two export functions from our kernel module to get a
specific user process's memory information and heap usage. Furthermore,
we can use such information to detect the memory leak issues. 

The example code is as follows:

/*example code*/

void m_map_vma(struct vm_area_struct *vma, unsigned long cur_pss,
                        unsigned long *native_heap, unsigned long
*java_heap)
{
	struct mm_struct *mm = vma->vm_mm;
        const char *name = NULL;

	...
	name = arch_vma_name(vma);
        if (!name) {
                struct anon_vma_name *anon_name;

                ...
                anon_name = m_anon_vma_name(vma);
                if (anon_name) {
                        if (strstr(anon_name->name, "scudo"))
                                (*native_heap) += cur_pss;
                        else if (strstr(anon_name->name,
"libc_malloc"))
                                (*native_heap) += cur_pss;
                        else if (strstr(anon_name->name, "GWP-ASan"))
                                (*native_heap) += cur_pss;
                        else if (strstr(anon_name->name, "dalvik-alloc
space"))
                                (*java_heap) += cur_pss;
                        else if (strstr(anon_name->name, "dalvik-main
space"))
                                (*java_heap) += cur_pss;

                        ...
                }
        }
}

void calculate_process_memory(struct task_struct *t)
{
        struct mm_struct *mm = NULL;
        struct vm_area_struct *vma = NULL;
        struct mem_size_stats mss;
        unsigned long pss, uss, rss, swap, cur_pss;
        unsigned long java_heap = 0, native_heap = 0;
        struct vma_iterator vmi;

        get_task_struct(t);
        mm = t->mm;
        if (mm) {
                memset(&mss, 0, sizeof(mss));
                mmgrab(mm);
                mmap_read_lock(mm);
                vma_iter_init(&vmi, mm, 0);

                for_each_vma(vmi, vma) {
                        cur_pss = (unsigned long)(mss.pss >>
PSS_SHIFT);
                        smap_gather_stats(vma, &mss, 0);
                        cur_pss =
                                ((unsigned long)(mss.pss >> PSS_SHIFT))
- cur_pss;
                        cur_pss = cur_pss / 1024;
                        m_map_vma(vma, cur_pss, &native_heap,
&java_heap);
                }
                mmap_read_unlock(mm);
                mmdrop(mm);
        }
        put_task_struct(t);

        ...
}

Thanks

Jim



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v1 1/1] memory: export symbols for process memory related functions
  2023-06-09 16:09   ` Wei-chin Tsai (蔡維晉)
@ 2023-06-10  0:21     ` Matthew Wilcox
  2023-06-12 14:21       ` Wei-chin Tsai (蔡維晉)
  0 siblings, 1 reply; 5+ messages in thread
From: Matthew Wilcox @ 2023-06-10  0:21 UTC (permalink / raw)
  To: Wei-chin Tsai (蔡維晉)
  Cc: linux@armlinux.org.uk, linux-kernel@vger.kernel.org,
	Mel Lee (李奇錚),
	linux-mediatek@lists.infradead.org, wsd_upstream,
	linux-arm-kernel@lists.infradead.org,
	linux-fsdevel@vger.kernel.org, matthias.bgg@gmail.com,
	Ivan Tseng (曾志軒),
	angelogioacchino.delregno@collabora.com

On Fri, Jun 09, 2023 at 04:09:01PM +0000, Wei-chin Tsai (蔡維晉) wrote:
> > You haven't included any users of these new exports, so the initial
> > reaction is going to be negative - please include the users of these
> > new symbols in your patch set.
> We use these two export functions from our kernel module to get a
> specific user process's memory information and heap usage. Furthermore,
> we can use such information to detect the memory leak issues. 
> 
> The example code is as follows:

No.  You need to be submitting the code that will use the symbol *at the
same time* as the patch to export the symbol.  No example code showing
how it could be used.  Because if the user isn't compelling, the patch
to export the symbol won't be applied either.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH v1 1/1] memory: export symbols for process memory related functions
  2023-06-10  0:21     ` Matthew Wilcox
@ 2023-06-12 14:21       ` Wei-chin Tsai (蔡維晉)
  2023-06-16  9:24         ` Matthias Brugger
  0 siblings, 1 reply; 5+ messages in thread
From: Wei-chin Tsai (蔡維晉) @ 2023-06-12 14:21 UTC (permalink / raw)
  To: willy@infradead.org
  Cc: linux-kernel@vger.kernel.org, Mel Lee (李奇錚),
	linux-mediatek@lists.infradead.org, linux@armlinux.org.uk,
	wsd_upstream, linux-arm-kernel@lists.infradead.org,
	linux-fsdevel@vger.kernel.org, matthias.bgg@gmail.com,
	Ivan Tseng (曾志軒),
	angelogioacchino.delregno@collabora.com

[-- Attachment #1: Type: text/plain, Size: 1217 bytes --]

On Sat, 2023-06-10 at 01:21 +0100, Matthew Wilcox wrote:
>  	 
> External email : Please do not click links or open attachments until
> you have verified the sender or the content.
>  On Fri, Jun 09, 2023 at 04:09:01PM +0000, Wei-chin Tsai (蔡維晉) wrote:
> > > You haven't included any users of these new exports, so the
> initial
> > > reaction is going to be negative - please include the users of
> these
> > > new symbols in your patch set.
> > We use these two export functions from our kernel module to get a
> > specific user process's memory information and heap usage.
> Furthermore,
> > we can use such information to detect the memory leak issues. 
> > 
> > The example code is as follows:
> 
> No.  You need to be submitting the code that will use the symbol *at
> the
> same time* as the patch to export the symbol.  No example code
> showing
> how it could be used.  Because if the user isn't compelling, the
> patch
> to export the symbol won't be applied either.

Hi Matthew,

Got it. The following attached patch file
"v1-0001-memory-export-symbols-for-process-memory-related-.patch" is
the patch including the users of these new symbols. Thanks.

Regards,

Jim

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v1-0001-memory-export-symbols-for-process-memory-related-.patch --]
[-- Type: text/x-patch; name="v1-0001-memory-export-symbols-for-process-memory-related-.patch", Size: 28708 bytes --]

From b4529be3bb55f643cecd6c3a40f40cc8446f5785 Mon Sep 17 00:00:00 2001
From: "jim.tsai" <Wei-chin.Tsai@mediatek.com>
Date: Mon, 12 Jun 2023 22:10:10 +0800
Subject: [PATCH v1 1/1] memory: export symbols for process memory related
 functions

Export symbols for arch_vma_name and smap_gather_stats
functions so that we can detect the memory leak issues.
Besides, we can know which memory type is leaked, too.

Signed-off-by: jim.tsai <Wei-chin.Tsai@mediatek.com>
---
 arch/arm/kernel/process.c                     |   1 +
 drivers/misc/mediatek_mbraink/Kconfig         |   7 +
 drivers/misc/mediatek_mbraink/Makefile        |   5 +
 drivers/misc/mediatek_mbraink/mbraink_data.c  | 417 ++++++++++++++++++
 drivers/misc/mediatek_mbraink/mbraink_data.h  |  67 +++
 .../mbraink_ioctl_struct_define.h             |  44 ++
 drivers/misc/mediatek_mbraink/mbraink_main.c  | 277 ++++++++++++
 drivers/misc/mediatek_mbraink/mbraink_main.h  |  32 ++
 fs/proc/task_mmu.c                            |   5 +-
 kernel/signal.c                               |   1 +
 10 files changed, 854 insertions(+), 2 deletions(-)
 create mode 100644 drivers/misc/mediatek_mbraink/Kconfig
 create mode 100644 drivers/misc/mediatek_mbraink/Makefile
 create mode 100644 drivers/misc/mediatek_mbraink/mbraink_data.c
 create mode 100644 drivers/misc/mediatek_mbraink/mbraink_data.h
 create mode 100644 drivers/misc/mediatek_mbraink/mbraink_ioctl_struct_define.h
 create mode 100644 drivers/misc/mediatek_mbraink/mbraink_main.c
 create mode 100644 drivers/misc/mediatek_mbraink/mbraink_main.h

diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 0e8ff85890ad..df91412a1069 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -343,6 +343,7 @@ const char *arch_vma_name(struct vm_area_struct *vma)
 {
 	return is_gate_vma(vma) ? "[vectors]" : NULL;
 }
+EXPORT_SYMBOL_GPL(arch_vma_name);
 
 /* If possible, provide a placement hint at a random offset from the
  * stack for the sigpage and vdso pages.
diff --git a/drivers/misc/mediatek_mbraink/Kconfig b/drivers/misc/mediatek_mbraink/Kconfig
new file mode 100644
index 000000000000..615c1043a866
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/Kconfig
@@ -0,0 +1,7 @@
+config MTK_MBRAINK
+	tristate "MTK MBRAINK support"
+	help
+          MBRAINK is a MediaTek in-house kernel module which can
+          communicate with android MBrain.
+          Set Y to enable this feature.
+          If unsure, Set N to stay with legancy feature.
diff --git a/drivers/misc/mediatek_mbraink/Makefile b/drivers/misc/mediatek_mbraink/Makefile
new file mode 100644
index 000000000000..8d75b41a8097
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/Makefile
@@ -0,0 +1,5 @@
+subdir-ccflags-y += -Wformat
+
+obj-${CONFIG_MTK_MBRAINK} += mtk_mbraink.o
+
+mtk_mbraink-objs += mbraink_data.o mbraink_main.o
diff --git a/drivers/misc/mediatek_mbraink/mbraink_data.c b/drivers/misc/mediatek_mbraink/mbraink_data.c
new file mode 100644
index 000000000000..5c793a8c262d
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_data.c
@@ -0,0 +1,417 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/rtc.h>
+#include <linux/sched/clock.h>
+#include <linux/kernel.h>
+#include <linux/uaccess.h>
+#include <linux/cdev.h>
+#include <linux/proc_fs.h>
+#include <linux/sched/signal.h>
+#include <linux/pid_namespace.h>
+#include <linux/mm.h>
+#include <linux/sched/mm.h>
+#include <linux/sched/task.h>
+#include <linux/pagewalk.h>
+#include <linux/shmem_fs.h>
+#include <linux/pagemap.h>
+#include <linux/mempolicy.h>
+#include <linux/rmap.h>
+#include <linux/sched/cputime.h>
+#include <linux/math64.h>
+#include <linux/refcount.h>
+#include <linux/ctype.h>
+#include <linux/stddef.h>
+#include <linux/cred.h>
+#include <linux/spinlock.h>
+#include <linux/rtc.h>
+#include <linux/sched/clock.h>
+#include <trace/events/sched.h>
+#include <linux/mm_inline.h>
+
+#include "mbraink_data.h"
+
+/*spinlock for mbraink tracing pidlist*/
+static DEFINE_SPINLOCK(tracing_pidlist_lock);
+/*Please make sure that tracing pidlist is protected by spinlock*/
+struct mbraink_tracing_pidlist mbraink_tracing_pidlist_data[MAX_TRACE_NUM];
+
+#if IS_ENABLED(CONFIG_ANON_VMA_NAME)
+struct anon_vma_name *mbraink_anon_vma_name(struct vm_area_struct *vma)
+{
+	if (vma->vm_file)
+		return NULL;
+
+	return vma->anon_name;
+}
+#else
+struct anon_vma_name *mbraink_anon_vma_name(struct vm_area_struct *vma)
+{
+	return NULL;
+}
+#endif
+
+void mbraink_map_vma(struct vm_area_struct *vma, unsigned long cur_pss,
+		     unsigned long *native_heap, unsigned long *java_heap)
+{
+	struct mm_struct *mm = vma->vm_mm;
+	const char *name = NULL;
+
+	if (vma->vm_file)
+		return;
+	/*
+	 * Print the dentry name for named mappings, and a
+	 * special [heap] marker for the heap:
+	 */
+
+	if (vma->vm_ops && vma->vm_ops->name) {
+		name = vma->vm_ops->name(vma);
+		if (name) {
+			if (strncmp(name, "dev/ashmem/libc malloc", 23) == 0)
+				(*native_heap) += cur_pss;
+			return;
+		}
+	}
+
+	name = arch_vma_name(vma);
+	if (!name) {
+		struct anon_vma_name *anon_name;
+
+		if (!mm)
+			return;
+
+		if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
+			(*native_heap) += cur_pss;
+			return;
+		}
+
+		if (vma->vm_start <= vma->vm_mm->start_stack &&
+		    vma->vm_end >= vma->vm_mm->start_stack)
+			return;
+
+		anon_name = mbraink_anon_vma_name(vma);
+		if (anon_name) {
+			if (strstr(anon_name->name, "scudo"))
+				(*native_heap) += cur_pss;
+			else if (strstr(anon_name->name, "libc_malloc"))
+				(*native_heap) += cur_pss;
+			else if (strstr(anon_name->name, "GWP-ASan"))
+				(*native_heap) += cur_pss;
+			else if (strstr(anon_name->name, "dalvik-alloc space"))
+				(*java_heap) += cur_pss;
+			else if (strstr(anon_name->name, "dalvik-main space"))
+				(*java_heap) += cur_pss;
+			else if (strstr(anon_name->name, "dalvik-large object space"))
+				(*java_heap) += cur_pss;
+			else if (strstr(anon_name->name, "dalvik-free list large object space"))
+				(*java_heap) += cur_pss;
+			else if (strstr(anon_name->name, "dalvik-non moving space"))
+				(*java_heap) += cur_pss;
+			else if (strstr(anon_name->name, "dalvik-zygote space"))
+				(*java_heap) += cur_pss;
+		}
+	}
+}
+
+void mbraink_get_process_memory_info(pid_t current_pid,
+				     struct mbraink_process_memory_data *process_memory_buffer)
+{
+	struct task_struct *t = NULL;
+	struct mm_struct *mm = NULL;
+	struct vm_area_struct *vma = NULL;
+	struct mem_size_stats mss;
+	unsigned short pid_count = 0;
+	unsigned long pss, uss, rss, swap, cur_pss;
+	unsigned long java_heap = 0, native_heap = 0;
+	struct vma_iterator vmi;
+
+	memset(process_memory_buffer, 0, sizeof(struct mbraink_process_memory_data));
+	process_memory_buffer->pid = 0;
+
+	read_lock(&tasklist_lock);
+	for_each_process(t) {
+		if (t->pid <= current_pid)
+			continue;
+
+		mm = t->mm;
+		if (mm) {
+			java_heap = 0;
+			native_heap = 0;
+			pid_count = process_memory_buffer->pid_count;
+
+			process_memory_buffer->drv_data[pid_count].pid =
+				(unsigned short)(t->pid);
+			process_memory_buffer->pid =
+				(unsigned short)(t->pid);
+
+			memset(&mss, 0, sizeof(mss));
+			get_task_struct(t);
+			mmgrab(mm);
+			read_unlock(&tasklist_lock);
+			mmap_read_lock(mm);
+			vma_iter_init(&vmi, mm, 0);
+			for_each_vma(vmi, vma) {
+				cur_pss = (unsigned long)(mss.pss >> PSS_SHIFT);
+				smap_gather_stats(vma, &mss, 0);
+				cur_pss =
+					((unsigned long)(mss.pss >> PSS_SHIFT)) - cur_pss;
+				cur_pss = cur_pss / 1024;
+				mbraink_map_vma(vma, cur_pss, &native_heap, &java_heap);
+			}
+			mmap_read_unlock(mm);
+			read_lock(&tasklist_lock);
+			mmdrop(mm);
+			put_task_struct(t);
+
+			pss = (unsigned long)(mss.pss >> PSS_SHIFT) / 1024;
+			uss = (mss.private_clean + mss.private_dirty) / 1024;
+			rss = (mss.resident) / 1024;
+			swap = (mss.swap) / 1024;
+
+			process_memory_buffer->drv_data[pid_count].pss = pss;
+			process_memory_buffer->drv_data[pid_count].uss = uss;
+			process_memory_buffer->drv_data[pid_count].rss = rss;
+			process_memory_buffer->drv_data[pid_count].swap = swap;
+			process_memory_buffer->drv_data[pid_count].java_heap =
+									java_heap;
+			process_memory_buffer->drv_data[pid_count].native_heap =
+									native_heap;
+			process_memory_buffer->pid_count++;
+
+			break;
+		}
+	}
+	read_unlock(&tasklist_lock);
+}
+
+/*****************************************************************
+ * Note: this function can only be used during tracing function
+ * This function is only used in tracing function so that there
+ * is no need for task t spinlock protection
+ *****************************************************************/
+static u64 mbraink_get_specific_process_jiffies(struct task_struct *t)
+{
+	u64 stime = 0, utime = 0, cutime = 0, cstime = 0;
+	u64 process_jiffies = 0;
+
+	if (t->pid == t->tgid) {
+		cutime = t->signal->cutime;
+		cstime = t->signal->cstime;
+		if (t->flags & PF_KTHREAD)
+			task_cputime_adjusted(t, &utime, &stime);
+		else
+			thread_group_cputime_adjusted(t, &utime, &stime);
+
+		process_jiffies = nsec_to_clock_t(utime) +
+				nsec_to_clock_t(stime) +
+				nsec_to_clock_t(cutime) +
+				nsec_to_clock_t(cstime);
+	} else {
+		task_cputime_adjusted(t, &utime, &stime);
+		process_jiffies = nsec_to_clock_t(utime) + nsec_to_clock_t(stime);
+	}
+
+	return process_jiffies;
+}
+
+/***************************************************************
+ * Note: this function can only be used during tracing function
+ * This function is only used in tracing function so that there
+ * is no need for task t spinlock protection
+ **************************************************************/
+static u16 mbraink_get_specific_process_uid(struct task_struct *t)
+{
+	const struct cred *cred = NULL;
+	u16 val = 0;
+
+	cred = get_task_cred(t);
+	val = cred->uid.val;
+	put_cred(cred);
+
+	return val;
+}
+
+static void mbraink_trace_sched_process_exit(void *data, struct task_struct *t)
+{
+	int i = 0;
+	struct timespec64 tv = { 0 };
+	unsigned long flags;
+
+	if (t->pid == t->tgid) {
+		spin_lock_irqsave(&tracing_pidlist_lock, flags);
+		for (i = 0; i < MAX_TRACE_NUM; i++) {
+			if (mbraink_tracing_pidlist_data[i].pid == (unsigned short)t->pid) {
+				ktime_get_real_ts64(&tv);
+				mbraink_tracing_pidlist_data[i].end =
+					(tv.tv_sec * 1000) + (tv.tv_nsec / 1000000);
+				mbraink_tracing_pidlist_data[i].jiffies =
+						mbraink_get_specific_process_jiffies(t);
+				mbraink_tracing_pidlist_data[i].dirty = true;
+
+				break;
+			}
+		}
+		if (i == MAX_TRACE_NUM) {
+			for (i = 0; i < MAX_TRACE_NUM; i++) {
+				if (mbraink_tracing_pidlist_data[i].pid == 0) {
+					mbraink_tracing_pidlist_data[i].pid =
+							(unsigned short)(t->pid);
+					mbraink_tracing_pidlist_data[i].tgid =
+							(unsigned short)(t->tgid);
+					mbraink_tracing_pidlist_data[i].uid =
+							mbraink_get_specific_process_uid(t);
+					mbraink_tracing_pidlist_data[i].priority =
+							t->prio - MAX_RT_PRIO;
+					memcpy(mbraink_tracing_pidlist_data[i].name,
+					       t->comm, TASK_COMM_LEN);
+					ktime_get_real_ts64(&tv);
+					mbraink_tracing_pidlist_data[i].end =
+							(tv.tv_sec * 1000) + (tv.tv_nsec / 1000000);
+					mbraink_tracing_pidlist_data[i].jiffies =
+							mbraink_get_specific_process_jiffies(t);
+					mbraink_tracing_pidlist_data[i].dirty = true;
+
+					break;
+				}
+			}
+			if (i == MAX_TRACE_NUM) {
+				pr_info("%s pid=%u:%s.\n", __func__, t->pid, t->comm);
+				memset(mbraink_tracing_pidlist_data, 0,
+				       sizeof(struct mbraink_tracing_pidlist) * MAX_TRACE_NUM);
+			}
+		}
+		spin_unlock_irqrestore(&tracing_pidlist_lock, flags);
+	}
+}
+
+static void mbraink_trace_sched_process_fork(void *data, struct task_struct *t,
+					     struct task_struct *p)
+{
+	int i = 0;
+	struct timespec64 tv = { 0 };
+	unsigned long flags;
+
+	if (p->pid == p->tgid) {
+		spin_lock_irqsave(&tracing_pidlist_lock, flags);
+		for (i = 0; i < MAX_TRACE_NUM; i++) {
+			if (mbraink_tracing_pidlist_data[i].pid == 0) {
+				mbraink_tracing_pidlist_data[i].pid = (unsigned short)(p->pid);
+				mbraink_tracing_pidlist_data[i].tgid = (unsigned short)(p->tgid);
+				mbraink_tracing_pidlist_data[i].uid =
+						mbraink_get_specific_process_uid(p);
+				mbraink_tracing_pidlist_data[i].priority = p->prio - MAX_RT_PRIO;
+				memcpy(mbraink_tracing_pidlist_data[i].name,
+				       p->comm, TASK_COMM_LEN);
+				ktime_get_real_ts64(&tv);
+				mbraink_tracing_pidlist_data[i].start =
+						(tv.tv_sec * 1000) + (tv.tv_nsec / 1000000);
+				mbraink_tracing_pidlist_data[i].dirty = true;
+				break;
+			}
+		}
+
+		if (i == MAX_TRACE_NUM) {
+			pr_info("%s child_pid=%u:%s.\n", __func__, p->pid, p->comm);
+			memset(mbraink_tracing_pidlist_data, 0,
+			       sizeof(struct mbraink_tracing_pidlist) * MAX_TRACE_NUM);
+		}
+		spin_unlock_irqrestore(&tracing_pidlist_lock, flags);
+	}
+}
+
+int mbraink_process_tracer_init(void)
+{
+	int ret = 0;
+
+	memset(mbraink_tracing_pidlist_data, 0,
+	       sizeof(struct mbraink_tracing_pidlist) * MAX_TRACE_NUM);
+
+	ret = register_trace_sched_process_fork(mbraink_trace_sched_process_fork, NULL);
+	if (ret) {
+		pr_notice("register_trace_sched_process_fork failed.\n");
+		goto register_trace_sched_process_fork;
+	}
+	ret = register_trace_sched_process_exit(mbraink_trace_sched_process_exit, NULL);
+	if (ret) {
+		pr_notice("register register_trace_sched_process_exit failed.\n");
+		goto register_trace_sched_process_exit;
+	}
+
+	return ret;
+
+register_trace_sched_process_exit:
+	unregister_trace_sched_process_fork(mbraink_trace_sched_process_fork, NULL);
+register_trace_sched_process_fork:
+	return ret;
+}
+
+void mbraink_process_tracer_exit(void)
+{
+	unregister_trace_sched_process_fork(mbraink_trace_sched_process_fork, NULL);
+	unregister_trace_sched_process_exit(mbraink_trace_sched_process_exit, NULL);
+}
+
+void mbraink_get_tracing_pid_info(unsigned short current_idx,
+				  struct mbraink_tracing_pid_data *tracing_pid_buffer)
+{
+	int i = 0;
+	int ret = 0;
+	unsigned long flags;
+	unsigned short tracing_count = 0;
+
+	spin_lock_irqsave(&tracing_pidlist_lock, flags);
+
+	memset(tracing_pid_buffer, 0, sizeof(struct mbraink_tracing_pid_data));
+
+	for (i = current_idx; i < MAX_TRACE_NUM; i++) {
+		if (mbraink_tracing_pidlist_data[i].dirty == false) {
+			continue;
+		} else {
+			tracing_count = tracing_pid_buffer->tracing_count;
+			if (tracing_count < MAX_TRACE_PID_NUM) {
+				tracing_pid_buffer->drv_data[tracing_count].pid =
+						mbraink_tracing_pidlist_data[i].pid;
+				tracing_pid_buffer->drv_data[tracing_count].tgid =
+						mbraink_tracing_pidlist_data[i].tgid;
+				tracing_pid_buffer->drv_data[tracing_count].uid =
+						mbraink_tracing_pidlist_data[i].uid;
+				tracing_pid_buffer->drv_data[tracing_count].priority =
+						mbraink_tracing_pidlist_data[i].priority;
+				memcpy(tracing_pid_buffer->drv_data[tracing_count].name,
+				       mbraink_tracing_pidlist_data[i].name, TASK_COMM_LEN);
+				tracing_pid_buffer->drv_data[tracing_count].start =
+						mbraink_tracing_pidlist_data[i].start;
+				tracing_pid_buffer->drv_data[tracing_count].end =
+						mbraink_tracing_pidlist_data[i].end;
+				tracing_pid_buffer->drv_data[tracing_count].jiffies =
+						mbraink_tracing_pidlist_data[i].jiffies;
+				tracing_pid_buffer->tracing_count++;
+				/*Deal with the end process record*/
+				if (mbraink_tracing_pidlist_data[i].end != 0) {
+					mbraink_tracing_pidlist_data[i].pid = 0;
+					mbraink_tracing_pidlist_data[i].tgid = 0;
+					mbraink_tracing_pidlist_data[i].uid = 0;
+					mbraink_tracing_pidlist_data[i].priority = 0;
+					memset(mbraink_tracing_pidlist_data[i].name,
+					       0, TASK_COMM_LEN);
+					mbraink_tracing_pidlist_data[i].start = 0;
+					mbraink_tracing_pidlist_data[i].end = 0;
+					mbraink_tracing_pidlist_data[i].jiffies = 0;
+					mbraink_tracing_pidlist_data[i].dirty = false;
+				} else {
+					mbraink_tracing_pidlist_data[i].dirty = false;
+				}
+			} else {
+				ret = -1;
+				tracing_pid_buffer->tracing_idx = i;
+				break;
+			}
+		}
+	}
+	pr_info("%s: current_idx = %u, count = %u\n",
+		__func__, tracing_pid_buffer->tracing_idx, tracing_pid_buffer->tracing_count);
+	spin_unlock_irqrestore(&tracing_pidlist_lock, flags);
+}
diff --git a/drivers/misc/mediatek_mbraink/mbraink_data.h b/drivers/misc/mediatek_mbraink/mbraink_data.h
new file mode 100644
index 000000000000..c10ec1083b79
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_data.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+#ifndef MBRAINK_DATA_H
+#define MBRAINK_DATA_H
+#include <linux/string_helpers.h>
+#include <linux/sched.h>
+#include <linux/sched/task.h>
+#include <linux/mm_types.h>
+#include <linux/pid.h>
+
+#include "mbraink_ioctl_struct_define.h"
+
+#define PSS_SHIFT			12
+#define MAX_RT_PRIO			100
+#define MAX_TRACE_NUM			3072
+
+struct mbraink_tracing_pidlist {
+	unsigned short pid;
+	unsigned short tgid;
+	unsigned short uid;
+	int priority;
+	char name[TASK_COMM_LEN];
+	long long start;
+	long long end;
+	u64 jiffies;
+	bool dirty;
+};
+
+struct mem_size_stats {
+	unsigned long resident;
+	unsigned long shared_clean;
+	unsigned long shared_dirty;
+	unsigned long private_clean;
+	unsigned long private_dirty;
+	unsigned long referenced;
+	unsigned long anonymous;
+	unsigned long lazyfree;
+	unsigned long anonymous_thp;
+	unsigned long shmem_thp;
+	unsigned long file_thp;
+	unsigned long swap;
+	unsigned long shared_hugetlb;
+	unsigned long private_hugetlb;
+	u64 pss;
+	u64 pss_anon;
+	u64 pss_file;
+	u64 pss_shmem;
+	u64 pss_locked;
+	u64 swap_pss;
+	bool check_shmem_swap;
+};
+
+void mbraink_get_process_memory_info(pid_t current_pid,
+				     struct mbraink_process_memory_data *process_memory_buffer);
+int mbraink_process_tracer_init(void);
+void mbraink_process_tracer_exit(void);
+void mbraink_get_tracing_pid_info(unsigned short current_idx,
+				  struct mbraink_tracing_pid_data *tracing_pid_buffer);
+void smap_gather_stats(struct vm_area_struct *vma,
+		       struct mem_size_stats *mss, unsigned long start);
+
+void task_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st);
+void thread_group_cputime_adjusted(struct task_struct *p, u64 *ut, u64 *st);
+u64 nsec_to_clock_t(u64 x);
+#endif
diff --git a/drivers/misc/mediatek_mbraink/mbraink_ioctl_struct_define.h b/drivers/misc/mediatek_mbraink/mbraink_ioctl_struct_define.h
new file mode 100644
index 000000000000..8395cf3b3702
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_ioctl_struct_define.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+#ifndef MBRAINK_IOCTL_STRUCT_H
+#define MBRAINK_IOCTL_STRUCT_H
+
+#define MAX_MEM_STRUCT_SZ			4
+#define MAX_TRACE_PID_NUM			16
+
+struct mbraink_process_memory_struct {
+	unsigned short pid;
+	unsigned long pss;
+	unsigned long uss;
+	unsigned long rss;
+	unsigned long swap;
+	unsigned long java_heap;
+	unsigned long native_heap;
+};
+
+struct mbraink_process_memory_data {
+	unsigned short pid;
+	unsigned short pid_count;
+	struct mbraink_process_memory_struct drv_data[MAX_MEM_STRUCT_SZ];
+};
+
+struct mbraink_tracing_pid {
+	unsigned short pid;
+	unsigned short tgid;
+	unsigned short uid;
+	int priority;
+	char name[TASK_COMM_LEN];
+	long long start;
+	long long end;
+	u64 jiffies;
+};
+
+struct mbraink_tracing_pid_data {
+	unsigned short tracing_idx;
+	unsigned short tracing_count;
+	struct mbraink_tracing_pid drv_data[MAX_TRACE_PID_NUM];
+};
+
+#endif
diff --git a/drivers/misc/mediatek_mbraink/mbraink_main.c b/drivers/misc/mediatek_mbraink/mbraink_main.c
new file mode 100644
index 000000000000..34bbc152b448
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_main.c
@@ -0,0 +1,277 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/compat.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/device.h>
+#include <linux/kdev_t.h>
+
+#include "mbraink_main.h"
+#include "mbraink_data.h"
+
+struct mbraink_data mbraink_priv;
+
+static int mbraink_open(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+static int mbraink_release(struct inode *inode, struct file *filp)
+{
+	return 0;
+}
+
+static long mbraink_ioctl(struct file *filp,
+			  unsigned int cmd,
+			  unsigned long arg)
+{
+	long ret = 0;
+
+	switch (cmd) {
+	case RO_PROCESS_MEMORY:
+	{
+		struct mbraink_process_memory_data process_memory_buffer;
+
+		pid_t pid = 1;
+
+		if (copy_from_user(&process_memory_buffer,
+				   (struct mbraink_process_memory_data *)arg,
+				   sizeof(process_memory_buffer))) {
+			pr_notice("copy process memory info from user Err!\n");
+			return -EPERM;
+		}
+
+		if (process_memory_buffer.pid > PID_MAX_DEFAULT ||
+		    process_memory_buffer.pid_count > PID_MAX_DEFAULT) {
+			pr_notice("process memory: Invalid pid_idx %u or pid_count %u\n",
+				  process_memory_buffer.pid, process_memory_buffer.pid_count);
+			return -EINVAL;
+		}
+		pid = process_memory_buffer.pid;
+
+		mbraink_get_process_memory_info(pid, &process_memory_buffer);
+
+		if (copy_to_user((struct mbraink_process_memory_data *)arg,
+				 &process_memory_buffer,
+				  sizeof(process_memory_buffer))) {
+			pr_notice("Copy process_memory_info to UserSpace error!\n");
+				return -EPERM;
+		}
+		break;
+	}
+	case RO_TRACE_PROCESS:
+	{
+		struct mbraink_tracing_pid_data tracing_pid_buffer;
+
+		unsigned short tracing_idx = 0;
+
+		if (copy_from_user(&tracing_pid_buffer,
+				   (struct mbraink_tracing_pid_data *)arg,
+				   sizeof(tracing_pid_buffer))) {
+			pr_notice("copy tracing_pid_buffer data from user Err!\n");
+			return -EPERM;
+		}
+
+		if (tracing_pid_buffer.tracing_idx > MAX_TRACE_NUM) {
+			pr_notice("invalid tracing_idx %u !\n",
+				  tracing_pid_buffer.tracing_idx);
+			return -EINVAL;
+		}
+		tracing_idx = tracing_pid_buffer.tracing_idx;
+
+		mbraink_get_tracing_pid_info(tracing_idx, &tracing_pid_buffer);
+
+		if (copy_to_user((struct mbraink_tracing_pid_data *)arg,
+				 &tracing_pid_buffer,
+				 sizeof(tracing_pid_buffer))) {
+			pr_notice("Copy tracing_pid_buffer to UserSpace error!\n");
+			return -EPERM;
+		}
+		break;
+	}
+	default:
+		pr_notice("illegal ioctl number %u.\n", cmd);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+#if IS_ENABLED(CONFIG_COMPAT)
+static long mbraink_compat_ioctl(struct file *filp,
+				 unsigned int cmd, unsigned long arg)
+{
+	return mbraink_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#endif
+
+static const struct file_operations mbraink_fops = {
+	.owner		= THIS_MODULE,
+	.open		= mbraink_open,
+	.release        = mbraink_release,
+	.unlocked_ioctl = mbraink_ioctl,
+#if IS_ENABLED(CONFIG_COMPAT)
+	.compat_ioctl   = mbraink_compat_ioctl,
+#endif
+};
+
+#if IS_ENABLED(CONFIG_PM_SLEEP)
+static int mbraink_suspend(struct device *dev)
+{
+	int ret;
+
+	ret = pm_generic_suspend(dev);
+
+	return ret;
+}
+
+static int mbraink_resume(struct device *dev)
+{
+	int ret;
+
+	ret = pm_generic_resume(dev);
+
+	return ret;
+}
+
+static const struct dev_pm_ops mbraink_class_dev_pm_ops = {
+	.suspend	= mbraink_suspend,
+	.resume	= mbraink_resume,
+};
+
+#define MBRAINK_CLASS_DEV_PM_OPS (&mbraink_class_dev_pm_ops)
+#else
+#define MBRAINK_CLASS_DEV_PM_OPS NULL
+#endif /*end of CONFIG_PM_SLEEP*/
+
+static void class_create_release(struct class *cls)
+{
+	/*do nothing because the mbraink class is not from malloc*/
+}
+
+static struct class mbraink_class = {
+	.name		= "mbraink_host",
+	.owner		= THIS_MODULE,
+	.class_release	= class_create_release,
+	.pm			= MBRAINK_CLASS_DEV_PM_OPS,
+};
+
+static void device_create_release(struct device *dev)
+{
+	/*do nothing because the mbraink device is not from malloc*/
+}
+
+static struct device mbraink_device = {
+	.init_name	= "mbraink",
+	.release		= device_create_release,
+	.parent		= NULL,
+	.driver_data	= NULL,
+	.class		= NULL,
+	.devt		= 0,
+};
+
+static int mbraink_dev_init(void)
+{
+	dev_t mbraink_dev_no = 0;
+
+	/*Allocating Major number*/
+	if ((alloc_chrdev_region(&mbraink_dev_no, 0, 1, CHRDEV_NAME)) < 0) {
+		pr_notice("Cannot allocate major number %u\n",
+			  mbraink_dev_no);
+		return -EBADF;
+	}
+	pr_info("[MBK_INFO] %s: Major = %u Minor = %u\n",
+		__func__, MAJOR(mbraink_dev_no),
+		MINOR(mbraink_dev_no));
+
+	/*Initialize cdev structure*/
+	cdev_init(&mbraink_priv.mbraink_cdev, &mbraink_fops);
+
+	/*Adding character device to the system*/
+	if ((cdev_add(&mbraink_priv.mbraink_cdev, mbraink_dev_no, 1)) < 0) {
+		pr_notice("Cannot add the device to the system\n");
+		goto r_class;
+	}
+
+	/*Register mbraink class*/
+	if (class_register(&mbraink_class)) {
+		pr_notice("Cannot register the mbraink class %s\n",
+			  mbraink_class.name);
+		goto r_class;
+	}
+
+	/*add mbraink device into mbraink_class host,
+	 *and assign the character device id to mbraink device
+	 */
+
+	mbraink_device.devt = mbraink_dev_no;
+	mbraink_device.class = &mbraink_class;
+
+	/*Register mbraink device*/
+	if (device_register(&mbraink_device)) {
+		pr_notice("Cannot register the Device %s\n",
+			  mbraink_device.init_name);
+		goto r_device;
+	}
+	pr_info("[MBK_INFO] %s: Mbraink device init done.\n", __func__);
+
+	return 0;
+
+r_device:
+	class_unregister(&mbraink_class);
+r_class:
+	unregister_chrdev_region(mbraink_dev_no, 1);
+
+	return -EPERM;
+}
+
+static int mbraink_init(void)
+{
+	int ret = 0;
+
+	ret = mbraink_dev_init();
+	if (ret)
+		pr_notice("mbraink device init failed.\n");
+
+	ret = mbraink_process_tracer_init();
+	if (ret)
+		pr_notice("mbraink tracer init failed.\n");
+
+	return ret;
+}
+
+static void mbraink_dev_exit(void)
+{
+	device_unregister(&mbraink_device);
+	mbraink_device.class = NULL;
+
+	class_unregister(&mbraink_class);
+	cdev_del(&mbraink_priv.mbraink_cdev);
+	unregister_chrdev_region(mbraink_device.devt, 1);
+
+	pr_info("[MBK_INFO] %s: MBraink device exit done, major:minor %u:%u\n",
+		__func__,
+		MAJOR(mbraink_device.devt),
+		MINOR(mbraink_device.devt));
+}
+
+static void mbraink_exit(void)
+{
+	mbraink_dev_exit();
+	mbraink_process_tracer_exit();
+}
+
+module_init(mbraink_init);
+module_exit(mbraink_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("<Wei-chin.Tsai@mediatek.com>");
+MODULE_DESCRIPTION("MBraink Linux Device Driver");
+MODULE_VERSION("1.0");
diff --git a/drivers/misc/mediatek_mbraink/mbraink_main.h b/drivers/misc/mediatek_mbraink/mbraink_main.h
new file mode 100644
index 000000000000..0bb3847cdffb
--- /dev/null
+++ b/drivers/misc/mediatek_mbraink/mbraink_main.h
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2022 MediaTek Inc.
+ */
+
+#ifndef MBRAINK_MAIN_H
+#define MBRAINK_MAIN_H
+
+#include <linux/ioctl.h>
+#include <linux/cdev.h>
+#include <linux/pid.h>
+
+#include "mbraink_ioctl_struct_define.h"
+
+#define IOC_MAGIC	'k'
+
+/*Mbrain Delegate Info List*/
+#define PROCESS_MEMORY_INFO		'4'
+#define TRACE_PROCESS_INFO      'a'
+
+/*Mbrain Delegate IOCTL List*/
+#define RO_PROCESS_MEMORY		_IOR(IOC_MAGIC, PROCESS_MEMORY_INFO, \
+							struct mbraink_process_memory_data*)
+#define RO_TRACE_PROCESS        _IOR(IOC_MAGIC, TRACE_PROCESS_INFO, \
+							struct mbraink_tracing_pid_data*)
+
+struct mbraink_data {
+#define CHRDEV_NAME     "mbraink_chrdev"
+	struct cdev mbraink_cdev;
+};
+
+#endif /*end of MBRAINK_MAIN_H*/
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 6259dd432eeb..814d7829a20b 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -773,8 +773,8 @@ static const struct mm_walk_ops smaps_shmem_walk_ops = {
  *
  * Use vm_start of @vma as the beginning address if @start is 0.
  */
-static void smap_gather_stats(struct vm_area_struct *vma,
-		struct mem_size_stats *mss, unsigned long start)
+void smap_gather_stats(struct vm_area_struct *vma,
+		       struct mem_size_stats *mss, unsigned long start)
 {
 	const struct mm_walk_ops *ops = &smaps_walk_ops;
 
@@ -809,6 +809,7 @@ static void smap_gather_stats(struct vm_area_struct *vma,
 	else
 		walk_page_range(vma->vm_mm, start, vma->vm_end, ops, mss);
 }
+EXPORT_SYMBOL_GPL(smap_gather_stats);
 
 #define SEQ_PUT_DEC(str, val) \
 		seq_put_decimal_ull_width(m, str, (val) >> 10, 8)
diff --git a/kernel/signal.c b/kernel/signal.c
index b5370fe5c198..a1abe77fcdc3 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -4700,6 +4700,7 @@ __weak const char *arch_vma_name(struct vm_area_struct *vma)
 {
 	return NULL;
 }
+EXPORT_SYMBOL_GPL(arch_vma_name);
 
 static inline void siginfo_buildtime_checks(void)
 {
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v1 1/1] memory: export symbols for process memory related functions
  2023-06-12 14:21       ` Wei-chin Tsai (蔡維晉)
@ 2023-06-16  9:24         ` Matthias Brugger
  0 siblings, 0 replies; 5+ messages in thread
From: Matthias Brugger @ 2023-06-16  9:24 UTC (permalink / raw)
  To: Wei-chin Tsai (蔡維晉), willy@infradead.org
  Cc: linux-kernel@vger.kernel.org, Mel Lee (李奇錚),
	linux-mediatek@lists.infradead.org, linux@armlinux.org.uk,
	wsd_upstream, linux-arm-kernel@lists.infradead.org,
	linux-fsdevel@vger.kernel.org,
	Ivan Tseng (曾志軒),
	angelogioacchino.delregno@collabora.com



On 12/06/2023 16:21, Wei-chin Tsai (蔡維晉) wrote:
> On Sat, 2023-06-10 at 01:21 +0100, Matthew Wilcox wrote:
>>   
>> External email : Please do not click links or open attachments until
>> you have verified the sender or the content.
>>  On Fri, Jun 09, 2023 at 04:09:01PM +0000, Wei-chin Tsai (蔡維晉) wrote:
>> > > You haven't included any users of these new exports, so the
>> initial
>> > > reaction is going to be negative - please include the users of
>> these
>> > > new symbols in your patch set.
>> > We use these two export functions from our kernel module to get a
>> > specific user process's memory information and heap usage.
>> Furthermore,
>> > we can use such information to detect the memory leak issues. 
>> > 
>> > The example code is as follows:
>> 
>> No.  You need to be submitting the code that will use the symbol *at
>> the
>> same time* as the patch to export the symbol.  No example code
>> showing
>> how it could be used.  Because if the user isn't compelling, the
>> patch
>> to export the symbol won't be applied either.
> 
> Hi Matthew,
> 
> Got it. The following attached patch file
> "v1-0001-memory-export-symbols-for-process-memory-related-.patch" is
> the patch including the users of these new symbols. Thanks.

Please send both patches as a single series, then we can start review process. I 
had a very quick look on the attached patch and it's missing a good commit 
message describing what the drivers is for and why you need it.

Regards,
Matthias

> 
> Regards,
> 
> Jim
> 
> ************* MEDIATEK Confidentiality Notice ********************
> The information contained in this e-mail message (including any
> attachments) may be confidential, proprietary, privileged, or otherwise
> exempt from disclosure under applicable laws. It is intended to be
> conveyed only to the designated recipient(s). Any use, dissemination,
> distribution, printing, retaining or copying of this e-mail (including its
> attachments) by unintended recipient(s) is strictly prohibited and may
> be unlawful. If you are not an intended recipient of this e-mail, or believe
> that you have received this e-mail in error, please notify the sender
> immediately (by replying to this e-mail), delete any and all copies of
> this e-mail (including any attachments) from your system, and do not
> disclose the content of this e-mail to any other person. Thank you!

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-06-16  9:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20230609110902.13799-1-Wei-chin.Tsai@mediatek.com>
2023-06-09 11:20 ` [PATCH v1 1/1] memory: export symbols for process memory related functions Russell King (Oracle)
2023-06-09 16:09   ` Wei-chin Tsai (蔡維晉)
2023-06-10  0:21     ` Matthew Wilcox
2023-06-12 14:21       ` Wei-chin Tsai (蔡維晉)
2023-06-16  9:24         ` Matthias Brugger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).