diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-01 16:52:08 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-08-01 16:52:08 -0400 |
commit | 5dd0bf621e84b9f48cbee8f4a31f4d68568aeaee (patch) | |
tree | a8b9ec9288c92794842b8380e6699bb0c2b9c3a6 /tools | |
parent | 1571a03daf626ff34705e5fb40404879d00ac463 (diff) | |
parent | d78388dbec256b179f1c42e714cf4acf630067c6 (diff) |
Merge tag 'linux-kselftest-4.8-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest
Pull kselftest updates from Shuah Khan:
"This contains new tests and fixes:
- a few fixes to existing tests
- new media tests for testing driver unbind, and device removal paths
while an user application is actively making system calls and
ioctls"
* tag 'linux-kselftest-4.8-rc1-update' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
selftests: media_tests add a new video device test
selftests: media_tests - Add media_device_open to .gitignore
selftests: add media controller regression test scripts and document
selftests: add media_device_open test
selftests: media_device_test change it to randomize loop count
selftests/vm: Don't mlockall MCL_CURRENT in on-fault-limit test
selftests/vm: write strlen length instead of sizeof to nr_hugepages
selftests/lib: set printf.sh executable
Diffstat (limited to 'tools')
-rwxr-xr-x[-rw-r--r--] | tools/testing/selftests/lib/printf.sh | 0 | ||||
-rw-r--r-- | tools/testing/selftests/media_tests/.gitignore | 2 | ||||
-rw-r--r-- | tools/testing/selftests/media_tests/Makefile | 4 | ||||
-rwxr-xr-x | tools/testing/selftests/media_tests/bind_unbind_sample.sh | 12 | ||||
-rw-r--r-- | tools/testing/selftests/media_tests/media_device_open.c | 81 | ||||
-rw-r--r-- | tools/testing/selftests/media_tests/media_device_test.c | 19 | ||||
-rwxr-xr-x | tools/testing/selftests/media_tests/open_loop_test.sh | 10 | ||||
-rw-r--r-- | tools/testing/selftests/media_tests/regression_test.txt | 43 | ||||
-rw-r--r-- | tools/testing/selftests/media_tests/video_device_test.c | 100 | ||||
-rw-r--r-- | tools/testing/selftests/vm/compaction_test.c | 8 | ||||
-rw-r--r-- | tools/testing/selftests/vm/on-fault-limit.c | 2 |
11 files changed, 268 insertions, 13 deletions
diff --git a/tools/testing/selftests/lib/printf.sh b/tools/testing/selftests/lib/printf.sh index 4fdc70fe6980..4fdc70fe6980 100644..100755 --- a/tools/testing/selftests/lib/printf.sh +++ b/tools/testing/selftests/lib/printf.sh | |||
diff --git a/tools/testing/selftests/media_tests/.gitignore b/tools/testing/selftests/media_tests/.gitignore index 1c0711708b98..8745eba39012 100644 --- a/tools/testing/selftests/media_tests/.gitignore +++ b/tools/testing/selftests/media_tests/.gitignore | |||
@@ -1 +1,3 @@ | |||
1 | media_device_test | 1 | media_device_test |
2 | media_device_open | ||
3 | video_device_test | ||
diff --git a/tools/testing/selftests/media_tests/Makefile b/tools/testing/selftests/media_tests/Makefile index 7071bcc1d066..6b34a0199468 100644 --- a/tools/testing/selftests/media_tests/Makefile +++ b/tools/testing/selftests/media_tests/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | TEST_PROGS := media_device_test | 1 | TEST_PROGS := media_device_test media_device_open video_device_test |
2 | all: $(TEST_PROGS) | 2 | all: $(TEST_PROGS) |
3 | 3 | ||
4 | include ../lib.mk | 4 | include ../lib.mk |
5 | 5 | ||
6 | clean: | 6 | clean: |
7 | rm -fr media_device_test | 7 | rm -fr media_device_test media_device_open video_device_test |
diff --git a/tools/testing/selftests/media_tests/bind_unbind_sample.sh b/tools/testing/selftests/media_tests/bind_unbind_sample.sh new file mode 100755 index 000000000000..9f362f10631a --- /dev/null +++ b/tools/testing/selftests/media_tests/bind_unbind_sample.sh | |||
@@ -0,0 +1,12 @@ | |||
1 | #!/bin/bash | ||
2 | # Find device number in /sys/bus/usb/drivers/drivername | ||
3 | # Edit this file to update the driver numer and name | ||
4 | # Example test for uvcvideo driver | ||
5 | #i=0 | ||
6 | # while :; do | ||
7 | # i=$((i+1)) | ||
8 | # echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/unbind; | ||
9 | # echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/bind; | ||
10 | # clear | ||
11 | # echo $i | ||
12 | #done | ||
diff --git a/tools/testing/selftests/media_tests/media_device_open.c b/tools/testing/selftests/media_tests/media_device_open.c new file mode 100644 index 000000000000..44343c091a20 --- /dev/null +++ b/tools/testing/selftests/media_tests/media_device_open.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * media_device_open.c - Media Controller Device Open Test | ||
3 | * | ||
4 | * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> | ||
5 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This file adds a test for Media Controller API. | ||
12 | * This test should be run as root and should not be | ||
13 | * included in the Kselftest run. This test should be | ||
14 | * run when hardware and driver that makes use Media | ||
15 | * Controller API are present in the system. | ||
16 | * | ||
17 | * This test opens user specified Media Device and calls | ||
18 | * MEDIA_IOC_DEVICE_INFO ioctl, closes the file, and exits. | ||
19 | * | ||
20 | * Usage: | ||
21 | * sudo ./media_device_open -d /dev/mediaX | ||
22 | * | ||
23 | * Run this test is a loop and run bind/unbind on the driver. | ||
24 | */ | ||
25 | |||
26 | #include <stdio.h> | ||
27 | #include <unistd.h> | ||
28 | #include <stdlib.h> | ||
29 | #include <errno.h> | ||
30 | #include <string.h> | ||
31 | #include <fcntl.h> | ||
32 | #include <sys/ioctl.h> | ||
33 | #include <sys/stat.h> | ||
34 | #include <linux/media.h> | ||
35 | |||
36 | int main(int argc, char **argv) | ||
37 | { | ||
38 | int opt; | ||
39 | char media_device[256]; | ||
40 | int count = 0; | ||
41 | struct media_device_info mdi; | ||
42 | int ret; | ||
43 | int fd; | ||
44 | |||
45 | if (argc < 2) { | ||
46 | printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]); | ||
47 | exit(-1); | ||
48 | } | ||
49 | |||
50 | /* Process arguments */ | ||
51 | while ((opt = getopt(argc, argv, "d:")) != -1) { | ||
52 | switch (opt) { | ||
53 | case 'd': | ||
54 | strncpy(media_device, optarg, sizeof(media_device) - 1); | ||
55 | media_device[sizeof(media_device)-1] = '\0'; | ||
56 | break; | ||
57 | default: | ||
58 | printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]); | ||
59 | exit(-1); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | if (getuid() != 0) { | ||
64 | printf("Please run the test as root - Exiting.\n"); | ||
65 | exit(-1); | ||
66 | } | ||
67 | |||
68 | /* Open Media device and keep it open */ | ||
69 | fd = open(media_device, O_RDWR); | ||
70 | if (fd == -1) { | ||
71 | printf("Media Device open errno %s\n", strerror(errno)); | ||
72 | exit(-1); | ||
73 | } | ||
74 | |||
75 | ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi); | ||
76 | if (ret < 0) | ||
77 | printf("Media Device Info errno %s\n", strerror(errno)); | ||
78 | else | ||
79 | printf("Media device model %s driver %s\n", | ||
80 | mdi.model, mdi.driver); | ||
81 | } | ||
diff --git a/tools/testing/selftests/media_tests/media_device_test.c b/tools/testing/selftests/media_tests/media_device_test.c index cbf53a032ab5..5d49943e77d0 100644 --- a/tools/testing/selftests/media_tests/media_device_test.c +++ b/tools/testing/selftests/media_tests/media_device_test.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * media_devkref_test.c - Media Controller Device Kref API Test | 2 | * media_device_test.c - Media Controller Device ioctl loop Test |
3 | * | 3 | * |
4 | * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> | 4 | * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> |
5 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. | 5 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. |
@@ -35,13 +35,14 @@ | |||
35 | #include <fcntl.h> | 35 | #include <fcntl.h> |
36 | #include <sys/ioctl.h> | 36 | #include <sys/ioctl.h> |
37 | #include <sys/stat.h> | 37 | #include <sys/stat.h> |
38 | #include <time.h> | ||
38 | #include <linux/media.h> | 39 | #include <linux/media.h> |
39 | 40 | ||
40 | int main(int argc, char **argv) | 41 | int main(int argc, char **argv) |
41 | { | 42 | { |
42 | int opt; | 43 | int opt; |
43 | char media_device[256]; | 44 | char media_device[256]; |
44 | int count = 0; | 45 | int count; |
45 | struct media_device_info mdi; | 46 | struct media_device_info mdi; |
46 | int ret; | 47 | int ret; |
47 | int fd; | 48 | int fd; |
@@ -69,6 +70,10 @@ int main(int argc, char **argv) | |||
69 | exit(-1); | 70 | exit(-1); |
70 | } | 71 | } |
71 | 72 | ||
73 | /* Generate random number of interations */ | ||
74 | srand((unsigned int) time(NULL)); | ||
75 | count = rand(); | ||
76 | |||
72 | /* Open Media device and keep it open */ | 77 | /* Open Media device and keep it open */ |
73 | fd = open(media_device, O_RDWR); | 78 | fd = open(media_device, O_RDWR); |
74 | if (fd == -1) { | 79 | if (fd == -1) { |
@@ -82,14 +87,16 @@ int main(int argc, char **argv) | |||
82 | "other Oops in the dmesg. Enable KaSan kernel\n" | 87 | "other Oops in the dmesg. Enable KaSan kernel\n" |
83 | "config option for use-after-free error detection.\n\n"); | 88 | "config option for use-after-free error detection.\n\n"); |
84 | 89 | ||
85 | while (count < 100) { | 90 | printf("Running test for %d iternations\n", count); |
91 | |||
92 | while (count > 0) { | ||
86 | ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi); | 93 | ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi); |
87 | if (ret < 0) | 94 | if (ret < 0) |
88 | printf("Media Device Info errno %s\n", strerror(errno)); | 95 | printf("Media Device Info errno %s\n", strerror(errno)); |
89 | else | 96 | else |
90 | printf("Media device model %s driver %s\n", | 97 | printf("Media device model %s driver %s - count %d\n", |
91 | mdi.model, mdi.driver); | 98 | mdi.model, mdi.driver, count); |
92 | sleep(10); | 99 | sleep(10); |
93 | count++; | 100 | count--; |
94 | } | 101 | } |
95 | } | 102 | } |
diff --git a/tools/testing/selftests/media_tests/open_loop_test.sh b/tools/testing/selftests/media_tests/open_loop_test.sh new file mode 100755 index 000000000000..dcd3c17efc17 --- /dev/null +++ b/tools/testing/selftests/media_tests/open_loop_test.sh | |||
@@ -0,0 +1,10 @@ | |||
1 | #!/bin/bash | ||
2 | i=0 | ||
3 | file=/dev/media$1 | ||
4 | while :; do | ||
5 | echo $file | ||
6 | i=$((i+1)) | ||
7 | R=$(./media_device_open -d $file); | ||
8 | # clear | ||
9 | echo -e "Loop $i\n$R" | ||
10 | done | ||
diff --git a/tools/testing/selftests/media_tests/regression_test.txt b/tools/testing/selftests/media_tests/regression_test.txt new file mode 100644 index 000000000000..2627367681f7 --- /dev/null +++ b/tools/testing/selftests/media_tests/regression_test.txt | |||
@@ -0,0 +1,43 @@ | |||
1 | Testing for regressions in Media Controller API register, ioctl, syscall, | ||
2 | and unregister paths. There have a few problems that result in user-after | ||
3 | free on media_device, media_devnode, and cdev pointers when the driver is | ||
4 | unbound while ioctl is in progress. | ||
5 | |||
6 | Test Procedure: | ||
7 | |||
8 | Run bin/unbind loop while ioctls are in progress. | ||
9 | Run rmmod and modprobe. | ||
10 | Disconnect the device. | ||
11 | |||
12 | Setup: | ||
13 | |||
14 | Build media_device_test | ||
15 | cd tools/testing/selftests/media_tests | ||
16 | make | ||
17 | |||
18 | Regressions test for cdev user-after free error on /dev/mediaX when driver | ||
19 | is unbound: | ||
20 | |||
21 | Start media_device_test to regression test media devnode dynamic alloc | ||
22 | and cdev user-after-free fixes. This opens media dev files and sits in | ||
23 | a loop running media ioctl MEDIA_IOC_DEVICE_INFO command once every 10 | ||
24 | seconds. The idea is when device file goes away, media devnode and cdev | ||
25 | should stick around until this test exits. | ||
26 | |||
27 | The test for a random number of iterations or until user kills it with a | ||
28 | sleep 10 in between the ioctl calls. | ||
29 | |||
30 | sudo ./media_device_test -d /dev/mediaX | ||
31 | |||
32 | Regression test for media_devnode unregister race with ioctl_syscall: | ||
33 | |||
34 | Start 6 open_loop_test.sh tests with different /dev/mediaX files. When | ||
35 | device file goes away after unbind, device file name changes. Start the | ||
36 | test with possible device names. If we start with /dev/media0 for example, | ||
37 | after unbind, /dev/media1 or /dev/media2 could get created. The idea is | ||
38 | keep ioctls going while bind/unbind runs. | ||
39 | |||
40 | Copy bind_unbind_sample.txt and make changes to specify the driver name | ||
41 | and number to run bind and unbind. Start the bind_unbind.sh | ||
42 | |||
43 | Run dmesg looking for any user-after free errors or mutex lock errors. | ||
diff --git a/tools/testing/selftests/media_tests/video_device_test.c b/tools/testing/selftests/media_tests/video_device_test.c new file mode 100644 index 000000000000..66d419c28653 --- /dev/null +++ b/tools/testing/selftests/media_tests/video_device_test.c | |||
@@ -0,0 +1,100 @@ | |||
1 | /* | ||
2 | * video_device_test - Video Device Test | ||
3 | * | ||
4 | * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> | ||
5 | * Copyright (c) 2016 Samsung Electronics Co., Ltd. | ||
6 | * | ||
7 | * This file is released under the GPLv2. | ||
8 | */ | ||
9 | |||
10 | /* | ||
11 | * This file adds a test for Video Device. This test should not be included | ||
12 | * in the Kselftest run. This test should be run when hardware and driver | ||
13 | * that makes use of V4L2 API is present. | ||
14 | * | ||
15 | * This test opens user specified Video Device and calls video ioctls in a | ||
16 | * loop once every 10 seconds. | ||
17 | * | ||
18 | * Usage: | ||
19 | * sudo ./video_device_test -d /dev/videoX | ||
20 | * | ||
21 | * While test is running, remove the device or unbind the driver and | ||
22 | * ensure there are no use after free errors and other Oops in the | ||
23 | * dmesg. | ||
24 | * When possible, enable KaSan kernel config option for use-after-free | ||
25 | * error detection. | ||
26 | */ | ||
27 | |||
28 | #include <stdio.h> | ||
29 | #include <unistd.h> | ||
30 | #include <stdlib.h> | ||
31 | #include <errno.h> | ||
32 | #include <string.h> | ||
33 | #include <fcntl.h> | ||
34 | #include <sys/ioctl.h> | ||
35 | #include <sys/stat.h> | ||
36 | #include <time.h> | ||
37 | #include <linux/videodev2.h> | ||
38 | |||
39 | int main(int argc, char **argv) | ||
40 | { | ||
41 | int opt; | ||
42 | char video_dev[256]; | ||
43 | int count; | ||
44 | struct v4l2_tuner vtuner; | ||
45 | struct v4l2_capability vcap; | ||
46 | int ret; | ||
47 | int fd; | ||
48 | |||
49 | if (argc < 2) { | ||
50 | printf("Usage: %s [-d </dev/videoX>]\n", argv[0]); | ||
51 | exit(-1); | ||
52 | } | ||
53 | |||
54 | /* Process arguments */ | ||
55 | while ((opt = getopt(argc, argv, "d:")) != -1) { | ||
56 | switch (opt) { | ||
57 | case 'd': | ||
58 | strncpy(video_dev, optarg, sizeof(video_dev) - 1); | ||
59 | video_dev[sizeof(video_dev)-1] = '\0'; | ||
60 | break; | ||
61 | default: | ||
62 | printf("Usage: %s [-d </dev/videoX>]\n", argv[0]); | ||
63 | exit(-1); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | /* Generate random number of interations */ | ||
68 | srand((unsigned int) time(NULL)); | ||
69 | count = rand(); | ||
70 | |||
71 | /* Open Video device and keep it open */ | ||
72 | fd = open(video_dev, O_RDWR); | ||
73 | if (fd == -1) { | ||
74 | printf("Video Device open errno %s\n", strerror(errno)); | ||
75 | exit(-1); | ||
76 | } | ||
77 | |||
78 | printf("\nNote:\n" | ||
79 | "While test is running, remove the device or unbind\n" | ||
80 | "driver and ensure there are no use after free errors\n" | ||
81 | "and other Oops in the dmesg. When possible, enable KaSan\n" | ||
82 | "kernel config option for use-after-free error detection.\n\n"); | ||
83 | |||
84 | while (count > 0) { | ||
85 | ret = ioctl(fd, VIDIOC_QUERYCAP, &vcap); | ||
86 | if (ret < 0) | ||
87 | printf("VIDIOC_QUERYCAP errno %s\n", strerror(errno)); | ||
88 | else | ||
89 | printf("Video device driver %s\n", vcap.driver); | ||
90 | |||
91 | ret = ioctl(fd, VIDIOC_G_TUNER, &vtuner); | ||
92 | if (ret < 0) | ||
93 | printf("VIDIOC_G_TUNER, errno %s\n", strerror(errno)); | ||
94 | else | ||
95 | printf("type %d rangelow %d rangehigh %d\n", | ||
96 | vtuner.type, vtuner.rangelow, vtuner.rangehigh); | ||
97 | sleep(10); | ||
98 | count--; | ||
99 | } | ||
100 | } | ||
diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c index 00c4f65d12da..6d1437f895b8 100644 --- a/tools/testing/selftests/vm/compaction_test.c +++ b/tools/testing/selftests/vm/compaction_test.c | |||
@@ -101,7 +101,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) | |||
101 | 101 | ||
102 | /* Start with the initial condition of 0 huge pages*/ | 102 | /* Start with the initial condition of 0 huge pages*/ |
103 | if (write(fd, "0", sizeof(char)) != sizeof(char)) { | 103 | if (write(fd, "0", sizeof(char)) != sizeof(char)) { |
104 | perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); | 104 | perror("Failed to write 0 to /proc/sys/vm/nr_hugepages\n"); |
105 | goto close_fd; | 105 | goto close_fd; |
106 | } | 106 | } |
107 | 107 | ||
@@ -110,14 +110,14 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) | |||
110 | /* Request a large number of huge pages. The Kernel will allocate | 110 | /* Request a large number of huge pages. The Kernel will allocate |
111 | as much as it can */ | 111 | as much as it can */ |
112 | if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) { | 112 | if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) { |
113 | perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); | 113 | perror("Failed to write 100000 to /proc/sys/vm/nr_hugepages\n"); |
114 | goto close_fd; | 114 | goto close_fd; |
115 | } | 115 | } |
116 | 116 | ||
117 | lseek(fd, 0, SEEK_SET); | 117 | lseek(fd, 0, SEEK_SET); |
118 | 118 | ||
119 | if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) { | 119 | if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) { |
120 | perror("Failed to read from /proc/sys/vm/nr_hugepages\n"); | 120 | perror("Failed to re-read from /proc/sys/vm/nr_hugepages\n"); |
121 | goto close_fd; | 121 | goto close_fd; |
122 | } | 122 | } |
123 | 123 | ||
@@ -138,7 +138,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) | |||
138 | 138 | ||
139 | if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages)) | 139 | if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages)) |
140 | != strlen(initial_nr_hugepages)) { | 140 | != strlen(initial_nr_hugepages)) { |
141 | perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); | 141 | perror("Failed to write value to /proc/sys/vm/nr_hugepages\n"); |
142 | goto close_fd; | 142 | goto close_fd; |
143 | } | 143 | } |
144 | 144 | ||
diff --git a/tools/testing/selftests/vm/on-fault-limit.c b/tools/testing/selftests/vm/on-fault-limit.c index 245acccce42d..0ae458f32fdb 100644 --- a/tools/testing/selftests/vm/on-fault-limit.c +++ b/tools/testing/selftests/vm/on-fault-limit.c | |||
@@ -20,7 +20,7 @@ static int test_limit(void) | |||
20 | return ret; | 20 | return ret; |
21 | } | 21 | } |
22 | 22 | ||
23 | if (mlockall(MCL_CURRENT | MCL_ONFAULT | MCL_FUTURE)) { | 23 | if (mlockall(MCL_ONFAULT | MCL_FUTURE)) { |
24 | perror("mlockall"); | 24 | perror("mlockall"); |
25 | return ret; | 25 | return ret; |
26 | } | 26 | } |