Merge branch 'akpm' (patches from Andrew)
Merge misc updates from Andrew Morton: "146 patches. Subsystems affected by this patch series: kthread, ia64, scripts, ntfs, squashfs, ocfs2, vfs, and mm (slab-generic, slab, kmemleak, dax, kasan, debug, pagecache, gup, shmem, frontswap, memremap, memcg, selftests, pagemap, dma, vmalloc, memory-failure, hugetlb, userfaultfd, vmscan, mempolicy, oom-kill, hugetlbfs, migration, thp, ksm, page-poison, percpu, rmap, zswap, zram, cleanups, hmm, and damon)" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: (146 commits) mm/damon: hide kernel pointer from tracepoint event mm/damon/vaddr: hide kernel pointer from damon_va_three_regions() failure log mm/damon/vaddr: use pr_debug() for damon_va_three_regions() failure logging mm/damon/dbgfs: remove an unnecessary variable mm/damon: move the implementation of damon_insert_region to damon.h mm/damon: add access checking for hugetlb pages Docs/admin-guide/mm/damon/usage: update for schemes statistics mm/damon/dbgfs: support all DAMOS stats Docs/admin-guide/mm/damon/reclaim: document statistics parameters mm/damon/reclaim: provide reclamation statistics mm/damon/schemes: account how many times quota limit has exceeded mm/damon/schemes: account scheme actions that successfully applied mm/damon: remove a mistakenly added comment for a future feature Docs/admin-guide/mm/damon/usage: update for kdamond_pid and (mk|rm)_contexts Docs/admin-guide/mm/damon/usage: mention tracepoint at the beginning Docs/admin-guide/mm/damon/usage: remove redundant information Docs/admin-guide/mm/damon/usage: update for scheme quotas and watermarks mm/damon: convert macro functions to static inline functions mm/damon: modify damon_rand() macro to static inline function mm/damon: move damon_rand() definition into damon.h ...
This commit is contained in:
@@ -24,19 +24,23 @@ if [[ "$1" == "-cgroup-v2" ]]; then
|
||||
reservation_usage_file=rsvd.current
|
||||
fi
|
||||
|
||||
cgroup_path=/dev/cgroup/memory
|
||||
if [[ ! -e $cgroup_path ]]; then
|
||||
mkdir -p $cgroup_path
|
||||
if [[ $cgroup2 ]]; then
|
||||
if [[ $cgroup2 ]]; then
|
||||
cgroup_path=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
|
||||
if [[ -z "$cgroup_path" ]]; then
|
||||
cgroup_path=/dev/cgroup/memory
|
||||
mount -t cgroup2 none $cgroup_path
|
||||
else
|
||||
do_umount=1
|
||||
fi
|
||||
echo "+hugetlb" >$cgroup_path/cgroup.subtree_control
|
||||
else
|
||||
cgroup_path=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}')
|
||||
if [[ -z "$cgroup_path" ]]; then
|
||||
cgroup_path=/dev/cgroup/memory
|
||||
mount -t cgroup memory,hugetlb $cgroup_path
|
||||
do_umount=1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $cgroup2 ]]; then
|
||||
echo "+hugetlb" >/dev/cgroup/memory/cgroup.subtree_control
|
||||
fi
|
||||
export cgroup_path
|
||||
|
||||
function cleanup() {
|
||||
if [[ $cgroup2 ]]; then
|
||||
@@ -108,7 +112,7 @@ function setup_cgroup() {
|
||||
|
||||
function wait_for_hugetlb_memory_to_get_depleted() {
|
||||
local cgroup="$1"
|
||||
local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
|
||||
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
|
||||
# Wait for hugetlbfs memory to get depleted.
|
||||
while [ $(cat $path) != 0 ]; do
|
||||
echo Waiting for hugetlb memory to get depleted.
|
||||
@@ -121,7 +125,7 @@ function wait_for_hugetlb_memory_to_get_reserved() {
|
||||
local cgroup="$1"
|
||||
local size="$2"
|
||||
|
||||
local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
|
||||
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$reservation_usage_file"
|
||||
# Wait for hugetlbfs memory to get written.
|
||||
while [ $(cat $path) != $size ]; do
|
||||
echo Waiting for hugetlb memory reservation to reach size $size.
|
||||
@@ -134,7 +138,7 @@ function wait_for_hugetlb_memory_to_get_written() {
|
||||
local cgroup="$1"
|
||||
local size="$2"
|
||||
|
||||
local path="/dev/cgroup/memory/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
|
||||
local path="$cgroup_path/$cgroup/hugetlb.${MB}MB.$fault_usage_file"
|
||||
# Wait for hugetlbfs memory to get written.
|
||||
while [ $(cat $path) != $size ]; do
|
||||
echo Waiting for hugetlb memory to reach size $size.
|
||||
@@ -574,5 +578,7 @@ for populate in "" "-o"; do
|
||||
done # populate
|
||||
done # method
|
||||
|
||||
umount $cgroup_path
|
||||
rmdir $cgroup_path
|
||||
if [[ $do_umount ]]; then
|
||||
umount $cgroup_path
|
||||
rmdir $cgroup_path
|
||||
fi
|
||||
|
||||
@@ -1248,6 +1248,48 @@ TEST_F(hmm, anon_teardown)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Test memory snapshot without faulting in pages accessed by the device.
|
||||
*/
|
||||
TEST_F(hmm, mixedmap)
|
||||
{
|
||||
struct hmm_buffer *buffer;
|
||||
unsigned long npages;
|
||||
unsigned long size;
|
||||
unsigned char *m;
|
||||
int ret;
|
||||
|
||||
npages = 1;
|
||||
size = npages << self->page_shift;
|
||||
|
||||
buffer = malloc(sizeof(*buffer));
|
||||
ASSERT_NE(buffer, NULL);
|
||||
|
||||
buffer->fd = -1;
|
||||
buffer->size = size;
|
||||
buffer->mirror = malloc(npages);
|
||||
ASSERT_NE(buffer->mirror, NULL);
|
||||
|
||||
|
||||
/* Reserve a range of addresses. */
|
||||
buffer->ptr = mmap(NULL, size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE,
|
||||
self->fd, 0);
|
||||
ASSERT_NE(buffer->ptr, MAP_FAILED);
|
||||
|
||||
/* Simulate a device snapshotting CPU pagetables. */
|
||||
ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
|
||||
ASSERT_EQ(ret, 0);
|
||||
ASSERT_EQ(buffer->cpages, npages);
|
||||
|
||||
/* Check what the device saw. */
|
||||
m = buffer->mirror;
|
||||
ASSERT_EQ(m[0], HMM_DMIRROR_PROT_READ);
|
||||
|
||||
hmm_buffer_free(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test memory snapshot without faulting in pages accessed by the device.
|
||||
*/
|
||||
|
||||
@@ -4,7 +4,11 @@
|
||||
*
|
||||
* Example of remapping huge page memory in a user application using the
|
||||
* mremap system call. Code assumes a hugetlbfs filesystem is mounted
|
||||
* at './huge'. The code will use 10MB worth of huge pages.
|
||||
* at './huge'. The amount of memory used by this test is decided by a command
|
||||
* line argument in MBs. If missing, the default amount is 10MB.
|
||||
*
|
||||
* To make sure the test triggers pmd sharing and goes through the 'unshare'
|
||||
* path in the mremap code use 1GB (1024) or more.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
@@ -18,8 +22,10 @@
|
||||
#include <linux/userfaultfd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#define LENGTH (1UL * 1024 * 1024 * 1024)
|
||||
#define DEFAULT_LENGTH_MB 10UL
|
||||
#define MB_TO_BYTES(x) (x * 1024 * 1024)
|
||||
|
||||
#define FILE_NAME "huge/hugepagefile"
|
||||
#define PROTECTION (PROT_READ | PROT_WRITE | PROT_EXEC)
|
||||
#define FLAGS (MAP_SHARED | MAP_ANONYMOUS)
|
||||
|
||||
@@ -28,20 +34,20 @@ static void check_bytes(char *addr)
|
||||
printf("First hex is %x\n", *((unsigned int *)addr));
|
||||
}
|
||||
|
||||
static void write_bytes(char *addr)
|
||||
static void write_bytes(char *addr, size_t len)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
for (i = 0; i < LENGTH; i++)
|
||||
for (i = 0; i < len; i++)
|
||||
*(addr + i) = (char)i;
|
||||
}
|
||||
|
||||
static int read_bytes(char *addr)
|
||||
static int read_bytes(char *addr, size_t len)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
check_bytes(addr);
|
||||
for (i = 0; i < LENGTH; i++)
|
||||
for (i = 0; i < len; i++)
|
||||
if (*(addr + i) != (char)i) {
|
||||
printf("Mismatch at %lu\n", i);
|
||||
return 1;
|
||||
@@ -99,11 +105,19 @@ static void register_region_with_uffd(char *addr, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
/* Read memory length as the first arg if valid, otherwise fallback to
|
||||
* the default length. Any additional args are ignored.
|
||||
*/
|
||||
size_t length = argc > 1 ? (size_t)atoi(argv[1]) : 0UL;
|
||||
|
||||
length = length > 0 ? length : DEFAULT_LENGTH_MB;
|
||||
length = MB_TO_BYTES(length);
|
||||
|
||||
int ret = 0;
|
||||
|
||||
int fd = open("/huge/test", O_CREAT | O_RDWR, 0755);
|
||||
int fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
|
||||
|
||||
if (fd < 0) {
|
||||
perror("Open failed");
|
||||
@@ -112,7 +126,7 @@ int main(void)
|
||||
|
||||
/* mmap to a PUD aligned address to hopefully trigger pmd sharing. */
|
||||
unsigned long suggested_addr = 0x7eaa40000000;
|
||||
void *haddr = mmap((void *)suggested_addr, LENGTH, PROTECTION,
|
||||
void *haddr = mmap((void *)suggested_addr, length, PROTECTION,
|
||||
MAP_HUGETLB | MAP_SHARED | MAP_POPULATE, fd, 0);
|
||||
printf("Map haddr: Returned address is %p\n", haddr);
|
||||
if (haddr == MAP_FAILED) {
|
||||
@@ -122,7 +136,7 @@ int main(void)
|
||||
|
||||
/* mmap again to a dummy address to hopefully trigger pmd sharing. */
|
||||
suggested_addr = 0x7daa40000000;
|
||||
void *daddr = mmap((void *)suggested_addr, LENGTH, PROTECTION,
|
||||
void *daddr = mmap((void *)suggested_addr, length, PROTECTION,
|
||||
MAP_HUGETLB | MAP_SHARED | MAP_POPULATE, fd, 0);
|
||||
printf("Map daddr: Returned address is %p\n", daddr);
|
||||
if (daddr == MAP_FAILED) {
|
||||
@@ -132,16 +146,16 @@ int main(void)
|
||||
|
||||
suggested_addr = 0x7faa40000000;
|
||||
void *vaddr =
|
||||
mmap((void *)suggested_addr, LENGTH, PROTECTION, FLAGS, -1, 0);
|
||||
mmap((void *)suggested_addr, length, PROTECTION, FLAGS, -1, 0);
|
||||
printf("Map vaddr: Returned address is %p\n", vaddr);
|
||||
if (vaddr == MAP_FAILED) {
|
||||
perror("mmap2");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
register_region_with_uffd(haddr, LENGTH);
|
||||
register_region_with_uffd(haddr, length);
|
||||
|
||||
void *addr = mremap(haddr, LENGTH, LENGTH,
|
||||
void *addr = mremap(haddr, length, length,
|
||||
MREMAP_MAYMOVE | MREMAP_FIXED, vaddr);
|
||||
if (addr == MAP_FAILED) {
|
||||
perror("mremap");
|
||||
@@ -150,10 +164,10 @@ int main(void)
|
||||
|
||||
printf("Mremap: Returned address is %p\n", addr);
|
||||
check_bytes(addr);
|
||||
write_bytes(addr);
|
||||
ret = read_bytes(addr);
|
||||
write_bytes(addr, length);
|
||||
ret = read_bytes(addr, length);
|
||||
|
||||
munmap(addr, LENGTH);
|
||||
munmap(addr, length);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -18,19 +18,24 @@ if [[ "$1" == "-cgroup-v2" ]]; then
|
||||
usage_file=current
|
||||
fi
|
||||
|
||||
CGROUP_ROOT='/dev/cgroup/memory'
|
||||
MNT='/mnt/huge/'
|
||||
|
||||
if [[ ! -e $CGROUP_ROOT ]]; then
|
||||
mkdir -p $CGROUP_ROOT
|
||||
if [[ $cgroup2 ]]; then
|
||||
if [[ $cgroup2 ]]; then
|
||||
CGROUP_ROOT=$(mount -t cgroup2 | head -1 | awk -e '{print $3}')
|
||||
if [[ -z "$CGROUP_ROOT" ]]; then
|
||||
CGROUP_ROOT=/dev/cgroup/memory
|
||||
mount -t cgroup2 none $CGROUP_ROOT
|
||||
sleep 1
|
||||
echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control
|
||||
else
|
||||
do_umount=1
|
||||
fi
|
||||
echo "+hugetlb +memory" >$CGROUP_ROOT/cgroup.subtree_control
|
||||
else
|
||||
CGROUP_ROOT=$(mount -t cgroup | grep ",hugetlb" | awk -e '{print $3}')
|
||||
if [[ -z "$CGROUP_ROOT" ]]; then
|
||||
CGROUP_ROOT=/dev/cgroup/memory
|
||||
mount -t cgroup memory,hugetlb $CGROUP_ROOT
|
||||
do_umount=1
|
||||
fi
|
||||
fi
|
||||
MNT='/mnt/huge/'
|
||||
|
||||
function get_machine_hugepage_size() {
|
||||
hpz=$(grep -i hugepagesize /proc/meminfo)
|
||||
|
||||
@@ -111,7 +111,7 @@ fi
|
||||
echo "-----------------------"
|
||||
echo "running hugepage-mremap"
|
||||
echo "-----------------------"
|
||||
./hugepage-mremap
|
||||
./hugepage-mremap 256
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "[FAIL]"
|
||||
exitcode=1
|
||||
|
||||
@@ -87,7 +87,7 @@ static bool test_uffdio_minor = false;
|
||||
|
||||
static bool map_shared;
|
||||
static int shm_fd;
|
||||
static int huge_fd = -1; /* only used for hugetlb_shared test */
|
||||
static int huge_fd;
|
||||
static char *huge_fd_off0;
|
||||
static unsigned long long *count_verify;
|
||||
static int uffd = -1;
|
||||
@@ -223,9 +223,6 @@ static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
|
||||
|
||||
static void hugetlb_release_pages(char *rel_area)
|
||||
{
|
||||
if (huge_fd == -1)
|
||||
return;
|
||||
|
||||
if (fallocate(huge_fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
|
||||
rel_area == huge_fd_off0 ? 0 : nr_pages * page_size,
|
||||
nr_pages * page_size))
|
||||
@@ -238,17 +235,17 @@ static void hugetlb_allocate_area(void **alloc_area)
|
||||
char **alloc_area_alias;
|
||||
|
||||
*alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
|
||||
map_shared ? MAP_SHARED :
|
||||
MAP_PRIVATE | MAP_HUGETLB |
|
||||
(map_shared ? MAP_SHARED : MAP_PRIVATE) |
|
||||
MAP_HUGETLB |
|
||||
(*alloc_area == area_src ? 0 : MAP_NORESERVE),
|
||||
huge_fd,
|
||||
*alloc_area == area_src ? 0 : nr_pages * page_size);
|
||||
huge_fd, *alloc_area == area_src ? 0 :
|
||||
nr_pages * page_size);
|
||||
if (*alloc_area == MAP_FAILED)
|
||||
err("mmap of hugetlbfs file failed");
|
||||
|
||||
if (map_shared) {
|
||||
area_alias = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
MAP_SHARED | MAP_HUGETLB,
|
||||
huge_fd, *alloc_area == area_src ? 0 :
|
||||
nr_pages * page_size);
|
||||
if (area_alias == MAP_FAILED)
|
||||
@@ -648,7 +645,7 @@ static int uffd_read_msg(int ufd, struct uffd_msg *msg)
|
||||
|
||||
if (ret != sizeof(*msg)) {
|
||||
if (ret < 0) {
|
||||
if (errno == EAGAIN)
|
||||
if (errno == EAGAIN || errno == EINTR)
|
||||
return 1;
|
||||
err("blocking read error");
|
||||
} else {
|
||||
@@ -724,8 +721,11 @@ static void *uffd_poll_thread(void *arg)
|
||||
|
||||
for (;;) {
|
||||
ret = poll(pollfd, 2, -1);
|
||||
if (ret <= 0)
|
||||
if (ret <= 0) {
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
err("poll error: %d", ret);
|
||||
}
|
||||
if (pollfd[1].revents & POLLIN) {
|
||||
if (read(pollfd[1].fd, &tmp_chr, 1) != 1)
|
||||
err("read pipefd error");
|
||||
@@ -1417,7 +1417,6 @@ static void userfaultfd_pagemap_test(unsigned int test_pgsize)
|
||||
static int userfaultfd_stress(void)
|
||||
{
|
||||
void *area;
|
||||
char *tmp_area;
|
||||
unsigned long nr;
|
||||
struct uffdio_register uffdio_register;
|
||||
struct uffd_stats uffd_stats[nr_cpus];
|
||||
@@ -1528,13 +1527,9 @@ static int userfaultfd_stress(void)
|
||||
count_verify[nr], nr);
|
||||
|
||||
/* prepare next bounce */
|
||||
tmp_area = area_src;
|
||||
area_src = area_dst;
|
||||
area_dst = tmp_area;
|
||||
swap(area_src, area_dst);
|
||||
|
||||
tmp_area = area_src_alias;
|
||||
area_src_alias = area_dst_alias;
|
||||
area_dst_alias = tmp_area;
|
||||
swap(area_src_alias, area_dst_alias);
|
||||
|
||||
uffd_stats_report(uffd_stats, nr_cpus);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ want_sleep=$8
|
||||
reserve=$9
|
||||
|
||||
echo "Putting task in cgroup '$cgroup'"
|
||||
echo $$ > /dev/cgroup/memory/"$cgroup"/cgroup.procs
|
||||
echo $$ > ${cgroup_path:-/dev/cgroup/memory}/"$cgroup"/cgroup.procs
|
||||
|
||||
echo "Method is $method"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user