Implement MPOL_PREFERRED as MPOL_LOCAL when nodeset is empty.

After 7858d7bca7fb ("mm/mempolicy: don't handle MPOL_LOCAL like a
fake MPOL_PREFERRED policy"), MPOL_PREFERRED is implemented as
MPOL_LOCAL when nodeset is empty.

Earlier, MPOL_LOCAL was implemented as MPOL_PREFERRED and kernel
checked that nodeset was empty.

Fixed the syscall test to avoid this conversion process. We don't
know which machine our native tests will run on, so it is hard to
test for either of these conversions of MPOL modes. In this state
the syscall test passes on newer and older kernels.

PiperOrigin-RevId: 460560999
This commit is contained in:
Ayush Ranjan
2022-07-12 15:06:40 -07:00
committed by gVisor bot
parent aadfe7f23c
commit dbe5a4abd9
2 changed files with 18 additions and 10 deletions
+9 -5
View File
@@ -294,16 +294,20 @@ func copyInMempolicyNodemask(t *kernel.Task, modeWithFlags linux.NumaPolicy, nod
}
case linux.MPOL_PREFERRED:
// This permits an empty nodemask, as long as no flags are set.
if nodemaskVal == 0 && flags != 0 {
return 0, 0, linuxerr.EINVAL
if nodemaskVal == 0 {
if flags != 0 {
return 0, 0, linuxerr.EINVAL
}
// On newer Linux versions, MPOL_PREFERRED is implemented as MPOL_LOCAL
// when node set is empty. See 7858d7bca7fb ("mm/mempolicy: don't handle
// MPOL_LOCAL like a fake MPOL_PREFERRED policy").
mode = linux.MPOL_LOCAL
}
case linux.MPOL_LOCAL:
// This requires an empty nodemask and no flags set ...
// This requires an empty nodemask and no flags set.
if nodemaskVal != 0 || flags != 0 {
return 0, 0, linuxerr.EINVAL
}
// ... and is implemented as MPOL_PREFERRED.
mode = linux.MPOL_PREFERRED
default:
// Unknown mode, which we should have rejected above.
panic(fmt.Sprintf("unknown mode: %v", mode))
+9 -5
View File
@@ -260,9 +260,11 @@ TEST(MempolicyTest, GetMempolicyNextInterleaveNode) {
}
TEST(MempolicyTest, Mbind) {
uint64_t nodemask = 0x1;
// Temporarily set the thread policy to MPOL_PREFERRED.
const auto cleanup_thread_policy =
ASSERT_NO_ERRNO_AND_VALUE(ScopedSetMempolicy(MPOL_PREFERRED, nullptr, 0));
ASSERT_NO_ERRNO_AND_VALUE(ScopedSetMempolicy(
MPOL_PREFERRED, &nodemask, sizeof(nodemask) * BITS_PER_BYTE));
const auto mapping = ASSERT_NO_ERRNO_AND_VALUE(
MmapAnon(kPageSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS));
@@ -274,10 +276,12 @@ TEST(MempolicyTest, Mbind) {
SyscallSucceeds());
EXPECT_EQ(mode, MPOL_DEFAULT);
// Set MPOL_PREFERRED for the vma and read it back.
ASSERT_THAT(
mbind(mapping.ptr(), mapping.len(), MPOL_PREFERRED, nullptr, 0, 0),
SyscallSucceeds());
// Set MPOL_PREFERRED for the vma and read it back. Note that setting
// MPOL_PREFERRED with an empty node set will set mode to MPOL_LOCAL on newer
// Linux releases.
ASSERT_THAT(mbind(mapping.ptr(), mapping.len(), MPOL_PREFERRED, &nodemask,
sizeof(nodemask) * BITS_PER_BYTE, 0),
SyscallSucceeds());
ASSERT_THAT(get_mempolicy(&mode, nullptr, 0, mapping.ptr(), MPOL_F_ADDR),
SyscallSucceeds());
EXPECT_EQ(mode, MPOL_PREFERRED);