mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-08 14:02:37 -04:00
mm/madvise: deduplicate madvise_do_behavior() skip case handlings
The logic for checking if a given madvise() request for a single memory range can skip real work, namely madvise_do_behavior(), is duplicated in do_madvise() and vector_madvise(). Split out the logic to a function and reuse it. Link: https://lkml.kernel.org/r/20250312164750.59215-4-sj@kernel.org Signed-off-by: SeongJae Park <sj@kernel.org> Reviewed-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com> Reviewed-by: Shakeel Butt <shakeel.butt@linux.dev> Cc: David Hildenbrand <david@redhat.com> Cc: Liam R. Howlett <howlett@gmail.com> Cc: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
f4a578d345
commit
0a6ffacb3b
57
mm/madvise.c
57
mm/madvise.c
@@ -1640,6 +1640,31 @@ static bool is_valid_madvise(unsigned long start, size_t len_in, int behavior)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* madvise_should_skip() - Return if the request is invalid or nothing.
|
||||
* @start: Start address of madvise-requested address range.
|
||||
* @len_in: Length of madvise-requested address range.
|
||||
* @behavior: Requested madvise behavor.
|
||||
* @err: Pointer to store an error code from the check.
|
||||
*
|
||||
* If the specified behaviour is invalid or nothing would occur, we skip the
|
||||
* operation. This function returns true in the cases, otherwise false. In
|
||||
* the former case we store an error on @err.
|
||||
*/
|
||||
static bool madvise_should_skip(unsigned long start, size_t len_in,
|
||||
int behavior, int *err)
|
||||
{
|
||||
if (!is_valid_madvise(start, len_in, behavior)) {
|
||||
*err = -EINVAL;
|
||||
return true;
|
||||
}
|
||||
if (start + PAGE_ALIGN(len_in) == start) {
|
||||
*err = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_madvise_populate(int behavior)
|
||||
{
|
||||
switch (behavior) {
|
||||
@@ -1747,23 +1772,15 @@ static int madvise_do_behavior(struct mm_struct *mm,
|
||||
*/
|
||||
int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int behavior)
|
||||
{
|
||||
unsigned long end;
|
||||
int error;
|
||||
size_t len;
|
||||
|
||||
if (!is_valid_madvise(start, len_in, behavior))
|
||||
return -EINVAL;
|
||||
|
||||
len = PAGE_ALIGN(len_in);
|
||||
end = start + len;
|
||||
|
||||
if (end == start)
|
||||
return 0;
|
||||
|
||||
if (madvise_should_skip(start, len_in, behavior, &error))
|
||||
return error;
|
||||
error = madvise_lock(mm, behavior);
|
||||
if (error)
|
||||
return error;
|
||||
error = madvise_do_behavior(mm, start, len_in, len, behavior);
|
||||
error = madvise_do_behavior(mm, start, len_in, PAGE_ALIGN(len_in),
|
||||
behavior);
|
||||
madvise_unlock(mm, behavior);
|
||||
|
||||
return error;
|
||||
@@ -1790,19 +1807,13 @@ static ssize_t vector_madvise(struct mm_struct *mm, struct iov_iter *iter,
|
||||
while (iov_iter_count(iter)) {
|
||||
unsigned long start = (unsigned long)iter_iov_addr(iter);
|
||||
size_t len_in = iter_iov_len(iter);
|
||||
size_t len;
|
||||
int error;
|
||||
|
||||
if (!is_valid_madvise(start, len_in, behavior)) {
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
len = PAGE_ALIGN(len_in);
|
||||
if (start + len == start)
|
||||
ret = 0;
|
||||
if (madvise_should_skip(start, len_in, behavior, &error))
|
||||
ret = error;
|
||||
else
|
||||
ret = madvise_do_behavior(mm, start, len_in, len,
|
||||
behavior);
|
||||
ret = madvise_do_behavior(mm, start, len_in,
|
||||
PAGE_ALIGN(len_in), behavior);
|
||||
/*
|
||||
* An madvise operation is attempting to restart the syscall,
|
||||
* but we cannot proceed as it would not be correct to repeat
|
||||
|
||||
Reference in New Issue
Block a user