Skip to contentSkip to conversation

syscalls/getdents: Add parameter to test getdents64 syscall

PATCH Superseded Markos Chandras 2 participants 3 messages Mar 14, 2013 1 message not in the archive

v1 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 syscalls/getdents: Add parameter to test getdents64 syscall

From: Markos Chandras <[email protected]>

Add new "-l" parameter to test the getdents64 syscall along with the getdents one. Use ltp_syscall() to call the system call to get proper return values when an architecture does not support any of the getdents{,64} syscalls. Modify runtest/syscalls to call getdentsXX tests with and without the "-l" parameter

---
 runtest/syscalls                                |    9 ++++
 testcases/kernel/syscalls/getdents/Makefile     |    2 +
 testcases/kernel/syscalls/getdents/getdents.h   |   48 ++++++++++++++++++++++-
 testcases/kernel/syscalls/getdents/getdents01.c |   42 +++++++++++++++----
 testcases/kernel/syscalls/getdents/getdents02.c |   38 +++++++++++++++---
 testcases/kernel/syscalls/getdents/getdents03.c |   35 ++++++++++++++--
 testcases/kernel/syscalls/getdents/getdents04.c |   41 +++++++++++++++----
 7 files changed, 186 insertions(+), 29 deletions(-)
runtest/syscalls +9 -0
index c70bcbd..191ad10 100644
@@ -331,6 +331,15 @@ getdents03_64 getdents03_64
 getdents04 getdents04
 getdents04_64 getdents04_64
 
+getdents01_long getdents01 -l
+getdents01_64_long getdents01_64 -l
+getdents02_long getdents02 -l
+getdents02_64_long getdents02_64 -l
+getdents03_long getdents03 -l
+getdents03_64_long getdents03_64 -l
+getdents04_long getdents04 -l
+getdents04_64_long getdents04_64 -l
+
 getdomainname01 getdomainname01
 
 getdtablesize01 getdtablesize01
testcases/kernel/syscalls/getdents/Makefile +2 -0
index df7b63f..8334aa7 100644
@@ -21,6 +21,8 @@ top_srcdir		?= ../../../..
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
+CFLAGS += -D_LARGEFILE64_SOURCE
+
 %_64: CPPFLAGS += -D_FILE_OFFSET_BITS=64 -DOFF_T=__off64_t
 
 include $(top_srcdir)/include/mk/generic_leaf_target.mk
testcases/kernel/syscalls/getdents/getdents.h +47 -1

70 lines not on this page · raw message

testcases/kernel/syscalls/getdents/getdents01.c +33 -9

86 lines not on this page · raw message

testcases/kernel/syscalls/getdents/getdents02.c +32 -6
index ee34de2..2299f30 100644
@@ -40,10 +40,12 @@
  *             -e   : Turn on errno logging.
  *	       -i n : Execute test n times.
  *	       -I x : Execute test for x seconds.
+ *	       -l   : Test the getdents64 system call.
  *	       -P x : Pause for x seconds between iterations.
  *	       -t   : Turn on syscall timing.
  *
  * HISTORY
+ *	03/2013 - Added -l option by Markos Chandras
  *	03/2001 - Written by Wayne Boyer
  *
  * RESTRICTIONS
@@ -69,6 +71,17 @@ int TST_TOTAL = 1;
 
 int exp_enos[] = { EBADF, 0 };	/* 0 terminated list of expected errnos */
 
+int longsyscall;
+
+option_t Options[] = {
+		{"l", &longsyscall, NULL}, /* -l long option. Tests getdents64 */
+		{NULL, NULL, NULL}
+};
+
+void help() {
+	printf("  -l      Test the getdents64 system call\n");
+}
+
 int main(int ac, char **av)
 {
 	int lc;
@@ -77,9 +90,10 @@ int main(int ac, char **av)
 	int count;
 	size_t size = 0;
 	char *dir_name = NULL;
+	struct dirent64 *dirp64;
 	struct dirent *dirp;
 
-	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
+	if ((msg = parse_opts(ac, av, Options, &help)) != NULL)
 		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
 
 	setup();
@@ -91,16 +105,25 @@ int main(int ac, char **av)
 			tst_brkm(TBROK, cleanup, "Can not get current "
 				 "directory name");
 
-		if ((dirp = malloc(sizeof(struct dirent))) == NULL)
-			tst_brkm(TBROK, cleanup, "malloc failed");
+		if (longsyscall) {
+			if ((dirp64 = malloc(sizeof(struct dirent))) == NULL)
+				tst_brkm(TBROK, cleanup, "malloc failed");
+			count = (int)sizeof(struct dirent64);
 
-		count = (int)sizeof(struct dirent);
+		} else {
+			if ((dirp = malloc(sizeof(struct dirent))) == NULL)
+				tst_brkm(TBROK, cleanup, "malloc failed");
+			count = (int)sizeof(struct dirent);
+		}
 
 		/* set up a bad file descriptor */
 
 		fd = -5;
 
-		rval = getdents(fd, dirp, count);
+		if (longsyscall)
+			rval = getdents64(fd, dirp64, count);
+		else
+			rval = getdents(fd, dirp, count);
 
 		/*
 		 * Hopefully we get an error due to the bad file descriptor.
@@ -124,7 +147,10 @@ int main(int ac, char **av)
 		free(dir_name);
 		dir_name = NULL;
 
-		free(dirp);
+		if (longsyscall)
+			free(dirp64);
+		else
+			free(dirp);
 	}
 
 	cleanup();
testcases/kernel/syscalls/getdents/getdents03.c +30 -5
index 700e54b..0c2ef92 100644
@@ -43,10 +43,12 @@
  *             -e   : Turn on errno logging.
  *	       -i n : Execute test n times.
  *	       -I x : Execute test for x seconds.
+ *	       -l   : Test the getdents64 system call.
  *	       -P x : Pause for x seconds between iterations.
  *	       -t   : Turn on syscall timing.
  *
  * HISTORY
+ *	03/2013 - Added -l option by Markos Chandras
  *	03/2001 - Written by Wayne Boyer
  *
  * RESTRICTIONS
@@ -72,6 +74,17 @@ int TST_TOTAL = 1;
 
 int exp_enos[] = { EINVAL, 0 };	/* 0 terminated list of expected errnos */
 
+int longsyscall;
+
+option_t Options[] = {
+		{"l", &longsyscall, NULL}, /* -l long option. Tests getdents64 */
+		{NULL, NULL, NULL}
+};
+
+void help() {
+	printf("  -l      Test the getdents64 system call\n");
+}
+
 int main(int ac, char **av)
 {
 	int lc;
@@ -80,9 +93,10 @@ int main(int ac, char **av)
 	int count;
 	size_t size = 0;
 	char *dir_name = NULL;
+	struct dirent64 *dirp64;
 	struct dirent *dirp;
 
-	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
+	if ((msg = parse_opts(ac, av, Options, &help)) != NULL)
 		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
 
 	setup();
@@ -94,8 +108,13 @@ int main(int ac, char **av)
 			tst_brkm(TBROK, cleanup, "Can not get current "
 				 "directory name");
 
-		if ((dirp = malloc(sizeof(struct dirent))) == NULL)
-			tst_brkm(TBROK, cleanup, "malloc failed");
+		if (longsyscall) {
+			if ((dirp64 = malloc(sizeof(struct dirent64))) == NULL)
+				tst_brkm(TBROK, cleanup, "malloc failed");
+		} else {
+			if ((dirp = malloc(sizeof(struct dirent))) == NULL)
+				tst_brkm(TBROK, cleanup, "malloc failed");
+		}
 
 		/* Set count to be very small.  The result should be EINVAL */
 
@@ -104,7 +123,10 @@ int main(int ac, char **av)
 		if ((fd = open(dir_name, O_RDONLY)) == -1)
 			tst_brkm(TBROK, cleanup, "open of directory failed");
 
-		rval = getdents(fd, dirp, count);
+		if (longsyscall)
+			rval = getdents64(fd, dirp64, count);
+		else
+			rval = getdents(fd, dirp, count);
 
 		/*
 		 * Hopefully we get an error due to the small buffer.
@@ -129,7 +151,10 @@ int main(int ac, char **av)
 		free(dir_name);
 		dir_name = NULL;
 
-		free(dirp);
+		if (longsyscall)
+			free(dirp64);
+		else
+			free(dirp);
 
 		if ((rval = close(fd)) == -1)
 			tst_brkm(TBROK, cleanup, "fd close failed");
testcases/kernel/syscalls/getdents/getdents04.c +33 -8

84 lines not on this page · raw message

Signature · 13 lines
1.7.1



------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list
#1 lore raw

Hi!

testcases/kernel/syscalls/getdents/Makefile top_srcdir ?= ../../../.. · line 24

Quoted 9 lines
testcases/kernel/syscalls/getdents/Makefile +1 -0
index df7b63f..8334aa7 100644
@@ -21,6 +21,8 @@ top_srcdir		?= ../../../..
 include $(top_srcdir)/include/mk/testcases.mk
 include $(abs_srcdir)/../utils/newer_64.mk
 
+CFLAGS += -D_LARGEFILE64_SOURCE

What exactly is this needed for? The getent64 function and linux_dirent64 are both declared in the getdents.h.

Quoted 50 lines
testcases/kernel/syscalls/getdents/Makefile +36 -1
 /*
  * The dirent struct that the C library exports is not the same
@@ -45,6 +48,13 @@ struct linux_dirent {
 	char            d_name[];
 };
 
+struct linux_dirent64 {
+	unsigned long long	d_ino;
+	long long		d_off;
+	unsigned short		d_reclen;
+	char			d_name[];
+};
+
 static inline int
 getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
 {
@@ -57,7 +67,43 @@ getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
 	unsigned int i;
 
 	ptrs.buf = buf;
-	ret = syscall(SYS_getdents, fd, buf, count);
+	ret = ltp_syscall(__NR_getdents, fd, buf, count);
+	if (ret < 0)
+		return ret;
+
+#define kdircpy(field) memcpy(&dirp[i].field, &ptrs.dirp->field, sizeof(dirp[i].field))
+
+	i = 0;
+	while (i < count && i < ret) {
+		unsigned long reclen;
+
+		kdircpy(d_ino);
+		kdircpy(d_reclen);
+		reclen = dirp[i].d_reclen;
+		kdircpy(d_off);
+		strcpy(dirp[i].d_name, ptrs.dirp->d_name);
+
+		ptrs.buf += reclen;
+
+		i += reclen;
+	}
+
+	return ret;
+}
+
+static inline int
+getdents64(unsigned int fd, struct dirent64 *dirp, unsigned int count)
+{
+	union {
+		struct linux_dirent64 *dirp;

testcases/kernel/syscalls/getdents/Makefile getdents(unsigned int fd, struct dirent *dirp, unsigned int count) · line 108

Quoted 10 lines
testcases/kernel/syscalls/getdents/Makefile +8 -0
+		char *buf;
+	} ptrs;
+	char buf[count];
+	long ret;
+	unsigned int i;
+
+	ptrs.buf = buf;
+	ret = ltp_syscall(__NR_getdents64, fd, buf, count);
 	if (ret < 0)
 		return ret;

Well my choice would be casting the buffer to the dirp pointer rather than using the union but looking at the original code, this has been there before...

Quoted 21 lines
testcases/kernel/syscalls/getdents/getdents04.c +2 -0
index 89479a4..7ba8a3d 100644
@@ -43,10 +43,12 @@
  *             -e   : Turn on errno logging.
  *	       -i n : Execute test n times.
  *	       -I x : Execute test for x seconds.
+ *	       -l   : Test the getdents64 system call.
  *	       -P x : Pause for x seconds between iterations.
  *	       -t   : Turn on syscall timing.
  *
  * HISTORY
+ *	03/2013 - Added -l option by Markos Chandras
  *	03/2001 - Written by Wayne Boyer
  *
  * RESTRICTIONS
@@ -73,6 +75,17 @@ int TST_TOTAL = 1;
 
 int exp_enos[] = { ENOTDIR, 0 };	/* 0 terminated list of expected errnos */
 

testcases/kernel/syscalls/getdents/getdents04.c int TST_TOTAL = 1; · line 87

Quoted 10 lines
testcases/kernel/syscalls/getdents/getdents04.c +10 -0
+int longsyscall;
+
+option_t Options[] = {
+		{"l", &longsyscall, NULL}, /* -l long option. Tests getdents64 */
+		{NULL, NULL, NULL}
+};
+
+void help() {
+	printf("  -l      Test the getdents64 system call\n");
+}

Please use LKML coding style, i.e. add void to the function prototype and move the opening bracket on the new line (you can you chekpatch.pl bundled with the linux kernel sources to check for style violations).

Also I tend to declare global functions and variables static so that compiler can report them as unused when they are unused.

Quoted 20 lines
testcases/kernel/syscalls/getdents/getdents04.c +3 -2
 int main(int ac, char **av)
 {
 	int lc;
@@ -80,11 +93,12 @@ int main(int ac, char **av)
 	int count, rval, fd;
 	size_t size = 0;
 	char *dir_name = NULL;
-	struct dirent *dirp;
 	struct stat *sbuf;
 	char *newfile;
+	struct dirent64 *dirp64;
+	struct dirent *dirp;
 
-	if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
+	if ((msg = parse_opts(ac, av, Options, &help)) != NULL)
 		tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
 
 	setup();
@@ -96,10 +110,15 @@ int main(int ac, char **av)
 			tst_brkm(TBROK, cleanup, "Can not get current "

testcases/kernel/syscalls/getdents/getdents04.c int main(int ac, char **av) · line 116

Quoted 10 lines
testcases/kernel/syscalls/getdents/getdents04.c +4 -4
 				 "directory name");
 
-		if ((dirp = malloc(sizeof(struct dirent))) == NULL)
-			tst_brkm(TBROK, cleanup, "malloc failed");
-
-		count = (int)sizeof(struct dirent);
+		if (longsyscall) {
+			if ((dirp64 = malloc(sizeof(struct dirent64))) == NULL)
+				tst_brkm(TBROK, cleanup, "malloc failed");
+			count = (int)sizeof(struct dirent64);

Does really assigment of size_t (return from sizeof) into the int (count) generate warning?

Quoted 21 lines
testcases/kernel/syscalls/getdents/getdents04.c +9 -1
+		} else {
+			if ((dirp = malloc(sizeof(struct dirent))) == NULL)
+				tst_brkm(TBROK, cleanup, "malloc failed");
+			count = (int)sizeof(struct dirent);
+		}
 
 		/* set up some space for a file name */
 		if ((newfile = malloc(sizeof(char) * 20)) == NULL)
@@ -123,7 +142,10 @@ int main(int ac, char **av)
 		if (S_ISDIR(sbuf->st_mode))
 			tst_brkm(TBROK, cleanup, "fd is a directory");
 
-		rval = getdents(fd, dirp, count);
+		if (longsyscall)
+			rval = getdents64(fd, dirp64, count);
+		else
+			rval = getdents(fd, dirp, count);
 
 		/*
 		 * Calling with a non directory file descriptor should give

testcases/kernel/syscalls/getdents/getdents04.c int main(int ac, char **av) · line 177

Quoted 8 lines
testcases/kernel/syscalls/getdents/getdents04.c +4 -1
@@ -149,7 +171,10 @@ int main(int ac, char **av)
 		free(dir_name);
 		dir_name = NULL;
 
-		free(dirp);
+		if (longsyscall)
+			free(dirp64);
+		else
+			free(dirp);

Hmm allocatin and freeing the structure in each loop iteration seems pointless, what about defining it on the stack or allocating it once before the main test loop and not bother freeing it. That would simplify the code.

Signature · 12 lines
Cyril Hrubis
[email protected]

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list

A message that is not in the archive (sent off-list or not yet received): CAG2jQ8ib0+MSxmYqZsj0jaJB5kJhJv9N4OMu_wfQpc9EY6_QkA@mail.gmail.com

#3 lore raw

Hi!

Quoted 6 lines
Quoted 2 lines

What exactly is this needed for? The getent64 function and linux_dirent64 are both declared in the getdents.h.

It's needed for getting the struct dirent64 definition. See /usr/include/bits/dirent.h

Ah right, so we have dirent dirent64 linux_dirent and linux_dirent64 two for the userspace and two for the syscalls.

Signature · 12 lines
Cyril Hrubis
[email protected]

------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_mar
_______________________________________________
Ltp-list mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ltp-list