getrusage: Fix memory_stat_mapped_file when SIGBUS occurs in file map

Change-Id: Ia4686f32a3c888d5c886ab6cc6c2b510885447f5
Refs: #1422
This commit is contained in:
Yoshihisa Morizumi
2020-08-27 23:51:37 +09:00
committed by Masamichi Takagi
parent baa7a6adcb
commit 9c7d0cfaec
7 changed files with 397 additions and 15 deletions

View File

@ -557,10 +557,8 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
struct fileobj *obj = to_fileobj(memobj);
int error = -1;
void *virt = NULL;
int npages;
uintptr_t phys = -1;
struct page *page;
struct pageio_args *args = NULL;
struct mcs_lock_node mcs_node;
int hash = (off >> PAGE_SHIFT) & FILEOBJ_PAGE_HASH_MASK;
@ -608,7 +606,6 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
*physp = virt_to_phys(virt);
dkprintf("%s: MF_ZEROFILL: off: %lu -> 0x%lx resolved\n",
__FUNCTION__, off, virt_to_phys(virt));
virt = NULL;
goto out_nolock;
}
@ -616,6 +613,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
page = __fileobj_page_hash_lookup(obj, hash, off);
if (!page || (page->mode == PM_WILL_PAGEIO)
|| (page->mode == PM_PAGEIO)) {
struct pageio_args *args;
args = kmalloc(sizeof(*args), IHK_MC_AP_NOWAIT);
if (!args) {
error = -ENOMEM;
@ -626,7 +624,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
}
if (!page) {
npages = 1 << p2align;
int npages = 1 << p2align;
virt = ihk_mc_alloc_pages_user(npages, (IHK_MC_AP_NOWAIT |
((to_memobj(obj)->flags & MF_ZEROFILL) ?
@ -638,6 +636,7 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
"alloc failed. %d\n",
obj, off, p2align, virt_addr, physp,
error);
kfree(args);
goto out;
}
phys = virt_to_phys(virt);
@ -666,8 +665,6 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
proc->pgio_arg = args;
error = -ERESTART;
virt = NULL;
args = NULL;
goto out;
}
else if (page->mode == PM_DONE_PAGEIO) {
@ -676,11 +673,11 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
}
else if (page->mode == PM_PAGEIO_EOF) {
error = -ERANGE;
goto out;
goto pageio_error;
}
else if (page->mode == PM_PAGEIO_ERROR) {
error = -EIO;
goto out;
goto pageio_error;
}
ihk_atomic_inc(&page->count);
@ -688,19 +685,22 @@ static int fileobj_get_page(struct memobj *memobj, off_t off,
error = 0;
*physp = page_to_phys(page);
virt = NULL;
out:
mcs_lock_unlock(&obj->page_hash_locks[hash], &mcs_node);
out_nolock:
if (virt) {
ihk_mc_free_pages_user(virt, npages);
}
if (args) {
kfree(args);
}
dkprintf("fileobj_get_page(%p,%lx,%x,%x,%p): %d %lx\n",
obj, off, p2align, virt_addr, physp, error, phys);
return error;
pageio_error:
__fileobj_page_hash_remove(page);
virt = phys_to_virt(page_to_phys(page));
if (page_unmap(page)) {
ihk_mc_free_pages_user(virt, 1);
kfree(page);
}
goto out;
}
static int fileobj_flush_page(struct memobj *memobj, uintptr_t phys,

74
test/issues/1422/C1422.sh Executable file
View File

@ -0,0 +1,74 @@
#!/bin/sh
USELTP=1
USEOSTEST=1
BOOTPARAM="-c 12-15 -m 512M@4"
. ../../common.sh
echo ""
echo "*** get_rusage test"
echo a > ./tmp
BEFORE_STR=`./get_rusage 0 | grep "memory_stat_mapped_file"`
$MCEXEC ./filemap_sigbus ./tmp
AFTER_STR=`./get_rusage 0 | grep "memory_stat_mapped_file"`
if [ "${BEFORE_STR}" == "${AFTER_STR}" ]; then
echo "TEST OK."
else
echo "TEST NG."
echo "${BEFORE_STR}"
echo "${AFTER_STR}"
fi
rm -f ./tmp
echo ""
echo "*** LTP"
# mmap01 - 09, 12 - 15
for i in `seq -f "%02g" 1 1 9` `seq -f "%02g" 12 1 15` ; do
$MCEXEC $LTPBIN/mmap$i
done
echo ""
echo "*** ostest, check ok"
for i in 0 2 4 6 10 11 32 34 36 38 40 41 42 43 48 ; do
echo a > ./tmp
$MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp \
| grep "RESULT: ok" > /dev/null
if [ $? -eq 0 ] ; then
echo "[OK] mmap_file $i"
else
echo "[NG] mmap_file $i"
fi
rm -f ./tmp
done
echo ""
echo "*** otest, check mmap error."
for i in 8 9 `seq 16 1 31` ; do
echo a > ./tmp
$MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp \
| grep "RESULT: mmap error." > /dev/null
if [ $? -eq 0 ] ; then
echo "[OK] mmap_file $i"
else
echo "[NG] mmap_file $i"
fi
rm -f ./tmp
done
echo ""
echo "*** oetest, check page fault"
for i in 1 3 5 7 12 13 14 15 33 35 37 39 44 45 46 47 ; do
echo a > ./tmp
$MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
if [ $? -eq 139 ] ; then
echo "[OK] mmap_file $i"
else
echo "[NG] mmap_file $i"
fi
rm -f ./tmp
done
rm -f core.* mccore-filemap_sigbus.* mccore-test_mck.*

14
test/issues/1422/Makefile Normal file
View File

@ -0,0 +1,14 @@
include $(HOME)/.mck_test_config.mk
CFLAGS=-g -O0 -Wall -I$(MCK_DIR)/include
LDFLAGS=-L$(MCK_DIR)/lib64 -lihk -Wl,-rpath=$(MCK_DIR)/lib64
all:
$(CC) $(CFLAGS) $(LDFLAGS) get_rusage.c -o get_rusage
$(CC) $(CFLAGS) filemap_sigbus.c -o filemap_sigbus
test: all
./C1422.sh
clean:
rm -f get_rusage filemap_sigbus

31
test/issues/1422/README Normal file
View File

@ -0,0 +1,31 @@
【Issue#1422 動作確認】
□ テスト内容
1. ファイルマップのEOFを超えたアクセスでSIGBUSが発生した場合に、
memory_stat_mapped_fileがマイナスにならないことを確認する。
2. ファイルマップ機能が正常に動作することを、LTPの以下のテストで確認する。
mmap01 mmap01
mmap02 mmap02
mmap03 mmap03
mmap04 mmap04
mmap05 mmap05
mmap06 mmap06
mmap07 mmap07
mmap08 mmap08
mmap09 mmap09
mmap12 mmap12
mmap13 mmap13
mmap14 mmap14
mmap15 mmap15
3. ファイルマップ機能が正常に動作することを、ostestの mmap_fileで確認する。
□ 実行手順
$ make test
McKernelのインストール先や、OSTEST, LTPの配置場所は、
$HOME/.mck_test_config を参照している。
.mck_test_config は、McKernelをビルドした際に生成されるmck_test_config.sample ファイルを
$HOMEにコピーし、適宜編集する。
□ 実行結果
result.log を参照。
すべての項目にPASSしていることを確認。

View File

@ -0,0 +1,49 @@
/* filemap_sigbus.c COPYRIGHT FUJITSU LIMITED 2019 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
int main(int argc, char *argv[])
{
int ret = -1;
int fd = -1;
int i = 0;
unsigned long *buf = NULL;
const long pgsize = sysconf(_SC_PAGESIZE);
if (argc != 2) {
printf("args invalid.\n");
ret = 0;
goto out;
}
fd = open(argv[1], O_RDWR);
if (fd == -1) {
perror("open");
goto out;
}
buf = (unsigned long *)mmap(0, 3 * pgsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE, fd, 0);
if (buf == MAP_FAILED) {
perror("mmap");
goto out;
}
/* Generate SIGBUS */
for (i = 0; i < 3 * pgsize / sizeof(unsigned long); i++) {
buf[i] = i;
}
munmap(buf, 3 * pgsize);
close(fd);
ret = 0;
out:
return ret;
}

View File

@ -0,0 +1,109 @@
/* get_rusage.c COPYRIGHT FUJITSU LIMITED 2019 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ihklib.h>
#include <ihk/ihk_rusage.h>
static void usage(char *cmd)
{
printf("Usage:\n");
printf(" %s <os_number>\n", cmd);
}
int main(int argc, char *argv[])
{
int os_num = 0;
int ret = -1;
int i = 0;
int nonzero = 0;
struct ihk_os_rusage mck_rusage;
if (argc != 2) {
usage(argv[0]);
goto out;
}
os_num = atoi(argv[1]);
if (os_num < 0 || 63 < os_num) {
printf("Invalid argument 1 os_num.\n");
usage(argv[0]);
goto out;
}
memset(&mck_rusage, 0, sizeof(mck_rusage));
ret = ihk_os_getrusage(os_num, &mck_rusage, sizeof(mck_rusage));
if (ret) {
perror("ihk_os_getrusage()");
goto out;
}
printf("show rusage:\n");
nonzero = 0;
for (i = 0; i < IHK_MAX_NUM_PGSIZES; i++) {
if (mck_rusage.memory_stat_rss[i] != 0) {
printf(" memory_stat_rss[%d] : 0x%lx\n", i,
mck_rusage.memory_stat_rss[i]);
nonzero = 1;
}
}
if (nonzero == 0) {
printf(" memory_stat_rss is all 0x0\n");
}
nonzero = 0;
for (i = 0; i < IHK_MAX_NUM_PGSIZES; i++) {
if (mck_rusage.memory_stat_mapped_file[i] != 0) {
printf(" memory_stat_mapped_file[%d] : 0x%lx\n", i,
mck_rusage.memory_stat_mapped_file[i]);
nonzero = 1;
}
}
if (nonzero == 0) {
printf(" memory_stat_mapped_file is all 0x0\n");
}
printf(" memory_max_usage : 0x%lx\n", mck_rusage.memory_max_usage);
printf(" memory_kmem_usage : 0x%lx\n", mck_rusage.memory_kmem_usage);
printf(" memory_kmem_max_usage : 0x%lx\n",
mck_rusage.memory_kmem_max_usage);
nonzero = 0;
for (i = 0; i < IHK_MAX_NUM_NUMA_NODES; i++) {
if (mck_rusage.memory_numa_stat[i] != 0) {
printf(" memory_numa_stat[%d] : 0x%lx\n", i,
mck_rusage.memory_numa_stat[i]);
nonzero = 1;
}
}
if (nonzero == 0) {
printf(" memory_numa_stat is all 0x0\n");
}
printf(" cpuacct_stat_system : 0x%lx\n",
mck_rusage.cpuacct_stat_system);
printf(" cpuacct_stat_user : 0x%lx\n", mck_rusage.cpuacct_stat_user);
printf(" cpuacct_usage : 0x%lx\n", mck_rusage.cpuacct_usage);
nonzero = 0;
for (i = 0; i < IHK_MAX_NUM_CPUS; i++) {
if (mck_rusage.cpuacct_usage_percpu[i] != 0) {
printf(" cpuacct_usage_percpu[%d] : 0x%lx\n", i,
mck_rusage.cpuacct_usage_percpu[i]);
nonzero = 1;
}
}
if (nonzero == 0) {
printf(" cpuacct_usage_percpu is all 0x0\n");
}
printf(" num_threads : 0x%x\n", mck_rusage.num_threads);
printf(" max_num_threads : 0x%x\n", mck_rusage.max_num_threads);
out:
return ret;
}

105
test/issues/1422/result.log Normal file
View File

@ -0,0 +1,105 @@
cc -g -O0 -Wall -I/root/mck/target/include -L/root/mck/target/lib64 -lihk -Wl,-rpath=/root/mck/target/lib64 get_rusage.c -o get_rusage
cc -g -O0 -Wall -I/root/mck/target/include filemap_sigbus.c -o filemap_sigbus
./C1422.sh
mcstop+release.sh ... done
mcreboot.sh -c 12-15 -m 512M@4 ... done
*** get_rusage test
./C1422.sh: line 12: 453200 Bus error (core dumped) $MCEXEC ./filemap_sigbus ./tmp
TEST OK.
*** LTP
mmap01 1 TPASS : Functionality of mmap() successful
mmap02 1 TPASS : Functionality of mmap() successful
mmap03 1 TPASS : mmap() functionality is correct
mmap04 1 TPASS : Functionality of mmap() successful
mmap05 1 TPASS : Got SIGSEGV as expected
mmap06 1 TPASS : mmap failed with EACCES
mmap07 1 TPASS : mmap failed with EACCES
mmap08 1 TPASS : mmap failed with EBADF
mmap09 1 TPASS : ftruncate mmaped file to a smaller size
mmap09 2 TPASS : ftruncate mmaped file to a larger size
mmap09 3 TPASS : ftruncate mmaped file to 0 size
tst_test.c:1096: INFO: Timeout per run is 0h 05m 00s
mmap12.c:103: INFO: All pages are present
mmap12.c:127: PASS: File mapped properly
Summary:
passed 1
failed 0
skipped 0
warnings 0
mmap13 1 TPASS : Got SIGBUS as expected
mmap14 1 TPASS : Functionality of mmap() successful
mmap15 1 TPASS : mmap into high region failed as expected: errno=ENOMEM(12): Cannot allocate memory
*** ostest, check ok
[OK] mmap_file 0
[OK] mmap_file 2
[OK] mmap_file 4
[OK] mmap_file 6
[OK] mmap_file 10
[OK] mmap_file 11
[OK] mmap_file 32
[OK] mmap_file 34
[OK] mmap_file 36
[OK] mmap_file 38
[OK] mmap_file 40
[OK] mmap_file 41
[OK] mmap_file 42
[OK] mmap_file 43
[OK] mmap_file 48
*** otest, check mmap error.
[OK] mmap_file 8
[OK] mmap_file 9
[OK] mmap_file 16
[OK] mmap_file 17
[OK] mmap_file 18
[OK] mmap_file 19
[OK] mmap_file 20
[OK] mmap_file 21
[OK] mmap_file 22
[OK] mmap_file 23
[OK] mmap_file 24
[OK] mmap_file 25
[OK] mmap_file 26
[OK] mmap_file 27
[OK] mmap_file 28
[OK] mmap_file 29
[OK] mmap_file 30
[OK] mmap_file 31
*** oetest, check page fault
./C1422.sh: line 60: 453714 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 1
./C1422.sh: line 60: 453724 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 3
./C1422.sh: line 60: 453734 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 5
./C1422.sh: line 60: 453744 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 7
./C1422.sh: line 60: 453754 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 12
./C1422.sh: line 60: 453764 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 13
./C1422.sh: line 60: 453774 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 14
./C1422.sh: line 60: 453784 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 15
./C1422.sh: line 60: 453794 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 33
./C1422.sh: line 60: 453804 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 35
./C1422.sh: line 60: 453814 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 37
./C1422.sh: line 60: 453824 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 39
./C1422.sh: line 60: 453836 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 44
./C1422.sh: line 60: 453846 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 45
./C1422.sh: line 60: 453856 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 46
./C1422.sh: line 60: 453866 Segmentation fault (core dumped) $MCEXEC $TESTMCK -s mmap_file -n $i -- -f ./tmp > /dev/null
[OK] mmap_file 47