Add test case 'hugepage_overcommit'

After a successful hugetlb page migration by soft offline, the source
page will either be freed into hugepage_freelists or buddy
(over-commit page). If page is in buddy, page_hstate(page) will be
NULL. It will hit a NULL pointer dereference in
dequeue_hwpoisoned_huge_page().

[  890.677918] BUG: unable to handle kernel NULL pointer dereference at 0000000000000058
[  890.685741] IP: [<ffffffff81163761>] dequeue_hwpoisoned_huge_page+0x131/0x1d0
[  890.692861] PGD c23762067 PUD c24be2067 PMD 0
[  890.697314] Oops: 0000 [#1] SMP

This test case is targeted for the bug reported by Jianguo Wu,
where we have NULL pointer access when we have to free source
hugepage under overcommitting situation.

Signed-off-by: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com>
Signed-off-by: Chen, Gong <gong.chen@linux.intel.com>
diff --git a/cases/function/hwpoison/Makefile b/cases/function/hwpoison/Makefile
index 87020bc..29b4556 100644
--- a/cases/function/hwpoison/Makefile
+++ b/cases/function/hwpoison/Makefile
@@ -1,7 +1,7 @@
 CFLAGS += -I. -g -Wall
 
 EXE := tinjpage tsimpleinj tkillpoison tprctl tsoft tsoftinj
-EXE += thugetlb ttranshuge
+EXE += thugetlb ttranshuge thugetlb_overcommit
 
 OBJ := $(addsuffix .o,${EXE})
 
diff --git a/cases/function/hwpoison/run_hugepage_overcommit.sh b/cases/function/hwpoison/run_hugepage_overcommit.sh
new file mode 100755
index 0000000..51f393e
--- /dev/null
+++ b/cases/function/hwpoison/run_hugepage_overcommit.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+pushd `dirname $0` > /dev/null
+
+. ./helpers.sh
+
+# make sure we have no hwpoisoned hugepage before starting this test.
+free_resources > /dev/null
+
+exec_testcase() {
+	echo "-------------------------------------"
+	local command="./thugetlb_overcommit 1"
+	echo "TestCase $command"
+	sysctl -q vm.nr_overcommit_hugepages=10
+	sysctl -q vm.nr_hugepages=1
+	executed_testcase=$[executed_testcase+1]
+	$command
+	if [ $? -eq 0 ] ; then
+		echo "$command returned with success."
+	else
+		"FAIL: migration failed."
+		failed_testcase=$[failed_testcase+1]
+	fi
+}
+
+cat <<-EOF
+
+***************************************************************************
+Pay attention:
+
+This test checks that hugepage soft-offlining works under overcommitting.
+***************************************************************************
+
+
+EOF
+
+exec_testcase
+
+free_resources
+
+show_summary
+
+popd > /dev/null
+
+exit $failed_testcase
diff --git a/cases/function/hwpoison/thugetlb_overcommit.c b/cases/function/hwpoison/thugetlb_overcommit.c
new file mode 100644
index 0000000..9f97e32
--- /dev/null
+++ b/cases/function/hwpoison/thugetlb_overcommit.c
@@ -0,0 +1,24 @@
+#define _GNU_SOURCE 1
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include "hugepage.h"
+
+#define HPAGE_SIZE (2UL*1024*1024)
+
+#define MADV_SOFT_OFFLINE	101
+
+int main(int argc, char *argv[])
+{
+	int PS = getpagesize();
+	int nr_hugepages;
+	void *addr;
+	int ret;
+
+	nr_hugepages = strtol(argv[1], NULL, 10);
+	addr = alloc_anonymous_hugepage(nr_hugepages * HPAGE_SIZE, 0);
+	write_hugepage(addr, nr_hugepages, NULL);
+	ret = madvise(addr, PS, MADV_SOFT_OFFLINE);
+	free_anonymous_hugepage(addr, nr_hugepages * HPAGE_SIZE);
+	return ret;
+}
diff --git a/groups/function b/groups/function
index 45ffd4e..c2ec85e 100644
--- a/groups/function
+++ b/groups/function
@@ -10,6 +10,7 @@
 HWPOISON-SOFT cases/function/hwpoison/run_soft.sh on
 HWPOISON-HARD cases/function/hwpoison/run_hard.sh on
 HWPOISON-HUGEPAGE cases/function/hwpoison/run_hugepage.sh on
+HWPOISON-HUGEPAGE-OVERCOMMIT cases/function/hwpoison/run_hugepage_overcommit.sh off
 HWPOISON-THP cases/function/hwpoison/run_thp.sh on
 #BSP
 BSP cases/function/bsp/runtest.sh on