diff --git a/kernel/fileobj.c b/kernel/fileobj.c index 2d74f538..4f468633 100644 --- a/kernel/fileobj.c +++ b/kernel/fileobj.c @@ -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, diff --git a/test/issues/1422/C1422.sh b/test/issues/1422/C1422.sh new file mode 100755 index 00000000..347307a2 --- /dev/null +++ b/test/issues/1422/C1422.sh @@ -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.* + diff --git a/test/issues/1422/Makefile b/test/issues/1422/Makefile new file mode 100644 index 00000000..a2675230 --- /dev/null +++ b/test/issues/1422/Makefile @@ -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 diff --git a/test/issues/1422/README b/test/issues/1422/README new file mode 100644 index 00000000..9f38cbb8 --- /dev/null +++ b/test/issues/1422/README @@ -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していることを確認。 diff --git a/test/issues/1422/filemap_sigbus.c b/test/issues/1422/filemap_sigbus.c new file mode 100644 index 00000000..305d4d06 --- /dev/null +++ b/test/issues/1422/filemap_sigbus.c @@ -0,0 +1,49 @@ +/* filemap_sigbus.c COPYRIGHT FUJITSU LIMITED 2019 */ +#include +#include +#include +#include +#include +#include +#include + +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; +} diff --git a/test/issues/1422/get_rusage.c b/test/issues/1422/get_rusage.c new file mode 100644 index 00000000..a9e0be72 --- /dev/null +++ b/test/issues/1422/get_rusage.c @@ -0,0 +1,109 @@ +/* get_rusage.c COPYRIGHT FUJITSU LIMITED 2019 */ +#include +#include +#include +#include +#include + +static void usage(char *cmd) +{ + printf("Usage:\n"); + printf(" %s \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; +} diff --git a/test/issues/1422/result.log b/test/issues/1422/result.log new file mode 100644 index 00000000..09fce192 --- /dev/null +++ b/test/issues/1422/result.log @@ -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