lkml.org 
[lkml]   [2015]   [Mar]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: [PATCH] selftest: add a test case to check how locks are shown in fdinfo
On Thu, Mar 12, 2015 at 02:43:19PM -0600, Shuah Khan wrote:
> Hi Andrey,
>
> Looks good in general. Couple of comments.

Thanks. The updated version is attached.

>
> On 03/12/2015 10:30 AM, Andrey Vagin wrote:
> > The main idea of this test is to check that locks are shown correctly
> > when they can't be placed in a default seq_file buffer due to its size.
> >
> > Cc: Andrew Morton <akpm@linux-foundation.org>
> > Cc: Shuah Khan <shuahkh@osg.samsung.com>
> > Signed-off-by: Andrey Vagin <avagin@openvz.org>
> > ---
> > tools/testing/selftests/Makefile | 1 +
> > tools/testing/selftests/fdinfo/Makefile | 11 +++
> > tools/testing/selftests/fdinfo/locks.c | 119 ++++++++++++++++++++++++++++++++
> > 3 files changed, 131 insertions(+)
> > create mode 100644 tools/testing/selftests/fdinfo/Makefile
> > create mode 100644 tools/testing/selftests/fdinfo/locks.c
> >
> > diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
> > index 4e51122..8cd57f6 100644
> > --- a/tools/testing/selftests/Makefile
> > +++ b/tools/testing/selftests/Makefile
> > @@ -17,6 +17,7 @@ TARGETS += sysctl
> > TARGETS += timers
> > TARGETS += user
> > TARGETS += vm
> > +TARGETS += fdinfo
> > #Please keep the TARGETS list alphabetically sorted
>
> Please move the new target up to keep the TARGETS list
> alphabetically sorted. This helps avoid conflicts as new
> tests get added.
>
> >
> > TARGETS_HOTPLUG = cpu-hotplug
> > diff --git a/tools/testing/selftests/fdinfo/Makefile b/tools/testing/selftests/fdinfo/Makefile
> > new file mode 100644
> > index 0000000..83f34ef
> > --- /dev/null
> > +++ b/tools/testing/selftests/fdinfo/Makefile
> > @@ -0,0 +1,11 @@
> > +CFLAGS += -Wall
> > +
> > +all: locks
> > +
> > +run_tests: all
> > + @./locks || echo "locks: [FAIL]"
> > +
> > +locks: locks.c
> > +
> > +clean:
> > + rm -f locks
> > diff --git a/tools/testing/selftests/fdinfo/locks.c b/tools/testing/selftests/fdinfo/locks.c
> > new file mode 100644
> > index 0000000..93f25c6
> > --- /dev/null
> > +++ b/tools/testing/selftests/fdinfo/locks.c
> > @@ -0,0 +1,119 @@
> > +#include <stdlib.h>
> > +#include <stdio.h>
> > +#include <unistd.h>
> > +#include <string.h>
> > +#include <sys/types.h>
> > +#include <sys/stat.h>
> > +#include <fcntl.h>
> > +
> > +#define pr_perror(fmt, ...) fprintf(stderr, "%s:%d: " fmt ": %m\n", \
> > + __FILE__, __LINE__, ##__VA_ARGS__)
> > +
> > +#define FILE_SIZE 4096
> > +
> > +int main(int argc, char **argv)
> > +{
> > + int fd, fdinfo, i, ret, size, bsize = 4096;
> > + char *buf, *p, fdinfo_path[] = "/proc/self/fdinfo/XXXXXXXXXX";
> > +
> > + fd = open("test_file", O_RDWR | O_CREAT, 0666);
> > + if (fd == -1) {
> > + pr_perror("Unable to open test_file");
> > + return 1;
> > + }
> > + unlink("test_file");
> > + if (ftruncate(fd, FILE_SIZE) == -1) {
> > + pr_perror("Unable to truncate test_file");
> > + return 1;
> > + }
> > +
> > + /*
> > + * Generate FILE_SIZE locks. We are going to exceed the default
> > + * size of seq buffer
> > + */
> > + for (i = 0; i < FILE_SIZE; i++) {
> > + struct flock lock;
> > +
> > + if (i % 2)
> > + lock.l_type = F_WRLCK;
> > + else
> > + lock.l_type = F_RDLCK;
> > + lock.l_whence = SEEK_SET;
> > + lock.l_start = i;
> > + lock.l_len = 1;
> > + lock.l_pid = -1;
> > + if (fcntl(fd, F_SETLK, &lock)) {
> > + pr_perror("Unable to set lock %d\n", i);
> > + return 1;
> > + }
> > + }
> > +
> > + snprintf(fdinfo_path, sizeof(fdinfo_path), "/proc/self/fdinfo/%d", fd);
> > + fdinfo = open(fdinfo_path, O_RDONLY);
> > + if (fdinfo < 0) {
> > + pr_perror("Unable to open %s", fdinfo_path);
> > + return 1;
> > + }
> > +
> > + buf = malloc(bsize);
> > + if (buf == NULL) {
> > + pr_perror("Unable to allocate a buffer");
> > + return 1;
> > + }
> > + size = 0;
> > + while (1) {
> > + ret = read(fdinfo, buf + size, bsize - 1 - size);
> > + if (ret == 0)
> > + break;
> > + if (ret == -1) {
> > + pr_perror("Unable to read %s", fdinfo_path);
> > + return 1;
> > + }
> > + size += ret;
> > + if (bsize - size < 4096)
> > + bsize += 4096;
> > + buf = realloc(buf, bsize);
> > + if (buf == NULL) {
> > + pr_perror("Unable to allocate a buffer");
> > + return 1;
> > + }
> > + }
> > + buf[size] = 0;
> > +
> > + i = 0;
> > + for (p = buf - 1; p != NULL; p = strchr(p, '\n')) {
> > + char fl_flag[10], fl_type[15], fl_option[10], end[32];
> > + int fl_id, fl_owner, maj, min;
> > + unsigned long ino;
> > + unsigned long long start;
> > +
> > + p++;
> > +
> > + if (strncmp(p, "lock:", 5))
> > + continue;
> > + ret = sscanf(p, "lock:\t%d:%s %s %s %d %x:%x:%ld %lld %s",
> > + &fl_id, fl_flag, fl_type, fl_option,
> > + &fl_owner, &maj, &min, &ino,
> > + &start, end);
> > + if (ret != 10) {
> > + pr_perror("Unable to parse");
> > + fprintf(stderr, "%s\n", buf);
> > + return 1;
> > + }
> > + i++;
> > + }
> > +
> > + close(fdinfo);
> > + close(fd);
> > +
> > + if (i == FILE_SIZE)
> > + printf("PASS\n");
>
> Look into using ksft framework for reporting pass/fail conditions.
> Please see kselftest.h for the framework.
>
> > + else {
> > + fprintf(stderr, "%s\n", buf);
> > + return 1;
> > + }
> > +
> > + free(buf);
> > +
> > + return 0;
> > +}
> >
>
> thanks,
> -- Shuah
>
> --
> Shuah Khan
> Sr. Linux Kernel Developer
> Open Source Innovation Group
> Samsung Research America (Silicon Valley)
> shuahkh@osg.samsung.com | (970) 217-8978
From 2b8180d6ef2be57c0c303ef422fbca40833142f3 Mon Sep 17 00:00:00 2001
From: Andrey Vagin <avagin@openvz.org>
Date: Thu, 12 Mar 2015 15:28:55 +0300
Subject: [PATCH] selftest: add a test case to check how locks are shown in
fdinfo (v2)

The main idea of this test is to check that locks are shown correctly
when they can't be placed in a default seq_file buffer due to its size.

V2: use the kselftest framework

Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Signed-off-by: Andrey Vagin <avagin@openvz.org>
---
tools/testing/selftests/Makefile | 1 +
tools/testing/selftests/fdinfo/Makefile | 11 +++
tools/testing/selftests/fdinfo/locks.c | 119 ++++++++++++++++++++++++++++++++
3 files changed, 131 insertions(+)
create mode 100644 tools/testing/selftests/fdinfo/Makefile
create mode 100644 tools/testing/selftests/fdinfo/locks.c

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 4e51122..061a507 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -2,6 +2,7 @@ TARGETS = breakpoints
TARGETS += cpu-hotplug
TARGETS += efivarfs
TARGETS += exec
+TARGETS += fdinfo
TARGETS += firmware
TARGETS += ftrace
TARGETS += kcmp
diff --git a/tools/testing/selftests/fdinfo/Makefile b/tools/testing/selftests/fdinfo/Makefile
new file mode 100644
index 0000000..83f34ef
--- /dev/null
+++ b/tools/testing/selftests/fdinfo/Makefile
@@ -0,0 +1,11 @@
+CFLAGS += -Wall
+
+all: locks
+
+run_tests: all
+ @./locks || echo "locks: [FAIL]"
+
+locks: locks.c
+
+clean:
+ rm -f locks
diff --git a/tools/testing/selftests/fdinfo/locks.c b/tools/testing/selftests/fdinfo/locks.c
new file mode 100644
index 0000000..71fc237
--- /dev/null
+++ b/tools/testing/selftests/fdinfo/locks.c
@@ -0,0 +1,119 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "../kselftest.h"
+
+#define pr_perror(fmt, ...) fprintf(stderr, "%s:%d: " fmt ": %m\n", \
+ __FILE__, __LINE__, ##__VA_ARGS__)
+
+#define FILE_SIZE 4096
+
+int main(int argc, char **argv)
+{
+ int fd, fdinfo, i, ret, size, bsize = 4096;
+ char *buf, *p, fdinfo_path[] = "/proc/self/fdinfo/XXXXXXXXXX";
+
+ fd = open("test_file", O_RDWR | O_CREAT, 0666);
+ if (fd == -1) {
+ pr_perror("Unable to open test_file");
+ return ksft_exit_fail();
+ }
+ unlink("test_file");
+ if (ftruncate(fd, FILE_SIZE) == -1) {
+ pr_perror("Unable to truncate test_file");
+ return ksft_exit_fail();
+ }
+
+ /*
+ * Generate FILE_SIZE locks. We are going to exceed the default
+ * size of seq buffer
+ */
+ for (i = 0; i < FILE_SIZE; i++) {
+ struct flock lock;
+
+ if (i % 2)
+ lock.l_type = F_WRLCK;
+ else
+ lock.l_type = F_RDLCK;
+ lock.l_whence = SEEK_SET;
+ lock.l_start = i;
+ lock.l_len = 1;
+ lock.l_pid = -1;
+ if (fcntl(fd, F_SETLK, &lock)) {
+ pr_perror("Unable to set lock %d\n", i);
+ return ksft_exit_fail();
+ }
+ }
+
+ snprintf(fdinfo_path, sizeof(fdinfo_path), "/proc/self/fdinfo/%d", fd);
+ fdinfo = open(fdinfo_path, O_RDONLY);
+ if (fdinfo < 0) {
+ pr_perror("Unable to open %s", fdinfo_path);
+ return ksft_exit_fail();
+ }
+
+ buf = malloc(bsize);
+ if (buf == NULL) {
+ pr_perror("Unable to allocate a buffer");
+ return ksft_exit_fail();
+ }
+ size = 0;
+ while (1) {
+ ret = read(fdinfo, buf + size, bsize - 1 - size);
+ if (ret == 0)
+ break;
+ if (ret == -1) {
+ pr_perror("Unable to read %s", fdinfo_path);
+ return ksft_exit_fail();
+ }
+ size += ret;
+ if (bsize - size < 4096)
+ bsize += 4096;
+ buf = realloc(buf, bsize);
+ if (buf == NULL) {
+ pr_perror("Unable to allocate a buffer");
+ return ksft_exit_fail();
+ }
+ }
+ buf[size] = 0;
+
+ i = 0;
+ for (p = buf - 1; p != NULL; p = strchr(p, '\n')) {
+ char fl_flag[10], fl_type[15], fl_option[10], end[32];
+ int fl_id, fl_owner, maj, min;
+ unsigned long ino;
+ unsigned long long start;
+
+ p++;
+
+ if (strncmp(p, "lock:", 5))
+ continue;
+ ret = sscanf(p, "lock:\t%d:%s %s %s %d %x:%x:%ld %lld %s",
+ &fl_id, fl_flag, fl_type, fl_option,
+ &fl_owner, &maj, &min, &ino,
+ &start, end);
+ if (ret != 10) {
+ pr_perror("Unable to parse");
+ fprintf(stderr, "%s\n", buf);
+ return ksft_exit_fail();
+ }
+ i++;
+ }
+
+ close(fdinfo);
+ close(fd);
+
+ if (i != FILE_SIZE) {
+ fprintf(stderr, "%s\n", buf);
+ return ksft_exit_fail();
+ }
+
+ free(buf);
+
+ return ksft_exit_pass();
+}
--
2.1.0
\
 
 \ /
  Last update: 2015-03-13 10:41    [W:0.048 / U:6.400 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site