mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andrew Morton <akpm@linux-foundation.org>
To: thnkslprpt@gmail.com, brads@mainlining.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH 3/3] profile: simplify /proc/profile read layout
Date: Tue, 20 Oct 2026 18:27:36 -0700	[thread overview]
Message-ID: <20261020182736.26ac79b01dd02ecda8a89ab6@linux-foundation.org> (raw)
In-Reply-To: <e7e8de4d10204573a54c2044c060379b.3@linux-foundation.org>

On Tue, 20 Oct 2026 17:52:03 -0700 Andrew Morton <akpm@linux-foundation.org> wrote:

> read_profile() is needlessly difficult to understand.  It copies the
> four-byte sampling-step header one byte at a time, then manufactures
> a pointer before prof_buffer so a file offset can be used as a
> counter-array offset.  Its signed byte counter, unsigned long file
> offset and repeated size calculations further obscure where each
> read starts and how many bytes it transfers.
> 
> Treat the file as two consecutive regions: a four-byte header and
> the profiling counters.  Use size_t for byte positions and lengths,
> copy the bounded header in one operation, and address the counters
> relative to the start of prof_buffer.  Brief comments explain each
> region.
> 
> Keep the word-sized shift and explicit narrowing required by Avi
> Weiss's "profiling: fix sampling step on 64-bit big-endian systems".
> Assign the header value separately and explain why the 32-bit ABI
> requires a narrowing conversion.
> 
> Preserve the partial-read and fault semantics established by [1/2],
> including short copies within either region.  No userspace-visible
> behavior change is intended.

Me:0, Sashiko:1

revised version, I'll resend in a few days.  I tested 32-bit now.


From: Andrew Morton <akpm@linux-foundation.org>
Subject: profile: simplify /proc/profile read layout
Date: Tue, 20 Oct 2026 23:58:33 +0000

read_profile() is needlessly difficult to understand.  It copies the
four-byte sampling-step header one byte at a time, then manufactures
a pointer before prof_buffer so a file offset can be used as a
counter-array offset.  Its signed byte counter, unsigned long file
offset and repeated size calculations further obscure where each
read starts and how many bytes it transfers.

Treat the file as two consecutive regions: a four-byte header and
the profiling counters.  Use size_t for byte positions and lengths,
copy the bounded header in one operation, and address the counters
relative to the start of prof_buffer.  Retain the full loff_t value
for EOF and negative-offset checks before narrowing it to size_t.
Brief comments explain each region.

Keep the word-sized shift and explicit narrowing required by Avi
Weiss's "profiling: fix sampling step on 64-bit big-endian systems".
Assign the header value separately and explain why the 32-bit ABI
requires a narrowing conversion.

Preserve the partial-read and fault semantics established by [1/2],
including short copies within either region.  The full-width offset
check also prevents 32-bit pread64() offsets from wrapping into earlier
profile data.  No other userspace-visible
behavior change is intended.

Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---
Tested the combined three-patch series on x86-64 and i686 QEMU/KVM
guests with CONFIG_PROFILING=y and profile=12.
profile-read-test.c: PASS (0 failures) on both architectures.
Covered short and unaligned reads, header boundaries, EOF, partial
user-copy faults, return values, file positions and retry behavior.
The 64-bit big-endian sampling-step fix was not runtime tested.
No separate per-patch or unpatched-versus-patched run was reported.

 kernel/profile.c |   61 ++++++++++++++++++++++++++++-----------------
 1 file changed, 39 insertions(+), 22 deletions(-)

--- a/kernel/profile.c~profile-simplify-proc-profile-read-layout
+++ a/kernel/profile.c
@@ -153,35 +153,52 @@ void profile_tick(int type)
 static ssize_t
 read_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos)
 {
-	unsigned long p = *ppos;
-	ssize_t read;
-	char *pnt;
-	unsigned int sample_step = (unsigned int)(1UL << prof_shift);
-	size_t not_copied;
+	const size_t header_size = sizeof(unsigned int);
+	const size_t file_size = (prof_len + 1) * sizeof(unsigned int);
+	unsigned int sample_step;
+	loff_t offset = *ppos;
+	size_t pos;
+	size_t done = 0;
+	size_t n, not_copied;
 
-	if (p >= (prof_len+1)*sizeof(unsigned int))
+	/* Keep the shift word-sized before narrowing to the 32-bit ABI. */
+	sample_step = (unsigned int)(1UL << prof_shift);
+
+	if (offset < 0)
+		return -EINVAL;
+	if (offset >= file_size)
 		return 0;
-	if (count > (prof_len+1)*sizeof(unsigned int) - p)
-		count = (prof_len+1)*sizeof(unsigned int) - p;
-	read = 0;
+	pos = offset;
+	count = min(count, file_size - pos);
 
-	while (p < sizeof(unsigned int) && count > 0) {
-		if (put_user(*((char *)(&sample_step)+p), buf))
-			goto out;
-		buf++; p++; count--; read++;
+	/* Copy the four-byte sampling resolution. */
+	if (pos < header_size) {
+		n = min(count, header_size - pos);
+		not_copied = copy_to_user(buf, (u8 *)&sample_step + pos, n);
+		done += n - not_copied;
+		if (not_copied)
+			goto fault;
+		buf += n;
+		pos += n;
+		count -= n;
 	}
+
+	/* Copy raw counters using offsets relative to the counter array. */
 	if (count) {
-		pnt = (char *)prof_buffer + p - sizeof(atomic_t);
-		not_copied = copy_to_user(buf, pnt, count);
-		read += count - not_copied;
+		not_copied = copy_to_user(buf,
+					(u8 *)prof_buffer + pos - header_size,
+					count);
+		done += count - not_copied;
 		if (not_copied)
-			goto out;
+			goto fault;
 	}
-	*ppos += read;
-	return read;
-out:
-	*ppos += read;
-	return read ? read : -EFAULT;
+	*ppos += done;
+	return done;
+fault:
+	*ppos += done;
+	if (!done)
+		return -EFAULT;
+	return done;
 }
 
 /* default is to not implement this call */
_


      reply	other threads:[~2026-10-21  1:27 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-21  0:51 [PATCH 1/3] profiling: fix sampling step on 64-bit big-endian systems Andrew Morton
2026-10-21  0:52 ` [PATCH 2/3] profile: account for partial /proc/profile reads Andrew Morton
2026-10-21  0:52 ` [PATCH 3/3] profile: simplify /proc/profile read layout Andrew Morton
2026-10-21  1:27   ` Andrew Morton [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261020182736.26ac79b01dd02ecda8a89ab6@linux-foundation.org \
    --to=akpm@linux-foundation.org \
    --cc=brads@mainlining.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=thnkslprpt@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®