linux-kselftest-4.8-rc1-update
This update for Kselftest adds: - 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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJXn4hHAAoJEAsCRMQNDUMc5cUP/iEUp8Xb21FXar3Cdoe6uZp7 F3TrtNKyWU6V2e9b97cSYmDkNAuARfq45w8TzDVm1fPp0kDq68RWVb9PW+FgYSAZ WK6i8TmLa5cCgwFMWjfu7XmkzpT5aXA4Upnqj12Rbg5DQZIDNtQDMi2SuJ23CrbP orSgAx/EdejpihxDRap8CO0OUhnv0bxhR9fX7HhzokhErjF5vUQ28auppZ0WxDZU 9XyuZhMRZ9TdrtKoslVCPxdaa9K1m+Bcu8ai+9cYpaQ0YcrXoN5ci3OKy5PDbFTP lNzmySBrKCfF5DN6V+Vrv9uSTWOI3Vbq+qsq+mySxobLhcMi7tkNiO269Podjtd8 koOTicEYcXQ/GAx/APTf1XI+jMq/GKGwp09mqzGMA7CUUoJ80qRAB11LAX62mrHb KonqsYou/gQmVHPCuAS2RT++vpa5jA257cqdtjdJ/Ds57QcyoXZA6BfUT3QxUh77 khufBbMM4MTjv3EMsHOmUGID2q4BoiFSI0HQZpgI8beUq+iJNOKBjmZ7ZWsgBMIP hOHu6Lo0LEMXkBiCJCQ73Fj/nuR6lKcbnBq3TX1FWtCfhTIoAsdnxRiqEeTzmxWm QS+yirp9LSuyTF/WWKfzvTYvDMQttLR7urBRzOK+6T2IJeObWjkpAkXjepUbeyLv M55J1MfhRMGgF6NNI0zS =C8Gn -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
5dd0bf621e
0
tools/testing/selftests/lib/printf.sh
Normal file → Executable file
0
tools/testing/selftests/lib/printf.sh
Normal file → Executable file
@ -1 +1,3 @@
|
|||||||
media_device_test
|
media_device_test
|
||||||
|
media_device_open
|
||||||
|
video_device_test
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
TEST_PROGS := media_device_test
|
TEST_PROGS := media_device_test media_device_open video_device_test
|
||||||
all: $(TEST_PROGS)
|
all: $(TEST_PROGS)
|
||||||
|
|
||||||
include ../lib.mk
|
include ../lib.mk
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -fr media_device_test
|
rm -fr media_device_test media_device_open video_device_test
|
||||||
|
12
tools/testing/selftests/media_tests/bind_unbind_sample.sh
Executable file
12
tools/testing/selftests/media_tests/bind_unbind_sample.sh
Executable file
@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# Find device number in /sys/bus/usb/drivers/drivername
|
||||||
|
# Edit this file to update the driver numer and name
|
||||||
|
# Example test for uvcvideo driver
|
||||||
|
#i=0
|
||||||
|
# while :; do
|
||||||
|
# i=$((i+1))
|
||||||
|
# echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/unbind;
|
||||||
|
# echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/bind;
|
||||||
|
# clear
|
||||||
|
# echo $i
|
||||||
|
#done
|
81
tools/testing/selftests/media_tests/media_device_open.c
Normal file
81
tools/testing/selftests/media_tests/media_device_open.c
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* media_device_open.c - Media Controller Device Open Test
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
|
||||||
|
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
|
||||||
|
*
|
||||||
|
* This file is released under the GPLv2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file adds a test for Media Controller API.
|
||||||
|
* This test should be run as root and should not be
|
||||||
|
* included in the Kselftest run. This test should be
|
||||||
|
* run when hardware and driver that makes use Media
|
||||||
|
* Controller API are present in the system.
|
||||||
|
*
|
||||||
|
* This test opens user specified Media Device and calls
|
||||||
|
* MEDIA_IOC_DEVICE_INFO ioctl, closes the file, and exits.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* sudo ./media_device_open -d /dev/mediaX
|
||||||
|
*
|
||||||
|
* Run this test is a loop and run bind/unbind on the driver.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <linux/media.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
char media_device[256];
|
||||||
|
int count = 0;
|
||||||
|
struct media_device_info mdi;
|
||||||
|
int ret;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process arguments */
|
||||||
|
while ((opt = getopt(argc, argv, "d:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'd':
|
||||||
|
strncpy(media_device, optarg, sizeof(media_device) - 1);
|
||||||
|
media_device[sizeof(media_device)-1] = '\0';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getuid() != 0) {
|
||||||
|
printf("Please run the test as root - Exiting.\n");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open Media device and keep it open */
|
||||||
|
fd = open(media_device, O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
printf("Media Device open errno %s\n", strerror(errno));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi);
|
||||||
|
if (ret < 0)
|
||||||
|
printf("Media Device Info errno %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
printf("Media device model %s driver %s\n",
|
||||||
|
mdi.model, mdi.driver);
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* media_devkref_test.c - Media Controller Device Kref API Test
|
* media_device_test.c - Media Controller Device ioctl loop Test
|
||||||
*
|
*
|
||||||
* Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
|
* Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
|
||||||
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
|
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
|
||||||
@ -35,13 +35,14 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <time.h>
|
||||||
#include <linux/media.h>
|
#include <linux/media.h>
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int opt;
|
int opt;
|
||||||
char media_device[256];
|
char media_device[256];
|
||||||
int count = 0;
|
int count;
|
||||||
struct media_device_info mdi;
|
struct media_device_info mdi;
|
||||||
int ret;
|
int ret;
|
||||||
int fd;
|
int fd;
|
||||||
@ -69,6 +70,10 @@ int main(int argc, char **argv)
|
|||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Generate random number of interations */
|
||||||
|
srand((unsigned int) time(NULL));
|
||||||
|
count = rand();
|
||||||
|
|
||||||
/* Open Media device and keep it open */
|
/* Open Media device and keep it open */
|
||||||
fd = open(media_device, O_RDWR);
|
fd = open(media_device, O_RDWR);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
@ -82,14 +87,16 @@ int main(int argc, char **argv)
|
|||||||
"other Oops in the dmesg. Enable KaSan kernel\n"
|
"other Oops in the dmesg. Enable KaSan kernel\n"
|
||||||
"config option for use-after-free error detection.\n\n");
|
"config option for use-after-free error detection.\n\n");
|
||||||
|
|
||||||
while (count < 100) {
|
printf("Running test for %d iternations\n", count);
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi);
|
ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
printf("Media Device Info errno %s\n", strerror(errno));
|
printf("Media Device Info errno %s\n", strerror(errno));
|
||||||
else
|
else
|
||||||
printf("Media device model %s driver %s\n",
|
printf("Media device model %s driver %s - count %d\n",
|
||||||
mdi.model, mdi.driver);
|
mdi.model, mdi.driver, count);
|
||||||
sleep(10);
|
sleep(10);
|
||||||
count++;
|
count--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
tools/testing/selftests/media_tests/open_loop_test.sh
Executable file
10
tools/testing/selftests/media_tests/open_loop_test.sh
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
i=0
|
||||||
|
file=/dev/media$1
|
||||||
|
while :; do
|
||||||
|
echo $file
|
||||||
|
i=$((i+1))
|
||||||
|
R=$(./media_device_open -d $file);
|
||||||
|
# clear
|
||||||
|
echo -e "Loop $i\n$R"
|
||||||
|
done
|
43
tools/testing/selftests/media_tests/regression_test.txt
Normal file
43
tools/testing/selftests/media_tests/regression_test.txt
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
Testing for regressions in Media Controller API register, ioctl, syscall,
|
||||||
|
and unregister paths. There have a few problems that result in user-after
|
||||||
|
free on media_device, media_devnode, and cdev pointers when the driver is
|
||||||
|
unbound while ioctl is in progress.
|
||||||
|
|
||||||
|
Test Procedure:
|
||||||
|
|
||||||
|
Run bin/unbind loop while ioctls are in progress.
|
||||||
|
Run rmmod and modprobe.
|
||||||
|
Disconnect the device.
|
||||||
|
|
||||||
|
Setup:
|
||||||
|
|
||||||
|
Build media_device_test
|
||||||
|
cd tools/testing/selftests/media_tests
|
||||||
|
make
|
||||||
|
|
||||||
|
Regressions test for cdev user-after free error on /dev/mediaX when driver
|
||||||
|
is unbound:
|
||||||
|
|
||||||
|
Start media_device_test to regression test media devnode dynamic alloc
|
||||||
|
and cdev user-after-free fixes. This opens media dev files and sits in
|
||||||
|
a loop running media ioctl MEDIA_IOC_DEVICE_INFO command once every 10
|
||||||
|
seconds. The idea is when device file goes away, media devnode and cdev
|
||||||
|
should stick around until this test exits.
|
||||||
|
|
||||||
|
The test for a random number of iterations or until user kills it with a
|
||||||
|
sleep 10 in between the ioctl calls.
|
||||||
|
|
||||||
|
sudo ./media_device_test -d /dev/mediaX
|
||||||
|
|
||||||
|
Regression test for media_devnode unregister race with ioctl_syscall:
|
||||||
|
|
||||||
|
Start 6 open_loop_test.sh tests with different /dev/mediaX files. When
|
||||||
|
device file goes away after unbind, device file name changes. Start the
|
||||||
|
test with possible device names. If we start with /dev/media0 for example,
|
||||||
|
after unbind, /dev/media1 or /dev/media2 could get created. The idea is
|
||||||
|
keep ioctls going while bind/unbind runs.
|
||||||
|
|
||||||
|
Copy bind_unbind_sample.txt and make changes to specify the driver name
|
||||||
|
and number to run bind and unbind. Start the bind_unbind.sh
|
||||||
|
|
||||||
|
Run dmesg looking for any user-after free errors or mutex lock errors.
|
100
tools/testing/selftests/media_tests/video_device_test.c
Normal file
100
tools/testing/selftests/media_tests/video_device_test.c
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* video_device_test - Video Device Test
|
||||||
|
*
|
||||||
|
* Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
|
||||||
|
* Copyright (c) 2016 Samsung Electronics Co., Ltd.
|
||||||
|
*
|
||||||
|
* This file is released under the GPLv2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file adds a test for Video Device. This test should not be included
|
||||||
|
* in the Kselftest run. This test should be run when hardware and driver
|
||||||
|
* that makes use of V4L2 API is present.
|
||||||
|
*
|
||||||
|
* This test opens user specified Video Device and calls video ioctls in a
|
||||||
|
* loop once every 10 seconds.
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* sudo ./video_device_test -d /dev/videoX
|
||||||
|
*
|
||||||
|
* While test is running, remove the device or unbind the driver and
|
||||||
|
* ensure there are no use after free errors and other Oops in the
|
||||||
|
* dmesg.
|
||||||
|
* When possible, enable KaSan kernel config option for use-after-free
|
||||||
|
* error detection.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
char video_dev[256];
|
||||||
|
int count;
|
||||||
|
struct v4l2_tuner vtuner;
|
||||||
|
struct v4l2_capability vcap;
|
||||||
|
int ret;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
printf("Usage: %s [-d </dev/videoX>]\n", argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process arguments */
|
||||||
|
while ((opt = getopt(argc, argv, "d:")) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'd':
|
||||||
|
strncpy(video_dev, optarg, sizeof(video_dev) - 1);
|
||||||
|
video_dev[sizeof(video_dev)-1] = '\0';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Usage: %s [-d </dev/videoX>]\n", argv[0]);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Generate random number of interations */
|
||||||
|
srand((unsigned int) time(NULL));
|
||||||
|
count = rand();
|
||||||
|
|
||||||
|
/* Open Video device and keep it open */
|
||||||
|
fd = open(video_dev, O_RDWR);
|
||||||
|
if (fd == -1) {
|
||||||
|
printf("Video Device open errno %s\n", strerror(errno));
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\nNote:\n"
|
||||||
|
"While test is running, remove the device or unbind\n"
|
||||||
|
"driver and ensure there are no use after free errors\n"
|
||||||
|
"and other Oops in the dmesg. When possible, enable KaSan\n"
|
||||||
|
"kernel config option for use-after-free error detection.\n\n");
|
||||||
|
|
||||||
|
while (count > 0) {
|
||||||
|
ret = ioctl(fd, VIDIOC_QUERYCAP, &vcap);
|
||||||
|
if (ret < 0)
|
||||||
|
printf("VIDIOC_QUERYCAP errno %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
printf("Video device driver %s\n", vcap.driver);
|
||||||
|
|
||||||
|
ret = ioctl(fd, VIDIOC_G_TUNER, &vtuner);
|
||||||
|
if (ret < 0)
|
||||||
|
printf("VIDIOC_G_TUNER, errno %s\n", strerror(errno));
|
||||||
|
else
|
||||||
|
printf("type %d rangelow %d rangehigh %d\n",
|
||||||
|
vtuner.type, vtuner.rangelow, vtuner.rangehigh);
|
||||||
|
sleep(10);
|
||||||
|
count--;
|
||||||
|
}
|
||||||
|
}
|
@ -101,7 +101,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
|
|||||||
|
|
||||||
/* Start with the initial condition of 0 huge pages*/
|
/* Start with the initial condition of 0 huge pages*/
|
||||||
if (write(fd, "0", sizeof(char)) != sizeof(char)) {
|
if (write(fd, "0", sizeof(char)) != sizeof(char)) {
|
||||||
perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
|
perror("Failed to write 0 to /proc/sys/vm/nr_hugepages\n");
|
||||||
goto close_fd;
|
goto close_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,14 +110,14 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
|
|||||||
/* Request a large number of huge pages. The Kernel will allocate
|
/* Request a large number of huge pages. The Kernel will allocate
|
||||||
as much as it can */
|
as much as it can */
|
||||||
if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) {
|
if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) {
|
||||||
perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
|
perror("Failed to write 100000 to /proc/sys/vm/nr_hugepages\n");
|
||||||
goto close_fd;
|
goto close_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
lseek(fd, 0, SEEK_SET);
|
lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
|
if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
|
||||||
perror("Failed to read from /proc/sys/vm/nr_hugepages\n");
|
perror("Failed to re-read from /proc/sys/vm/nr_hugepages\n");
|
||||||
goto close_fd;
|
goto close_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +138,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
|
|||||||
|
|
||||||
if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages))
|
if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages))
|
||||||
!= strlen(initial_nr_hugepages)) {
|
!= strlen(initial_nr_hugepages)) {
|
||||||
perror("Failed to write to /proc/sys/vm/nr_hugepages\n");
|
perror("Failed to write value to /proc/sys/vm/nr_hugepages\n");
|
||||||
goto close_fd;
|
goto close_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@ static int test_limit(void)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mlockall(MCL_CURRENT | MCL_ONFAULT | MCL_FUTURE)) {
|
if (mlockall(MCL_ONFAULT | MCL_FUTURE)) {
|
||||||
perror("mlockall");
|
perror("mlockall");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user