From: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
To: SeongJae Park <sj@kernel.org>
Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com>,
Andrew Morton <akpm@linux-foundation.org>,
David Hildenbrand <david@redhat.com>,
Shakeel Butt <shakeel.butt@linux.dev>,
Vlastimil Babka <vbabka@suse.cz>,
linux-kernel@vger.kernel.org, linux-mm@kvack.org
Subject: Re: [RFC PATCH v2 4/4] mm/madvise: remove redundant mmap_lock operations from process_madvise()
Date: Fri, 31 Jan 2025 16:53:17 +0000 [thread overview]
Message-ID: <aeeac6f3-f828-4bee-966f-c8df41df30bc@lucifer.local> (raw)
In-Reply-To: <20250117013058.1843-5-sj@kernel.org>
On Thu, Jan 16, 2025 at 05:30:58PM -0800, SeongJae Park wrote:
> Optimize redundant mmap lock operations from process_madvise() by
> directly doing the mmap locking first, and then the remaining works for
> all ranges in the loop.
>
> Signed-off-by: SeongJae Park <sj@kernel.org>
I wonder if this might increase lock contention because now all of the
vector operations will hold the relevant mm lock without releasing after
each operation?
Probably it's ok given limited size of iov, but maybe in future we'd want
to set a limit on the ranges before we drop/reacquire lock?
I've tested this against my PIDFD_SELF changes [0] and the
process_madvise() invocation in the guard-pages tests which utilises
process_madvise() in a perhaps 'unusual' way so is a good test bed for
this, and all working fine.
Amazingly, this appears to be the only place (afaict) where
process_madivse() is actually tested...
Buuuut, I think this change is incorrect, I comment on this below. Should
be an easy fix though.
[0]:https://lore.kernel.org/all/cover.1738268370.git.lorenzo.stoakes@oracle.com/
> ---
> mm/madvise.c | 22 ++++++++++++++++++++--
> 1 file changed, 20 insertions(+), 2 deletions(-)
>
> diff --git a/mm/madvise.c b/mm/madvise.c
> index 913936a5c353..1a796a03a4fb 100644
> --- a/mm/madvise.c
> +++ b/mm/madvise.c
> @@ -1752,9 +1752,26 @@ static ssize_t vector_madvise(struct mm_struct *mm, struct iov_iter *iter,
>
> total_len = iov_iter_count(iter);
>
> + ret = madvise_lock(mm, behavior);
> + if (ret)
> + return ret;
> +
> while (iov_iter_count(iter)) {
> - ret = do_madvise(mm, (unsigned long)iter_iov_addr(iter),
> - iter_iov_len(iter), behavior);
> + unsigned long start = (unsigned long)iter_iov_addr(iter);
This is nicer than just passing in.
> + size_t len_in = iter_iov_len(iter);
Equally so here...
> + size_t len;
> +
> + if (!is_valid_madvise(start, len_in, behavior)) {
> + ret = -EINVAL;
> + break;
> + }
> +
> + len = PAGE_ALIGN(len_in);
> + if (start + len == start)
> + ret = 0;
> + else
> + ret = madvise_do_behavior(mm, start, len_in, len,
> + behavior);
Very slight duplication here (I wonder if we can somehow wrap the 'if zero
length return 0' thing?).
But it doesn't really matter, probably better to spell it out, actually.
> /*
> * An madvise operation is attempting to restart the syscall,
> * but we cannot proceed as it would not be correct to repeat
> @@ -1776,6 +1793,7 @@ static ssize_t vector_madvise(struct mm_struct *mm, struct iov_iter *iter,
> break;
> iov_iter_advance(iter, iter_iov_len(iter));
> }
> + madvise_unlock(mm, behavior);
>
> ret = (total_len - iov_iter_count(iter)) ? : ret;
So I think this is now wrong because of the work I did recently. In this code:
/*
* An madvise operation is attempting to restart the syscall,
* but we cannot proceed as it would not be correct to repeat
* the operation in aggregate, and would be surprising to the
* user.
*
* As we have already dropped locks, it is safe to just loop and
* try again. We check for fatal signals in case we need exit
* early anyway.
*/
if (ret == -ERESTARTNOINTR) {
if (fatal_signal_pending(current)) {
ret = -EINTR;
break;
}
continue;
}
Note that it assumes the locks have been dropped before simply trying
again, as the only way this would happen is because of a race, and we may
end up stuck in a loop if we just hold on to the lock.
So I'd suggest updating this comment and changing the code like this:
if (ret == -ERESTARTNOINTR) {
if (fatal_signal_pending(current)) {
ret = -EINTR;
break;
}
+ /* Drop and reacquire lock to unwind race. */
+ madvise_unlock(mm, behaviour);
+ madvise_lock(mm, behaviour);
continue;
}
Which brings back the existing behaviour.
By the way I hate that this function swallows error codes. But that's not
your fault, and is now established user-facing behaviour so yeah. Big sigh.
>
> --
> 2.39.5
next prev parent reply other threads:[~2025-01-31 16:53 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-17 1:30 [RFC PATCH v2 0/4] " SeongJae Park
2025-01-17 1:30 ` [RFC PATCH v2 1/4] mm/madvise: split out mmap locking operations for madvise() SeongJae Park
2025-01-29 19:18 ` Shakeel Butt
2025-01-31 15:58 ` Lorenzo Stoakes
2025-01-31 17:33 ` Davidlohr Bueso
2025-01-17 1:30 ` [RFC PATCH v2 2/4] mm/madvise: split out madvise input validity check SeongJae Park
2025-01-29 19:18 ` Shakeel Butt
2025-01-31 16:01 ` Lorenzo Stoakes
2025-01-31 19:19 ` Davidlohr Bueso
2025-01-17 1:30 ` [RFC PATCH v2 3/4] mm/madvise: split out madvise() behavior execution SeongJae Park
2025-01-29 19:19 ` Shakeel Butt
2025-01-31 16:10 ` Lorenzo Stoakes
2025-01-17 1:30 ` [RFC PATCH v2 4/4] mm/madvise: remove redundant mmap_lock operations from process_madvise() SeongJae Park
2025-01-29 19:20 ` Shakeel Butt
2025-01-31 16:53 ` Lorenzo Stoakes [this message]
2025-01-31 17:31 ` Davidlohr Bueso
2025-01-31 17:47 ` Liam R. Howlett
2025-01-31 17:51 ` Lorenzo Stoakes
2025-01-31 17:58 ` Davidlohr Bueso
2025-02-04 19:53 ` SeongJae Park
2025-02-06 6:28 ` SeongJae Park
2025-05-17 19:28 ` Lorenzo Stoakes
2025-05-19 18:25 ` SeongJae Park
2025-01-31 19:17 ` Shakeel Butt
2025-02-04 18:56 ` SeongJae Park
2025-01-29 19:22 ` [RFC PATCH v2 0/4] " Shakeel Butt
2025-01-29 21:09 ` SeongJae Park
2025-01-31 16:04 ` Liam R. Howlett
2025-01-31 16:30 ` SeongJae Park
2025-01-31 16:55 ` Lorenzo Stoakes
2025-01-31 17:53 ` Lorenzo Stoakes
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=aeeac6f3-f828-4bee-966f-c8df41df30bc@lucifer.local \
--to=lorenzo.stoakes@oracle.com \
--cc=Liam.Howlett@oracle.com \
--cc=akpm@linux-foundation.org \
--cc=david@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=shakeel.butt@linux.dev \
--cc=sj@kernel.org \
--cc=vbabka@suse.cz \
/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