Skip to contentSkip to conversation

move hugepage test examples to tools/testing/selftests/vm

PATCH In review Dave Young 4 participants 12 messages Feb 5, 2012 – Feb 10, 2012

Subsystems (3)
lore
Share & tools
lore

Dave Young

author
#0 lore raw

PATCH 3/3 move hugepage test examples to tools/testing/selftests/vm

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_test to do such work which will call the three test programs and check the return value of them.

Changes to original code including below:
a. add run_test script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

---
 Documentation/vm/Makefile                          |    8 --
 tools/testing/selftests/Makefile                   |    2 +-
 tools/testing/selftests/run_tests                  |    6 +-
 tools/testing/selftests/vm/Makefile                |   11 +++
 .../testing/selftests}/vm/hugepage-mmap.c          |   13 ++--
 .../testing/selftests}/vm/hugepage-shm.c           |   10 ++-
 .../testing/selftests}/vm/map_hugetlb.c            |   10 ++-
 tools/testing/selftests/vm/run_test                |   77 ++++++++++++++++++++
 8 files changed, 112 insertions(+), 25 deletions(-)
 delete mode 100644 Documentation/vm/Makefile
 create mode 100644 tools/testing/selftests/vm/Makefile
 rename {Documentation => tools/testing/selftests}/vm/hugepage-mmap.c (93%)
 rename {Documentation => tools/testing/selftests}/vm/hugepage-shm.c (94%)
 rename {Documentation => tools/testing/selftests}/vm/map_hugetlb.c (94%)
 create mode 100755 tools/testing/selftests/vm/run_test
Documentation/vm/Makefile deleted +0 -8
deleted file mode 100644
index e538864..0000000
@@ -1,8 +0,0 @@
-# kbuild trick to avoid linker error. Can be omitted if a module is built.
-obj- := dummy.o
-
-# List of programs to build
-hostprogs-y := hugepage-mmap hugepage-shm map_hugetlb
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
tools/testing/selftests/Makefile +1 -1
index 4ec8401..9a72fe5 100644
@@ -1,4 +1,4 @@
-TARGETS = breakpoints
+TARGETS = breakpoints vm
 
 all:
 	for TARGET in $(TARGETS); do \
tools/testing/selftests/run_tests +4 -2
index 320718a..1f4a5ef 100644
@@ -1,8 +1,10 @@
 #!/bin/bash
 
-TARGETS=breakpoints
+TARGETS="breakpoints vm"
 
 for TARGET in $TARGETS
 do
-	$TARGET/run_test
+	cd "$TARGET"
+	./run_test
+	cd ..
 done
tools/testing/selftests/vm/Makefile new file +11 -0
new file mode 100644
index 0000000..537ec38
@@ -0,0 +1,11 @@
+# Makefile for vm selftests
+
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -Wall -Wextra
+
+all: hugepage-mmap hugepage-shm  map_hugetlb
+%: %.c
+	$(CC) $(CFLAGS) -o $@ $^
+
+clean:
+	$(RM) hugepage-mmap hugepage-shm  map_hugetlb
tools/testing/selftests/vm/hugepage-mmap.c renamed from Documentation/vm/hugepage-mmap.c +7 -6
similarity index 93%
rename from Documentation/vm/hugepage-mmap.c
rename to tools/testing/selftests/vm/hugepage-mmap.c
index db0dd9a..a10f310 100644
@@ -22,7 +22,7 @@
 #include <sys/mman.h>
 #include <fcntl.h>
 
-#define FILE_NAME "/mnt/hugepagefile"
+#define FILE_NAME "huge/hugepagefile"
 #define LENGTH (256UL*1024*1024)
 #define PROTECTION (PROT_READ | PROT_WRITE)
 
@@ -48,7 +48,7 @@ static void write_bytes(char *addr)
 		*(addr + i) = (char)i;
 }
 
-static void read_bytes(char *addr)
+static int read_bytes(char *addr)
 {
 	unsigned long i;
 
@@ -56,14 +56,15 @@ static void read_bytes(char *addr)
 	for (i = 0; i < LENGTH; i++)
 		if (*(addr + i) != (char)i) {
 			printf("Mismatch at %lu\n", i);
-			break;
+			return 1;
 		}
+	return 0;
 }
 
 int main(void)
 {
 	void *addr;
-	int fd;
+	int fd, ret;
 
 	fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
 	if (fd < 0) {
@@ -81,11 +82,11 @@ int main(void)
 	printf("Returned address is %p\n", addr);
 	check_bytes(addr);
 	write_bytes(addr);
-	read_bytes(addr);
+	ret = read_bytes(addr);
 
 	munmap(addr, LENGTH);
 	close(fd);
 	unlink(FILE_NAME);
 
-	return 0;
+	return ret;
 }
tools/testing/selftests/vm/hugepage-shm.c renamed from Documentation/vm/hugepage-shm.c +6 -4
similarity index 94%
rename from Documentation/vm/hugepage-shm.c
rename to tools/testing/selftests/vm/hugepage-shm.c
index 07956d8..0d0ef4f 100644
@@ -57,8 +57,8 @@ int main(void)
 	unsigned long i;
 	char *shmaddr;
 
-	if ((shmid = shmget(2, LENGTH,
-			    SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
+	shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
+	if (shmid < 0) {
 		perror("shmget");
 		exit(1);
 	}
@@ -82,14 +82,16 @@ int main(void)
 
 	dprintf("Starting the Check...");
 	for (i = 0; i < LENGTH; i++)
-		if (shmaddr[i] != (char)i)
+		if (shmaddr[i] != (char)i) {
 			printf("\nIndex %lu mismatched\n", i);
+			exit(3);
+		}
 	dprintf("Done.\n");
 
 	if (shmdt((const void *)shmaddr) != 0) {
 		perror("Detach failure");
 		shmctl(shmid, IPC_RMID, NULL);
-		exit(3);
+		exit(4);
 	}
 
 	shmctl(shmid, IPC_RMID, NULL);
tools/testing/selftests/vm/map_hugetlb.c renamed from Documentation/vm/map_hugetlb.c +6 -4
similarity index 94%
rename from Documentation/vm/map_hugetlb.c
rename to tools/testing/selftests/vm/map_hugetlb.c
index eda1a6d..ac56639 100644
@@ -44,7 +44,7 @@ static void write_bytes(char *addr)
 		*(addr + i) = (char)i;
 }
 
-static void read_bytes(char *addr)
+static int read_bytes(char *addr)
 {
 	unsigned long i;
 
@@ -52,13 +52,15 @@ static void read_bytes(char *addr)
 	for (i = 0; i < LENGTH; i++)
 		if (*(addr + i) != (char)i) {
 			printf("Mismatch at %lu\n", i);
-			break;
+			return 1;
 		}
+	return 0;
 }
 
 int main(void)
 {
 	void *addr;
+	int ret;
 
 	addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
 	if (addr == MAP_FAILED) {
@@ -69,9 +71,9 @@ int main(void)
 	printf("Returned address is %p\n", addr);
 	check_bytes(addr);
 	write_bytes(addr);
-	read_bytes(addr);
+	ret = read_bytes(addr);
 
 	munmap(addr, LENGTH);
 
-	return 0;
+	return ret;
 }
tools/testing/selftests/vm/run_test new file +77 -0

77 lines not on this page · raw message

Signature · 8 lines
1.7.4.4

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
maintainer
#1 lore raw
Quoted 8 lines · On Sun, 5 Feb 2012 16:15:55 +0800 Dave Young <[email protected]> wrote:

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_test to do such work which will call the three test programs and check the return value of them.

Quoted 5 lines

Changes to original code including below:
a. add run_test script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

I think Frederic is doing away with tools/testing/selftests/run_tests in favour of a Makefile target? ("make run_tests", for example).

Until we see such a patch we cannot finalise your patch and if I apply your patch, his patch will need more work. Not that this is rocket science ;)

tools/testing/selftests/vm/run_test

Quoted 5 lines

...

tools/testing/selftests/vm/run_test new file +0 -0

(We now have a "run_tests" and a "run_test". The difference in naming is irritating)

Your vm/run_test file does quite a lot of work and we couldn't sensibly move all its functionality into Makefile, I expect.

So I think it's OK to retain a script for this, but I do think that we should think up a standardized way of invoking it from vm/Makefile, so the top-level Makefile in tools/testing/selftests can simply do "cd vm;make run_test", where the run_test target exists in all subdirectories. The vm/Makefile run_test target can then call out to the script.

Also, please do not assume that the script has the x bit set. The x bit easily gets lost on kernel scripts (patch(1) can lose it) so it is safer to invoke the script via "/bin/sh script-name" or $SHELL or whatever.

Anyway, we should work with Frederic on sorting out some standard behavior before we can finalize this work, please.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#2 lore raw
Quoted 17 lines · Andrew Morton
Quoted 8 lines · On Sun, 5 Feb 2012 16:15:55 +0800 Dave Young <[email protected]> wrote:

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_test to do such work which will call the three test programs and check the return value of them.

Quoted 5 lines

Changes to original code including below:
a. add run_test script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

Quoted 8 lines

I think Frederic is doing away with tools/testing/selftests/run_tests in favour of a Makefile target? ("make run_tests", for example).

Until we see such a patch we cannot finalise your patch and if I apply your patch, his patch will need more work. Not that this is rocket science ;)

Understand.

Quoted 9 lines

tools/testing/selftests/vm/run_test

Quoted 6 lines

...

tools/testing/selftests/vm/run_test new file +0 -0

(We now have a "run_tests" and a "run_test". The difference in naming is irritating)

Yes, I'm just refer to the breakpoints/Makefile which will make a target breakpoints/run_test

Quoted 10 lines

Your vm/run_test file does quite a lot of work and we couldn't sensibly move all its functionality into Makefile, I expect.

So I think it's OK to retain a script for this, but I do think that we should think up a standardized way of invoking it from vm/Makefile, so the top-level Makefile in tools/testing/selftests can simply do "cd vm;make run_test", where the run_test target exists in all subdirectories. The vm/Makefile run_test target can then call out to the script.

Frederic, do you have any idea about this?

Quoted 5 lines

Also, please do not assume that the script has the x bit set. The x bit easily gets lost on kernel scripts (patch(1) can lose it) so it is safer to invoke the script via "/bin/sh script-name" or $SHELL or whatever.

Agree, and quilt can not keep the x bit as well, I have to use git to create a executable shell script

Quoted 4 lines

Anyway, we should work with Frederic on sorting out some standard behavior before we can finalize this work, please.

Fine, I can redo this after the standard behavior is out

Signature · 9 lines
Thanks
Dave

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#3 lore raw

PATCH 1/1 selftests: Launch individual selftests from the main Makefile

In reply to Andrew Morton
Quoted 43 lines · Andrew Morton
Quoted 8 lines · On Sun, 5 Feb 2012 16:15:55 +0800 Dave Young <[email protected]> wrote:

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_test to do such work which will call the three test programs and check the return value of them.

Quoted 5 lines

Changes to original code including below:
a. add run_test script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

I think Frederic is doing away with tools/testing/selftests/run_tests in favour of a Makefile target? ("make run_tests", for example).

Until we see such a patch we cannot finalise your patch and if I apply your patch, his patch will need more work. Not that this is rocket science ;)

tools/testing/selftests/vm/run_test

Quoted 5 lines

...

tools/testing/selftests/vm/run_test new file +0 -0

(We now have a "run_tests" and a "run_test". The difference in naming is irritating)

Your vm/run_test file does quite a lot of work and we couldn't sensibly move all its functionality into Makefile, I expect.

So I think it's OK to retain a script for this, but I do think that we should think up a standardized way of invoking it from vm/Makefile, so the top-level Makefile in tools/testing/selftests can simply do "cd vm;make run_test", where the run_test target exists in all subdirectories. The vm/Makefile run_test target can then call out to the script.

Quoted 8 lines

Also, please do not assume that the script has the x bit set. The x bit easily gets lost on kernel scripts (patch(1) can lose it) so it is safer to invoke the script via "/bin/sh script-name" or $SHELL or whatever.

Anyway, we should work with Frederic on sorting out some standard behavior before we can finalize this work, please.

Ok. Would the following patch work?

---
From: Frederic Weisbecker <[email protected]>
Date: Wed, 8 Feb 2012 04:21:46 +0100
Subject: [PATCH] selftests: Launch individual selftests from the main
Makefile

Drop the run_tests script and launch the selftests by calling "make run_tests" from the selftests top directory instead. This delegates to the Makefile on each selftest directory where it is decided how to launch the local test.

This drops the need to add each selftest directory on the now removed "run_tests" top script.

---
 tools/testing/selftests/Makefile             |    5 +++++
 tools/testing/selftests/breakpoints/Makefile |    7 +++++--
 tools/testing/selftests/run_tests            |    8 --------
 3 files changed, 10 insertions(+), 10 deletions(-)
 delete mode 100644 tools/testing/selftests/run_tests
tools/testing/selftests/Makefile +5 -0
index 4ec8401..b1119f0 100644
@@ -5,6 +5,11 @@ all:
 		make -C $$TARGET; \
 	done;
 
+run_tests:
+	for TARGET in $(TARGETS); do \
+		make -C $$TARGET run_tests; \
+	done;
+
 clean:
 	for TARGET in $(TARGETS); do \
 		make -C $$TARGET clean; \
tools/testing/selftests/breakpoints/Makefile +5 -2
index f362722..9312780 100644
@@ -11,10 +11,13 @@ endif
 
 all:
 ifeq ($(ARCH),x86)
-	gcc breakpoint_test.c -o run_test
+	gcc breakpoint_test.c -o breakpoint_test
 else
 	echo "Not an x86 target, can't build breakpoints selftests"
 endif
 
+run_tests:
+	./breakpoint_test
+
 clean:
-	rm -fr run_test
+	rm -fr breakpoint_test
tools/testing/selftests/run_tests deleted +0 -8
deleted file mode 100644
index 320718a..0000000
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-TARGETS=breakpoints
-
-for TARGET in $TARGETS
-do
-	$TARGET/run_test
-done
Signature · 9 lines
1.7.5.4


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#4 lore raw

Re: [PATCH] selftests: Launch individual selftests from the main Makefile

Note that slub also has an embedded selftest (see function resiliency_test). That code could be separated out and put with the selftests that you are creating now.

I also have a series of in kernel benchmarks for the page allocation, vm statistics and slab allocators that could be useful to included somewhere.

All this code runs in the kernel context.

For the in kernel benchmarks I am creating modules that fail to load but first run the tests.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#5 lore raw

Re: [PATCH] selftests: Launch individual selftests from the main Makefile

Quoted 3 lines · Christoph Lameter

Note that slub also has an embedded selftest (see function resiliency_test). That code could be separated out and put with the selftests that you are creating now.

That would be nice. As long as it's in userspace and it runs validation tests, it's pretty welcome.

It's deemed to test expected behaviour with deterministic tests. stress tests probably don't fit well there although it should be no problem if they are short.

Quoted 7 lines

I also have a series of in kernel benchmarks for the page allocation, vm statistics and slab allocators that could be useful to included somewhere.

All this code runs in the kernel context.

For the in kernel benchmarks I am creating modules that fail to load but first run the tests.

Hmm, benchmarks tend to require some user analysis, I'm not sure if a batch of validation tests is the right place for them. But loading modules is probably not a problem.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#6 lore raw

Re: [PATCH] selftests: Launch individual selftests from the main Makefile

In reply to Frederic Weisbecker
Quoted 7 lines · On Wed, 8 Feb 2012 04:40:59 +0100 Frederic Weisbecker <[email protected]>…

Drop the run_tests script and launch the selftests by calling "make run_tests" from the selftests top directory instead. This delegates to the Makefile on each selftest directory where it is decided how to launch the local test.

This drops the need to add each selftest directory on the now removed "run_tests" top script.

Looks good.

I did

cd tools/testing/selftests
make run_tests

and it didn't work. This?

From: Andrew Morton <[email protected]>
Subject: selftests/Makefile: make run_tests' depend on all'

So a "make run_tests" will build the tests before trying to run them.

Cc Frederic Weisbecker <[email protected]>

---

 tools/testing/selftests/Makefile |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/Makefile renamed from tools/testing/selftests/Makefile~a +1 -1
diff -puN tools/testing/selftests/Makefile~a tools/testing/selftests/Makefile
@@ -5,7 +5,7 @@ all:
 		make -C $$TARGET; \
 	done;
 
-run_tests:
+run_tests: all
 	for TARGET in $(TARGETS); do \
 		make -C $$TARGET run_tests; \
 	done;

_

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#7 lore raw

Re: [PATCH] selftests: Launch individual selftests from the main Makefile

Quoted 38 lines · Andrew Morton
Quoted 7 lines · On Wed, 8 Feb 2012 04:40:59 +0100 Frederic Weisbecker <[email protected]>…

Drop the run_tests script and launch the selftests by calling "make run_tests" from the selftests top directory instead. This delegates to the Makefile on each selftest directory where it is decided how to launch the local test.

This drops the need to add each selftest directory on the now removed "run_tests" top script.

Looks good.

I did

cd tools/testing/selftests
make run_tests

and it didn't work. This?

From: Andrew Morton <[email protected]>
Subject: selftests/Makefile: make run_tests' depend on all'

So a "make run_tests" will build the tests before trying to run them.

Cc Frederic Weisbecker <[email protected]>

---

 tools/testing/selftests/Makefile |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff -puN tools/testing/selftests/Makefile~a tools/testing/selftests/Makefile

tools/testing/selftests/Makefile all: · line 11

Quoted 8 lines
tools/testing/selftests/Makefile renamed from tools/testing/selftests/Makefile~a +1 -1
@@ -5,7 +5,7 @@ all:
 		make -C $$TARGET; \
 	done;
 
-run_tests:
+run_tests: all
 	for TARGET in $(TARGETS); do \
 		make -C $$TARGET run_tests; \
 	done;

Yeah that's good. Thanks!

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#8 lore raw
In reply to Andrew Morton
Quoted 43 lines · Andrew Morton
Quoted 8 lines · On Sun, 5 Feb 2012 16:15:55 +0800 Dave Young <[email protected]> wrote:

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_test to do such work which will call the three test programs and check the return value of them.

Quoted 5 lines

Changes to original code including below:
a. add run_test script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

I think Frederic is doing away with tools/testing/selftests/run_tests in favour of a Makefile target? ("make run_tests", for example).

Until we see such a patch we cannot finalise your patch and if I apply your patch, his patch will need more work. Not that this is rocket science ;)

tools/testing/selftests/vm/run_test

Quoted 5 lines

...

tools/testing/selftests/vm/run_test new file +0 -0

(We now have a "run_tests" and a "run_test". The difference in naming is irritating)

Your vm/run_test file does quite a lot of work and we couldn't sensibly move all its functionality into Makefile, I expect.

So I think it's OK to retain a script for this, but I do think that we should think up a standardized way of invoking it from vm/Makefile, so the top-level Makefile in tools/testing/selftests can simply do "cd vm;make run_test", where the run_test target exists in all subdirectories. The vm/Makefile run_test target can then call out to the script.

Quoted 8 lines

Also, please do not assume that the script has the x bit set. The x bit easily gets lost on kernel scripts (patch(1) can lose it) so it is safer to invoke the script via "/bin/sh script-name" or $SHELL or whatever.

Anyway, we should work with Frederic on sorting out some standard behavior before we can finalize this work, please.

Andrew, updated the patch as below, is it ok to you?
---

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_vmtests to do such work which will call the three test programs and check the return value of them.

Changes to original code including below:
a. add run_vmtests script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

[v1 -> v2]:
1. [akpm:] rebased on runing make run_tests from Makefile
2. [akpm:] rename test script from run_test ro run_vmtests
2. fix a bug about shell exit code checking

---
 Documentation/vm/Makefile                  |    8 --
 Documentation/vm/hugepage-mmap.c           |   91 --------------------------
 Documentation/vm/hugepage-shm.c            |   98 ----------------------------
 Documentation/vm/map_hugetlb.c             |   77 ----------------------
 tools/testing/selftests/Makefile           |    2 
 tools/testing/selftests/vm/Makefile        |   14 ++++
 tools/testing/selftests/vm/hugepage-mmap.c |   92 ++++++++++++++++++++++++++
 tools/testing/selftests/vm/hugepage-shm.c  |  100 +++++++++++++++++++++++++++++
 tools/testing/selftests/vm/map_hugetlb.c   |   79 ++++++++++++++++++++++
 tools/testing/selftests/vm/run_vmtests     |   77 ++++++++++++++++++++++
 10 files changed, 363 insertions(+), 275 deletions(-)
Documentation/vm/Makefile deleted +0 -8
@@ -1,8 +0,0 @@
-# kbuild trick to avoid linker error. Can be omitted if a module is built.
-obj- := dummy.o
-
-# List of programs to build
-hostprogs-y := hugepage-mmap hugepage-shm map_hugetlb
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
Documentation/vm/hugepage-mmap.c deleted +0 -91

91 lines not on this page · raw message

Documentation/vm/hugepage-shm.c deleted +0 -98

98 lines not on this page · raw message

Documentation/vm/map_hugetlb.c deleted +0 -77

77 lines not on this page · raw message

tools/testing/selftests/Makefile +1 -1
@@ -1,4 +1,4 @@
-TARGETS = breakpoints
+TARGETS = breakpoints vm
 
 all:
 	for TARGET in $(TARGETS); do \
tools/testing/selftests/vm/Makefile new file +14 -0
@@ -0,0 +1,14 @@
+# Makefile for vm selftests
+
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -Wall -Wextra
+
+all: hugepage-mmap hugepage-shm  map_hugetlb
+%: %.c
+	$(CC) $(CFLAGS) -o $@ $^
+
+run_tests:
+	/bin/sh ./run_vmtests
+
+clean:
+	$(RM) hugepage-mmap hugepage-shm  map_hugetlb
tools/testing/selftests/vm/hugepage-mmap.c new file +92 -0

92 lines not on this page · raw message

tools/testing/selftests/vm/hugepage-shm.c new file +100 -0

100 lines not on this page · raw message

tools/testing/selftests/vm/map_hugetlb.c new file +79 -0

79 lines not on this page · raw message

tools/testing/selftests/vm/run_vmtests new file +77 -0

77 lines not on this page · raw message

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

maintainer
#9 lore raw
Quoted 16 lines · On Thu, 9 Feb 2012 09:46:22 +0800 Dave Young <[email protected]> wrote:

Andrew, updated the patch as below, is it ok to you?
---

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_vmtests to do such work which will call the three test programs and check the return value of them.

Changes to original code including below:
a. add run_vmtests script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

Quoted 5 lines

[v1 -> v2]:
1. [akpm:] rebased on runing make run_tests from Makefile
2. [akpm:] rename test script from run_test ro run_vmtests
2. fix a bug about shell exit code checking

So I tried to run this, from tools/testing/selftests.

a) The testing failed because ./vm's run_test target requires root.

We need to make a policy decision here. Do we require that selftests run as root? If not then the root-requiring selftests should warn and bail out without declaring a failure, so that those tests which can be run without root permissions can be successfully used.

b) When I ran the vm test, my machine went paralytically comatose for half a minute. That's a bit rude - if all the selftests do this then the selftests become kinda useless.

c) I can run "make run_tests" in the top-lvel directory and all is
well: the tools in ./vm get compiled first. But when I do "make clean ; cd vm ; make run-tests" it fails, because vm/Makefile doesn't build the targets before trying to run them.

This can be fixed with

tools/testing/selftests/vm/Makefile renamed from tools/testing/selftests/vm/Makefile~a +1 -1
@@ -7,7 +7,7 @@ all: hugepage-mmap hugepage-shm  map_hug
 %: %.c
 	$(CC) $(CFLAGS) -o $@ $^
 
-run_tests:
+run_tests: all
 	/bin/sh ./run_vmtests
 
 clean:

But this is unpleasing: a top-level "make run_tests" will end up trying to compile the targets twice.

We could change the top-level Makefile to a single-pass thing which just descends into the subdirectories and runs "make run_tests". But that gives us no way of compiling everything without also running everything. That's a huge PITA if running everything sends your machine comatose for half a minute!

So I think I'll go with the above patch.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#10 lore raw
Quoted 27 lines · Andrew Morton
Quoted 16 lines · On Thu, 9 Feb 2012 09:46:22 +0800 Dave Young <[email protected]> wrote:

Andrew, updated the patch as below, is it ok to you?
---

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_vmtests to do such work which will call the three test programs and check the return value of them.

Changes to original code including below:
a. add run_vmtests script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

Quoted 5 lines

[v1 -> v2]:
1. [akpm:] rebased on runing make run_tests from Makefile
2. [akpm:] rename test script from run_test ro run_vmtests
2. fix a bug about shell exit code checking

So I tried to run this, from tools/testing/selftests.

Quoted 7 lines

a) The testing failed because ./vm's run_test target requires root.

We need to make a policy decision here. Do we require that selftests run as root? If not then the root-requiring selftests should warn and bail out without declaring a failure, so that those tests which can be run without root permissions can be successfully used.

I agree with bailing out with warning for root-requiring selftests.

Quoted 4 lines

b) When I ran the vm test, my machine went paralytically comatose for half a minute. That's a bit rude - if all the selftests do this then the selftests become kinda useless.

Maybe 256M testing is too much, how about lower it to 64M hugepage test?

Quoted 23 lines

c) I can run "make run_tests" in the top-lvel directory and all is
well: the tools in ./vm get compiled first. But when I do "make clean ; cd vm ; make run-tests" it fails, because vm/Makefile doesn't build the targets before trying to run them.

This can be fixed with

tools/testing/selftests/vm/Makefile renamed from tools/testing/selftests/vm/Makefile~a +1 -1
@@ -7,7 +7,7 @@ all: hugepage-mmap hugepage-shm  map_hug
 %: %.c
 	$(CC) $(CFLAGS) -o $@ $^
 
-run_tests:
+run_tests: all
 	/bin/sh ./run_vmtests
 
 clean:

But this is unpleasing: a top-level "make run_tests" will end up trying to compile the targets twice.

Quoted 8 lines

We could change the top-level Makefile to a single-pass thing which just descends into the subdirectories and runs "make run_tests". But that gives us no way of compiling everything without also running everything. That's a huge PITA if running everything sends your machine comatose for half a minute!

So I think I'll go with the above patch.

Thanks for the fix. For your comment a) and b), how about below fix? If it's ok, then do you need I resend it with a refreshed whole patch?

---

Run make run_tests will fail without root previledge for vm selftests. Change to Just bail out with a warning. At the same time lower the test memory to 64M to avoid comatose machine.

---
 tools/testing/selftests/vm/hugepage-mmap.c |    4 ++--
 tools/testing/selftests/vm/hugepage-shm.c  |    8 ++++----
 tools/testing/selftests/vm/map_hugetlb.c   |    4 ++--
 tools/testing/selftests/vm/run_vmtests     |   14 +++++++-------
 4 files changed, 15 insertions(+), 15 deletions(-)
tools/testing/selftests/vm/run_vmtests +7 -7
@@ -1,8 +1,8 @@
 #!/bin/bash
 #please run as root
 
-#we need 256M, below is the size in kB
-needmem=262144
+#we need 64M, below is the size in kB
+needmem=65536
 mnt=./huge
 
 #get pagesize and freepages from /proc/meminfo
@@ -23,13 +23,13 @@ if [ -n "$freepgs" ] && [ -n "$pgsize" ]
 		lackpgs=$(( $needpgs - $freepgs ))
 		echo $(( $lackpgs + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
 		if [ $? -ne 0 ]; then
-			echo "Please run this test as root"
-			exit 1
+			echo "WARN: Bail out! Please run vm tests as root."
+			exit 0
 		fi
 	fi
 else
-	echo "no hugetlbfs support in kernel?"
-	exit 1
+	echo "WARN: Bail out! no hugetlbfs support in kernel?"
+	exit 0
 fi
 
 mkdir $mnt
@@ -47,7 +47,7 @@ fi
 
 shmmax=`cat /proc/sys/kernel/shmmax`
 shmall=`cat /proc/sys/kernel/shmall`
-echo 268435456 > /proc/sys/kernel/shmmax
+echo 67108864 > /proc/sys/kernel/shmmax
 echo 4194304 > /proc/sys/kernel/shmall
 echo "--------------------"
 echo "runing hugepage-shm"
tools/testing/selftests/vm/hugepage-mmap.c +2 -2
@@ -5,7 +5,7 @@
  * system call.  Before running this application, make sure that the
  * administrator has mounted the hugetlbfs filesystem (on some directory
  * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this
- * example, the app is requesting memory of size 256MB that is backed by
+ * example, the app is requesting memory of size 64MB that is backed by
  * huge pages.
  *
  * For the ia64 architecture, the Linux kernel reserves Region number 4 for
@@ -23,7 +23,7 @@
 #include <fcntl.h>
 
 #define FILE_NAME "huge/hugepagefile"
-#define LENGTH (256UL*1024*1024)
+#define LENGTH (64UL*1024*1024)
 #define PROTECTION (PROT_READ | PROT_WRITE)
 
 /* Only ia64 requires this */
tools/testing/selftests/vm/hugepage-shm.c +4 -4
@@ -2,7 +2,7 @@
  * hugepage-shm:
  *
  * Example of using huge page memory in a user application using Sys V shared
- * memory system calls.  In this example the app is requesting 256MB of
+ * memory system calls.  In this example the app is requesting 64MB of
  * memory that is backed by huge pages.  The application uses the flag
  * SHM_HUGETLB in the shmget system call to inform the kernel that it is
  * requesting huge pages.
@@ -17,9 +17,9 @@
  * Note: The default shared memory limit is quite low on many kernels,
  * you may need to increase it via:
  *
- * echo 268435456 > /proc/sys/kernel/shmmax
+ * echo 67108864 > /proc/sys/kernel/shmmax
  *
- * This will increase the maximum size per shared memory segment to 256MB.
+ * This will increase the maximum size per shared memory segment to 64MB.
  * The other limit that you will hit eventually is shmall which is the
  * total amount of shared memory in pages. To set it to 16GB on a system
  * with a 4kB pagesize do:
@@ -38,7 +38,7 @@
 #define SHM_HUGETLB 04000
 #endif
 
-#define LENGTH (256UL*1024*1024)
+#define LENGTH (64UL*1024*1024)
 
 #define dprintf(x)  printf(x)
 
tools/testing/selftests/vm/map_hugetlb.c +2 -2
@@ -2,7 +2,7 @@
  * Example of using hugepage memory in a user application using the mmap
  * system call with MAP_HUGETLB flag.  Before running this program make
  * sure the administrator has allocated enough default sized huge pages
- * to cover the 256 MB allocation.
+ * to cover the 64 MB allocation.
  *
  * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages.
  * That means the addresses starting with 0x800000... will need to be
@@ -15,7 +15,7 @@
 #include <sys/mman.h>
 #include <fcntl.h>
 
-#define LENGTH (256UL*1024*1024)
+#define LENGTH (64UL*1024*1024)
 #define PROTECTION (PROT_READ | PROT_WRITE)
 
 #ifndef MAP_HUGETLB

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#11 lore raw
In reply to Dave Young
Quoted 282 lines · Dave Young

hugepage-mmap.c, hugepage-shm.c and map_hugetlb.c in Documentation/vm are simple pass/fail tests, It's better to promote them to tools/testing/selftests

Thanks suggestion of Andrew Morton about this. They all need firstly setting up proper nr_hugepages and hugepage-mmap need to mount hugetlbfs. So I add a shell script run_test to do such work which will call the three test programs and check the return value of them.

Changes to original code including below:
a. add run_test script
b. return error when read_bytes mismatch with writed bytes. c. coding style fixes: do not use assignment in if condition

---
 Documentation/vm/Makefile                          |    8 --
 tools/testing/selftests/Makefile                   |    2 +-
 tools/testing/selftests/run_tests                  |    6 +-
 tools/testing/selftests/vm/Makefile                |   11 +++
 .../testing/selftests}/vm/hugepage-mmap.c          |   13 ++--
 .../testing/selftests}/vm/hugepage-shm.c           |   10 ++-
 .../testing/selftests}/vm/map_hugetlb.c            |   10 ++-
 tools/testing/selftests/vm/run_test                |   77 ++++++++++++++++++++
 8 files changed, 112 insertions(+), 25 deletions(-)
 delete mode 100644 Documentation/vm/Makefile
 create mode 100644 tools/testing/selftests/vm/Makefile
 rename {Documentation => tools/testing/selftests}/vm/hugepage-mmap.c (93%)
 rename {Documentation => tools/testing/selftests}/vm/hugepage-shm.c (94%)
 rename {Documentation => tools/testing/selftests}/vm/map_hugetlb.c (94%)
 create mode 100755 tools/testing/selftests/vm/run_test
Documentation/vm/Makefile deleted +0 -8
deleted file mode 100644
index e538864..0000000
@@ -1,8 +0,0 @@
-# kbuild trick to avoid linker error. Can be omitted if a module is built.
-obj- := dummy.o
-
-# List of programs to build
-hostprogs-y := hugepage-mmap hugepage-shm map_hugetlb
-
-# Tell kbuild to always build the programs
-always := $(hostprogs-y)
tools/testing/selftests/Makefile +1 -1
index 4ec8401..9a72fe5 100644
@@ -1,4 +1,4 @@
-TARGETS = breakpoints
+TARGETS = breakpoints vm
 
 all:
 	for TARGET in $(TARGETS); do \
tools/testing/selftests/run_tests +4 -2
index 320718a..1f4a5ef 100644
@@ -1,8 +1,10 @@
 #!/bin/bash
 
-TARGETS=breakpoints
+TARGETS="breakpoints vm"
 
 for TARGET in $TARGETS
 do
-	$TARGET/run_test
+	cd "$TARGET"
+	./run_test
+	cd ..
 done
tools/testing/selftests/vm/Makefile new file +11 -0
new file mode 100644
index 0000000..537ec38
@@ -0,0 +1,11 @@
+# Makefile for vm selftests
+
+CC = $(CROSS_COMPILE)gcc
+CFLAGS = -Wall -Wextra
+
+all: hugepage-mmap hugepage-shm  map_hugetlb
+%: %.c
+	$(CC) $(CFLAGS) -o $@ $^
+
+clean:
+	$(RM) hugepage-mmap hugepage-shm  map_hugetlb
tools/testing/selftests/vm/hugepage-mmap.c renamed from Documentation/vm/hugepage-mmap.c +7 -6
similarity index 93%
rename from Documentation/vm/hugepage-mmap.c
rename to tools/testing/selftests/vm/hugepage-mmap.c
index db0dd9a..a10f310 100644
@@ -22,7 +22,7 @@
 #include <sys/mman.h>
 #include <fcntl.h>
 
-#define FILE_NAME "/mnt/hugepagefile"
+#define FILE_NAME "huge/hugepagefile"
 #define LENGTH (256UL*1024*1024)
 #define PROTECTION (PROT_READ | PROT_WRITE)
 
@@ -48,7 +48,7 @@ static void write_bytes(char *addr)
 		*(addr + i) = (char)i;
 }
 
-static void read_bytes(char *addr)
+static int read_bytes(char *addr)
 {
 	unsigned long i;
 
@@ -56,14 +56,15 @@ static void read_bytes(char *addr)
 	for (i = 0; i < LENGTH; i++)
 		if (*(addr + i) != (char)i) {
 			printf("Mismatch at %lu\n", i);
-			break;
+			return 1;
 		}
+	return 0;
 }
 
 int main(void)
 {
 	void *addr;
-	int fd;
+	int fd, ret;
 
 	fd = open(FILE_NAME, O_CREAT | O_RDWR, 0755);
 	if (fd < 0) {
@@ -81,11 +82,11 @@ int main(void)
 	printf("Returned address is %p\n", addr);
 	check_bytes(addr);
 	write_bytes(addr);
-	read_bytes(addr);
+	ret = read_bytes(addr);
 
 	munmap(addr, LENGTH);
 	close(fd);
 	unlink(FILE_NAME);
 
-	return 0;
+	return ret;
 }
tools/testing/selftests/vm/hugepage-shm.c renamed from Documentation/vm/hugepage-shm.c +6 -4
similarity index 94%
rename from Documentation/vm/hugepage-shm.c
rename to tools/testing/selftests/vm/hugepage-shm.c
index 07956d8..0d0ef4f 100644
@@ -57,8 +57,8 @@ int main(void)
 	unsigned long i;
 	char *shmaddr;
 
-	if ((shmid = shmget(2, LENGTH,
-			    SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
+	shmid = shmget(2, LENGTH, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
+	if (shmid < 0) {
 		perror("shmget");
 		exit(1);
 	}
@@ -82,14 +82,16 @@ int main(void)
 
 	dprintf("Starting the Check...");
 	for (i = 0; i < LENGTH; i++)
-		if (shmaddr[i] != (char)i)
+		if (shmaddr[i] != (char)i) {
 			printf("\nIndex %lu mismatched\n", i);
+			exit(3);
+		}
 	dprintf("Done.\n");
 
 	if (shmdt((const void *)shmaddr) != 0) {
 		perror("Detach failure");
 		shmctl(shmid, IPC_RMID, NULL);
-		exit(3);
+		exit(4);
 	}
 
 	shmctl(shmid, IPC_RMID, NULL);
tools/testing/selftests/vm/map_hugetlb.c renamed from Documentation/vm/map_hugetlb.c +6 -4
similarity index 94%
rename from Documentation/vm/map_hugetlb.c
rename to tools/testing/selftests/vm/map_hugetlb.c
index eda1a6d..ac56639 100644
@@ -44,7 +44,7 @@ static void write_bytes(char *addr)
 		*(addr + i) = (char)i;
 }
 
-static void read_bytes(char *addr)
+static int read_bytes(char *addr)
 {
 	unsigned long i;
 
@@ -52,13 +52,15 @@ static void read_bytes(char *addr)
 	for (i = 0; i < LENGTH; i++)
 		if (*(addr + i) != (char)i) {
 			printf("Mismatch at %lu\n", i);
-			break;
+			return 1;
 		}
+	return 0;
 }
 
 int main(void)
 {
 	void *addr;
+	int ret;
 
 	addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
 	if (addr == MAP_FAILED) {
@@ -69,9 +71,9 @@ int main(void)
 	printf("Returned address is %p\n", addr);
 	check_bytes(addr);
 	write_bytes(addr);
-	read_bytes(addr);
+	ret = read_bytes(addr);
 
 	munmap(addr, LENGTH);
 
-	return 0;
+	return ret;
 }
tools/testing/selftests/vm/run_test new file +48 -0
new file mode 100755
index 0000000..33d355d
@@ -0,0 +1,77 @@
+#!/bin/bash
+#please run as root
+
+#we need 256M, below is the size in kB
+needmem=262144
+mnt=./huge
+
+#get pagesize and freepages from /proc/meminfo
+while read name size unit; do
+	if [ "$name" = "HugePages_Free:" ]; then
+		freepgs=$size
+	fi
+	if [ "$name" = "Hugepagesize:" ]; then
+		pgsize=$size
+	fi
+done < /proc/meminfo
+
+#set proper nr_hugepages
+if [ -n "$freepgs" ] && [ -n "$pgsize" ]; then
+	nr_hugepgs=`cat /proc/sys/vm/nr_hugepages`
+	needpgs=`expr $needmem / $pgsize`
+	if [ $freepgs -lt $needpgs ]; then
+		lackpgs=$(( $needpgs - $freepgs ))
+		echo $(( $lackpgs + $nr_hugepgs )) > /proc/sys/vm/nr_hugepages
+		if [ $? -ne 0 ]; then
+			echo "Please run this test as root"
+			exit 1
+		fi
+	fi
+else
+	echo "no hugetlbfs support in kernel?"
+	exit 1
+fi
+
+mkdir $mnt
+mount -t hugetlbfs none $mnt
+
+echo "--------------------"
+echo "runing hugepage-mmap"
+echo "--------------------"
+./hugepage-mmap
+if [ $? -ne 0 ]; then
+	echo "[FAIL]"
+else
+	echo "[PASS]"
+fi
+
+shmmax=`cat /proc/sys/kernel/shmmax`

tools/testing/selftests/vm/run_test line 58

Quoted 10 lines
tools/testing/selftests/vm/run_test new file +10 -0
+shmall=`cat /proc/sys/kernel/shmall`
+echo 268435456 > /proc/sys/kernel/shmmax
+echo 4194304 > /proc/sys/kernel/shmall
+echo "--------------------"
+echo "runing hugepage-shm"
+echo "--------------------"
+./hugepage-shm
+echo $shmmax > /proc/sys/kernel/shmmax
+echo $shmall > /proc/sys/kernel/shmall
+if [ $? -ne 0 ]; then

Oops, $? check place is wrong, will fix in v2

Quoted 19 lines
tools/testing/selftests/vm/run_test new file +19 -0
+	echo "[FAIL]"
+else
+	echo "[PASS]"
+fi
+
+echo "--------------------"
+echo "runing map_hugetlb"
+echo "--------------------"
+./map_hugetlb
+if [ $? -ne 0 ]; then
+	echo "[FAIL]"
+else
+	echo "[PASS]"
+fi
+
+#cleanup
+umount $mnt
+rm -rf $mnt
+echo $nr_hugepgs > /proc/sys/vm/nr_hugepages
Signature · 9 lines
Thanks
Dave

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>