mmap: Check if size exceeds available memory when MAP_HUGETLB

If size exceeds, mmap fails and set -ENOMEM

Change-Id: I4f0d6e18ee3a7c8e32e251b7ed07ee9f76305603
Refs: #1183
This commit is contained in:
Ken Sato
2019-07-02 15:42:13 +09:00
committed by Masamichi Takagi
parent 2dd8687974
commit 8efced7bf7
11 changed files with 542 additions and 0 deletions

View File

@ -15,6 +15,7 @@
#include <limits.h>
#include <uio.h>
#include <syscall.h>
#include <rusage_private.h>
#include <ihk/debug.h>
void terminate_mcexec(int, int);
@ -1958,6 +1959,12 @@ SYSCALL_DECLARE(mmap)
goto out;
}
pgsize = (size_t)1 << ((flags >> MAP_HUGE_SHIFT) & 0x3F);
if (rusage_check_overmap(len0,
(flags >> MAP_HUGE_SHIFT) & 0x3F)) {
error = -ENOMEM;
goto out;
}
}
#define VALID_DUMMY_ADDR ((region->user_start + PTL3_SIZE - 1) & ~(PTL3_SIZE - 1))

View File

@ -31,6 +31,7 @@
#include <page.h>
#include <limits.h>
#include <syscall.h>
#include <rusage_private.h>
#include <ihk/debug.h>
void terminate_mcexec(int, int);
@ -1701,6 +1702,12 @@ SYSCALL_DECLARE(mmap)
}
pgsize = (size_t)1 << ((flags >> MAP_HUGE_SHIFT) & 0x3F);
if (rusage_check_overmap(len0,
(flags >> MAP_HUGE_SHIFT) & 0x3F)) {
error = -ENOMEM;
goto out;
}
}
#define VALID_DUMMY_ADDR ((region->user_start + PTL3_SIZE - 1) & ~(PTL3_SIZE - 1))

View File

@ -301,6 +301,23 @@ rusage_check_oom(int numa_id, unsigned long pages, int is_user)
return 0;
}
static inline int
rusage_check_overmap(size_t len, int pgshift)
{
int npages = 0, remain_pages = 0;
npages = (len + (1UL << pgshift) - 1) >> pgshift;
remain_pages = (rusage.total_memory - rusage.total_memory_usage)
>> pgshift;
if (npages > remain_pages) {
/* overmap */
return 1;
}
return 0;
}
static inline void
rusage_page_add(int numa_id, unsigned long pages, int is_user)
{

142
test/issues/1183/C1183.sh Executable file
View File

@ -0,0 +1,142 @@
#!/bin/sh
USELTP=1
USEOSTEST=0
arch=`uname -p`
if [ -f "./${arch}_config" ]; then
. ./${arch}_config
else
echo "$1 is unexpected arch"
exit 1
fi
. ../../common.sh
issue=1183
tid=01
ng=0
echo "*** C${issue}T${tid} start *******************************"
echo "** over-mapping with MAP_HUGETLB (expect mmap FAIL)"
for pgshift in ${PGSHIFT_LIST[@]}
do
echo pageshift: ${pgshift}
${MCEXEC} ./hugemap ${OVERSIZE} ${OVERSIZE} ${pgshift}
if [ $? -ne 0 ]; then
echo "** [OK]"
else
echo "** [NG]"
ng=1
fi
done
if [ ${ng} -eq 0 ]; then
echo "*** C${issue}T${tid}: PASSED"
else
echo "*** C${issue}T${tid}: FAILED"
fi
echo ""
tid=02
ng=0
echo "*** C${issue}T${tid} start *******************************"
echo "** within-mapping with MAP_HUGETLB (expect mmap SUCCESS)"
for pgshift in ${PGSHIFT_LIST[@]}
do
echo pageshift: ${pgshift}
${MCEXEC} ./hugemap ${INSIZE} ${INSIZE} ${pgshift}
if [ $? -eq 0 ]; then
echo "** [OK]"
else
echo "** [NG]"
ng=1
fi
done
if [ ${ng} -eq 0 ]; then
echo "*** C${issue}T${tid}: PASSED"
else
echo "*** C${issue}T${tid}: FAILED"
fi
echo ""
tid=03
ng=0
idx=0
echo "*** C${issue}T${tid} start *******************************"
echo "** multi within-mapping with MAP_HUGETLB"
for pgshift in ${PGSHIFT_LIST[@]}
do
echo pageshift: ${pgshift}
${MCEXEC} ./hugemap `expr ${MEMALL} \* 4` ${INSIZE} ${pgshift}
if [ $? -eq ${MULTI_MAP_RESULT[${idx}]} ]; then
echo "** [OK]"
else
echo "** [NG]"
ng=1
fi
let idx++
done
if [ ${ng} -eq 0 ]; then
echo "*** C${issue}T${tid}: PASSED"
else
echo "*** C${issue}T${tid}: FAILED"
fi
echo ""
tid=04
ng=0
echo "*** C${issue}T${tid} start *******************************"
echo "** over-mapping without MAP_HUGETLB (expect mmap SUCCESS)"
${MCEXEC} ./hugemap ${OVERSIZE} ${OVERSIZE} -1
if [ $? -eq 0 ]; then
echo "** [OK]"
else
echo "** [NG]"
ng=1
fi
if [ ${ng} -eq 0 ]; then
echo "*** C${issue}T${tid}: PASSED"
else
echo "*** C${issue}T${tid}: FAILED"
fi
echo ""
tid=05
ng=0
echo "*** C${issue}T${tid} start *******************************"
echo "** within-mapping without MAP_HUGETLB (expect mmap SUCCESS)"
${MCEXEC} ./hugemap ${INSIZE} ${INSIZE} -1
if [ $? -eq 0 ]; then
echo "** [OK]"
else
echo "** [NG]"
ng=1
fi
if [ ${ng} -eq 0 ]; then
echo "*** C${issue}T${tid}: PASSED"
else
echo "*** C${issue}T${tid}: FAILED"
fi
echo ""
tid=06
ng=0
echo "*** C${issue}T${tid} start *******************************"
echo "** multi within-mapping with MAP_HUGETLB (expect mmap SUCCESS)"
${MCEXEC} ./hugemap `expr ${MEMALL} \* 4` ${INSIZE} -1
if [ $? -eq 0 ]; then
echo "** [OK]"
else
echo "** [NG]"
ng=1
fi
if [ ${ng} -eq 0 ]; then
echo "*** C${issue}T${tid}: PASSED"
else
echo "*** C${issue}T${tid}: FAILED"
fi

17
test/issues/1183/Makefile Normal file
View File

@ -0,0 +1,17 @@
CC = gcc
TARGET=hugemap
CPPFLAGS =
LDFLAGS =
all: $(TARGET)
hugemap: hugemap.c
$(CC) -o $@ $^ $(LDFLAGS)
test: all
@sh ./C1183.sh
clean:
rm -f $(TARGET) *.o

49
test/issues/1183/README Normal file
View File

@ -0,0 +1,49 @@
【Issue#1183 動作確認】
□ テスト内容
テストで扱うメモリサイズについて、以下のように定義する
メモリ総容量McKernelに割り当てられたメモリ量。本テストでは10GB とする
利用可能サイズ:メモリ総容量から、マップ済ページの合計サイズを引いたもの
利用可能サイズを超えるサイズ:本テストではメモリ総容量 + 1GB とする
利用可能サイズを超えないサイズ: 本テストではメモリ総容量 / 2 とする
1. MAP_HUGETLB指定時のmmapの動作確認
C1183T01:
一回のmmapでの要求サイズが、利用可能サイズを超える場合、
利用可能なそれぞれのHugePageSizeでmmapが失敗することを確認する
C1183T02:
一回のmmapでの要求サイズが、利用可能サイズを超えない場合、
利用可能なそれぞれのHugePageSize でmmapが成功することを確認する
C1183T03:
複数回のmmapにおいて、各回のmmapでの要求サイズが利用可能サイズを超えない場合に成功し、
超えた場合に失敗することを確認する
なお、anonymous mmapは連続した物理メモリが確保出来た場合はプリマップをするため、
アーキテクチャごとに下記のような動作となる
- x86_64 : 2MBページ要求時は利用可能サイズが減少していくが、1GBページ要求時は減少しない
- aarch64 : 64KB, 2MBページ要求時は利用可能サイズが減少していくが、32MB, 1GBページ要求時は減少しない
1. MAP_HUGETLB未指定時のmmapの動作確認
C1183T04:
一回のmmapでの要求サイズが、利用可能サイズを超える場合、mmapが成功することを確認する
C1183T05
一回のmmapでの要求サイズが、利用可能サイズを超えない場合、mmapが成功することを確認する
C1183T06:
複数回のmmapにおいて、各回のmmapでの要求サイズが利用可能サイズを超えない場合に成功し、
超えた場合に失敗することを確認する
なお、MAP_HUGETLB未指定時にはプリマップは行われないため、複数回のmmapによっても
利用可能サイズは減少せず、累積のmmap要求サイズがメモリ総容量を超過してもmmapは成功する
□ 実行手順
$ make test
McKernelのインストール先や、OSTEST, LTPの配置場所は、
$HOME/.mck_test_config を参照している
.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
$HOMEにコピーし、適宜編集する
□ 実行結果
x86_64_result.log, aarch64_result.log 参照。
すべての項目をPASSしていることを確認。

View File

@ -0,0 +1,6 @@
MEMALL=10
BOOTPARAM="-c 1-7,9-15 -m ${MEMALL}G@0 -r 1-7:0+9-15:8 -O"
OVERSIZE=`expr ${MEMALL} + 1`
INSIZE=`expr ${MEMALL} / 2`
PGSHIFT_LIST=(0 16 21 25 30)
MULTI_MAP_RESULT=(1 1 1 0 0)

View File

@ -0,0 +1,126 @@
*** C1183T01 start *******************************
** over-mapping with MAP_HUGETLB (expect mmap FAIL)
pageshift: 0
*** total_mapsize: 11 GB, mapsize: 11 pgshift: 0
** mmap 11 GB: failed
** [OK]
pageshift: 16
*** total_mapsize: 11 GB, mapsize: 11 pgshift: 16
** mmap 11 GB: failed
** [OK]
pageshift: 21
*** total_mapsize: 11 GB, mapsize: 11 pgshift: 21
** mmap 11 GB: failed
** [OK]
pageshift: 25
*** total_mapsize: 11 GB, mapsize: 11 pgshift: 25
** mmap 11 GB: failed
** [OK]
pageshift: 30
*** total_mapsize: 11 GB, mapsize: 11 pgshift: 30
** mmap 11 GB: failed
** [OK]
*** C1183T01: PASSED
*** C1183T02 start *******************************
** within-mapping with MAP_HUGETLB (expect mmap SUCCESS)
pageshift: 0
*** total_mapsize: 5 GB, mapsize: 5 pgshift: 0
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
pageshift: 16
*** total_mapsize: 5 GB, mapsize: 5 pgshift: 16
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
pageshift: 21
*** total_mapsize: 5 GB, mapsize: 5 pgshift: 21
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
pageshift: 25
*** total_mapsize: 5 GB, mapsize: 5 pgshift: 25
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
pageshift: 30
*** total_mapsize: 5 GB, mapsize: 5 pgshift: 30
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T02: PASSED
*** C1183T03 start *******************************
** multi within-mapping with MAP_HUGETLB
pageshift: 0
*** total_mapsize: 40 GB, mapsize: 5 pgshift: 0
** mmap 5 GB: succeed
** mmap 5 GB: failed
** [OK]
pageshift: 16
*** total_mapsize: 40 GB, mapsize: 5 pgshift: 16
** mmap 5 GB: succeed
** mmap 5 GB: failed
** [OK]
pageshift: 21
*** total_mapsize: 40 GB, mapsize: 5 pgshift: 21
** mmap 5 GB: succeed
** mmap 5 GB: failed
** [OK]
pageshift: 25
*** total_mapsize: 40 GB, mapsize: 5 pgshift: 25
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
pageshift: 30
*** total_mapsize: 40 GB, mapsize: 5 pgshift: 30
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T03: PASSED
*** C1183T04 start *******************************
** over-mapping without MAP_HUGETLB (expect mmap SUCCESS)
*** total_mapsize: 11 GB, mapsize: 11 pgshift: -1
** mmap 11 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T04: PASSED
*** C1183T05 start *******************************
** within-mapping without MAP_HUGETLB (expect mmap SUCCESS)
*** total_mapsize: 5 GB, mapsize: 5 pgshift: -1
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T05: PASSED
*** C1183T06 start *******************************
** multi within-mapping with MAP_HUGETLB (expect mmap SUCCESS)
*** total_mapsize: 40 GB, mapsize: 5 pgshift: -1
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T06: PASSED

View File

@ -0,0 +1,73 @@
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/mman.h>
#define MAP_HUGE_SHIFT 26
void print_usage(void)
{
printf("usage: hugemap <total_mapsize(GB)> <mapsize(GB)> <pgshift>\n");
}
int mmap_flag(size_t mapsize, int page_shift)
{
char *addr_mmap;
int flags = MAP_ANONYMOUS | MAP_PRIVATE;
if (page_shift >= 0) {
/* mean use MAP_HUGETLB */
flags |= MAP_HUGETLB | (page_shift << MAP_HUGE_SHIFT);
}
addr_mmap = mmap(0, mapsize,
PROT_READ | PROT_WRITE,
flags, -1, 0);
if (addr_mmap == MAP_FAILED) {
return 1;
}
return 0;
}
int main(int argc, char **argv)
{
int ret;
int i;
unsigned long maptotal;
size_t mapsize;
int pgshift;
void *addr = NULL;
if (argc < 4) {
print_usage();
return 1;
}
maptotal = atol(argv[1]) << 30;
mapsize = atol(argv[2]) << 30;
pgshift = atoi(argv[3]);
printf("*** total_mapsize: %ld GB, mapsize: %ld pgshift: %d\n",
maptotal >> 30, mapsize >> 30, pgshift);
for (i = 0; i < maptotal / mapsize; i++) {
printf("** mmap %ld GB: ", mapsize >> 30);
ret = mmap_flag(mapsize, pgshift);
if (ret != 0) {
printf("failed\n");
goto out;
}
else {
printf("succeed\n");
}
}
printf("** all mmaps succeeded\n");
out:
return ret;
}

View File

@ -0,0 +1,7 @@
MEMALL=10
BOOTPARAM="-c 1-7,9-15,17-23,25-31 -m ${MEMALL}G@0 -r 1-7:0+9-15:8+17-23:16+25-31:24 -O"
OVERSIZE=`expr ${MEMALL} + 1`
INSIZE=`expr ${MEMALL} / 2`
PGSHIFT_LIST=(0 21 30)
MULTI_MAP_RESULT=(1 1 0)

View File

@ -0,0 +1,91 @@
*** C1183T01 start *******************************
** over-mapping with MAP_HUGETLB (expect mmap FAIL)
pageshift: 0
*** total_mapsize: 11 GB, mapsize: 11 pgshift: 0
** mmap 11 GB: failed
** [OK]
pageshift: 21
*** total_mapsize: 11 GB, mapsize: 11 pgshift: 21
** mmap 11 GB: failed
** [OK]
pageshift: 30
*** total_mapsize: 11 GB, mapsize: 11 pgshift: 30
** mmap 11 GB: failed
** [OK]
*** C1183T01: PASSED
*** C1183T02 start *******************************
** within-mapping with MAP_HUGETLB (expect mmap SUCCESS)
pageshift: 0
*** total_mapsize: 5 GB, mapsize: 5 pgshift: 0
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
pageshift: 21
*** total_mapsize: 5 GB, mapsize: 5 pgshift: 21
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
pageshift: 30
*** total_mapsize: 5 GB, mapsize: 5 pgshift: 30
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T02: PASSED
*** C1183T03 start *******************************
** multi within-mapping with MAP_HUGETLB
pageshift: 0
*** total_mapsize: 40 GB, mapsize: 5 pgshift: 0
** mmap 5 GB: succeed
** mmap 5 GB: failed
** [OK]
pageshift: 21
*** total_mapsize: 40 GB, mapsize: 5 pgshift: 21
** mmap 5 GB: succeed
** mmap 5 GB: failed
** [OK]
pageshift: 30
*** total_mapsize: 40 GB, mapsize: 5 pgshift: 30
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T03: PASSED
*** C1183T04 start *******************************
** over-mapping without MAP_HUGETLB (expect mmap SUCCESS)
*** total_mapsize: 11 GB, mapsize: 11 pgshift: -1
** mmap 11 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T04: PASSED
*** C1183T05 start *******************************
** within-mapping without MAP_HUGETLB (expect mmap SUCCESS)
*** total_mapsize: 5 GB, mapsize: 5 pgshift: -1
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T05: PASSED
*** C1183T06 start *******************************
** multi within-mapping with MAP_HUGETLB (expect mmap SUCCESS)
*** total_mapsize: 40 GB, mapsize: 5 pgshift: -1
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** mmap 5 GB: succeed
** all mmaps succeeded
** [OK]
*** C1183T06: PASSED