[LTP] [PATCH v2 2/2] network/nfs05: rewrite the test, make use of new library

Alexey Kodanev alexey.kodanev@oracle.com
Tue Jun 28 18:00:55 CEST 2016


* remove dynamic allocation of memory, use asprintf in few places;
* run built binaries and check that they print correct message;
* run tst_run_cmd() to call make/make clean;
* clean directories with tst_rmdir library.

Signed-off-by: Alexey Kodanev <alexey.kodanev@oracle.com>
---
v2: * added run_targets() to run built binaries and check their output
    * correct generated C files and Makefiles
    * fix makefile: include testcases.mk
    * added check for gcc and make commands

 testcases/network/nfs/nfs_stress/Makefile          |    2 +-
 testcases/network/nfs/nfs_stress/nfs05             |   10 +-
 testcases/network/nfs/nfs_stress/nfs05_make_tree.c |  934 ++++----------------
 3 files changed, 194 insertions(+), 752 deletions(-)

diff --git a/testcases/network/nfs/nfs_stress/Makefile b/testcases/network/nfs/nfs_stress/Makefile
index 0e6aebc..308230f 100644
--- a/testcases/network/nfs/nfs_stress/Makefile
+++ b/testcases/network/nfs/nfs_stress/Makefile
@@ -16,7 +16,7 @@
 
 top_srcdir		?= ../../../..
 
-include $(top_srcdir)/include/mk/env_pre.mk
+include $(top_srcdir)/include/mk/testcases.mk
 
 nfs04_create_file: CPPFLAGS += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
 nfs05_make_tree: LDLIBS += -lpthread
diff --git a/testcases/network/nfs/nfs_stress/nfs05 b/testcases/network/nfs/nfs_stress/nfs05
index 0e15c8c..23a34c7 100755
--- a/testcases/network/nfs/nfs_stress/nfs05
+++ b/testcases/network/nfs/nfs_stress/nfs05
@@ -31,11 +31,17 @@ THREAD_NUM=${THREAD_NUM:-"8"}
 . nfs_lib.sh
 . test_net.sh
 
+tst_check_cmds make gcc
+
 nfs_setup
 
 tst_resm TINFO "start nfs05_make_tree -d $DIR_NUM -f $FILE_NUM -t $THREAD_NUM"
-ROD nfs05_make_tree -d $DIR_NUM -f $FILE_NUM -t $THREAD_NUM
+TMPDIR=$(pwd) nfs05_make_tree -d $DIR_NUM -f $FILE_NUM -t $THREAD_NUM
 
-tst_resm TPASS "test finished"
+if [ $? -ne 0 ]; then
+	tst_resm TFAIL "'make' test failed"
+else
+	tst_resm TPASS "'make' test finished"
+fi
 
 tst_exit
diff --git a/testcases/network/nfs/nfs_stress/nfs05_make_tree.c b/testcases/network/nfs/nfs_stress/nfs05_make_tree.c
index 4163988..98a1040 100644
--- a/testcases/network/nfs/nfs_stress/nfs05_make_tree.c
+++ b/testcases/network/nfs/nfs_stress/nfs05_make_tree.c
@@ -1,179 +1,50 @@
-/******************************************************************************/
-/*									      */
-/* Copyright (c) International Business Machines  Corp., 2001		      */
-/*									      */
-/* This program is free software;  you can redistribute it and/or modify      */
-/* it under the terms of the GNU General Public License as published by       */
-/* the Free Software Foundation; either version 2 of the License, or          */
-/* (at your option) any later version.					      */
-/*									      */
-/* This program is distributed in the hope that it will be useful,	      */
-/* but WITHOUT ANY WARRANTY;  without even the implied warranty of	      */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See	              */
-/* the GNU General Public License for more details.			      */
-/*									      */
-/* You should have received a copy of the GNU General Public License	      */
-/* along with this program;  if not, write to the Free Software		      */
-/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA    */
-/*									      */
-/******************************************************************************/
-
-/******************************************************************************/
-/*                                                                            */
-/* History:     Oct - 10 - 2001 Created - Manoj Iyer, IBM Austin TX.          */
-/*                               email:manjo@austin.ibm.com                   */
-/*					- create a directory tree that is     */
-/*				unique to each process. The base directory    */
-/*				looks like hostname.<pid of the process>      */
-/*				the subdirectories will be <pid>.0 <pid.1> etc*/
-/*				eg:					      */
-/*				    hostname.1234			      */
-/*					       |_ 1234.0	              */
-/*					               |_ 1234.1              */
-/*					                      |_1234.2        */
-/*								    |....     */
-/*				hostname -  hostname of the machine           */
-/*			        1234     -  pid of the current process.       */
-/*			        Each of these directories are populated with  */
-/*				N number of ".c" files and a makefile that can*/
-/*				compile the ".c" files and also initiate      */
-/*				compile of ".c" files in the subdirectories   */
-/*				under it.			              */
-/*                                                                            */
-/*		Oct - 11 - 2001 Modified 				      */
-/*				- fixed a bug in the makefiles, the last make-*/
-/*				  file was expecting subdirectories. Added    */
-/*				  code to generate a different makefile for   */
-/*				  the last subdirectory.		      */
-/*				- Added logic to first compile all the c files*/
-/*				  and upon completion remove them.            */
-/*			        - Added multithreading, arguments handling.   */
-/*				  By default the program will generate 8      */
-/*				  threads, each creating by default 100 deep  */
-/*				  directory tree each containing default 100  */
-/*			          ".c" files and one makefile.                */
-/*			        - Added usage message.                        */
-/*								              */
-/*		Oct - 12 - 2001 Modified			              */
-/*				- Added logic to print missing arguments to   */
-/*				  options.                                    */
-/*                                                                            */
-/*		Oct - 15 - 2001 Modified			              */
-/*				- Added logic to remove the files, makefiles  */
-/*				  and subdirectories that were created.       */
-/*			        - Added logic to print debug messages.        */
-/*								              */
-/*		Oct - 16 - 2001 Modified		                      */
-/*				- Added sync() calls to commit changes.       */
-/*				- Fixed bug. pthread_join() returns 0 when    */
-/*			          pthread_join fails, if the thread function  */
-/*				  fails pthread_join() will put the exit value*/
-/*			          of the thread function in the thread_return */
-/*				  output argument.			      */
-/*				- Debugging function crte_mk_rm fails to      */
-/*				  create fies, problem appears only in multi- */
-/*				  threaded case.                              */
-/*								              */
-/*		Oct - 17 - 2001 Checked in		                      */
-/*				- GPL statement was added and the initial ver */
-/*			        - checked into CVS.		              */
-/*			        - note: this version works only if it is run  */
-/*				  single threaded, when its run multithreaded */
-/*		                  random thread will fail on open() sys call  */
-/*				  problem currently under investigation.      */
-/*                                                                            */
-/*		Oct - 20 - 2001 Modified				      */
-/*				- fixed a whole bunch of problems.            */
-/*			        - created function init_compile. Apparently   */
-/*				  this code works!!.                          */
-/*			        - removed system() system call that was doing */
-/*				  make and make clean. init_compile() replaces*/
-/*				  this piece of code.                         */
-/*				- on supplying the full pathname to unlink()  */
-/*				  solved most of the problems with rm_file_mk */
-/*			          function.                                   */
-/*				- reset the default vaulues for MAXT = 8      */
-/*				  MAXD = 100 and MAXF = 100.                  */
-/*				  ie. maximum number of threads = 8           */
-/*				      directory depth (num of sub dirs) = 100 */
-/*				      numeber of .c fils in each sub dir = 100*/
-/*				- finally program is now in working state.    */
-/*                                                                            */
-/*		Nov - 01 - 2001 Modified.				      */
-/*				- fixed usage message default MAXT is 8 not 1 */
-/*				- fixed make to compile the files silently    */
-/*									      */
-/*		Nov - 19 - 2001 Modified.				      */
-/*				- changed th_status in function main() from   */
-/*				  dynamic variable to static array.           */
-/*									      */
-/* File:        make_tree.c                                                   */
-/*                                                                            */
-/* Description:	This program is designed stress the NFS implimentation.       */
-/* 		Many bugs were uncovered in the AIX operating system          */
-/*		implimentation of NFS when AIX kernel was built over NFS.     */
-/*		Source directory on a remote machine (one server many clients)*/
-/*		NFS-mounted on to a directory on a local machine from which   */
-/*		the kernel build was initiated. Apparently many defects/bugs  */
-/* 		were uncovered when multiple users tried to build the kernel  */
-/* 		by NFS mounting the kernel source from a remote machine and   */
-/* 		tried to build the kernel on a local machine. AIX build envi- */
-/*		ronment is set up to create the object files and executable   */
-/*		on the local machine. 					      */
-/* 		This testcase will try to recreate such a senario.            */
-/*		Spawn N number of threads. Each thread does the following.    */
-/*		* Create a directory tree.                                    */
-/*		* Populate it with ".c" files and makefiles.                  */
-/*		* initate a build. Executable will print hello world when exed*/
-/*		* clean up all the executables that were created.             */
-/*		* recurssively remove each subdir and its contents.           */
-/*		The test is aimed at stressing the NFS client and server.     */
-/*				    hostname.1234			      */
-/*                                             |                              */
-/*				               | - 1234.0.0.c                 */
-/*					       | - 1234.0.1.c                 */
-/*                                             | - ..........                 */
-/*					       | - makefile                   */
-/*                                             |                              */
-/*					       |_ 1234.0	              */
-/*                                                    |                       */
-/*				                      | - 1234.1.0.c          */
-/*					              | - 1234.1.1.c          */
-/*                                                    | - ..........          */
-/*					              | - makefile            */
-/*                                                    |                       */
-/*					              |_ 1234.1               */
-/*                                                           |                */
-/*				                             | - 1234.2.0.c   */
-/*					                     | - 1234.2.1.c   */
-/*                                                           | - ..........   */
-/*					                     | - makefile     */
-/*                                                           |                */
-/*					                     |_1234.2         */
-/*								    |....     */
-/*                                                                            */
-/* Setup:	- on the server side:			                      */
-/*		  * create a directory /nfs_test 		              */
-/*		  * make an entry in /etc/exports file like this...           */
-/*		    "/nfs_test *(rw,no_root_squash)"		              */
-/*		  * run command "exportfs -a"		                      */
-/*	        - on client side:			                      */
-/*		  * create a directory say for eg: /nfs_cli                   */
-/*		  * mount -t nfs servername:/nfs_test /nfs_cli                */
-/*		  * set up the tescase in /nfs_cli directory		      */
-/*		- I reccomend that you have atleast 8 client machines running */
-/*		   this test, linux has 8 NFSD's running by default, you might*/
-/*		   have to increase it as per your requirement.               */
-/*		                                                              */
-/* Note:	- assumed that NFS services are installed and configured      */
-/*		- you have atleast 2 machines to act as client and server     */
-/*		  (you can have muiltiple client machines and one server)     */
-/*		- large amount of disk space, this depends on the number of   */
-/*		  of clients you will have, if you have only one client, I    */
-/*		  reccomend that the server have atleast 4 Giga bytes of      */
-/*		  disk space (paranoid!).			              */
-/*									      */
-/******************************************************************************/
+/*
+ * Copyright (c) 2016 Oracle and/or its affiliates. All Rights Reserved.
+ * Copyright (c) International Business Machines  Corp., 2001
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ * Description:
+ * This program is designed to stress the NFS implimentation. Many bugs were
+ * uncovered in the AIX operating system implimentation of NFS when AIX kernel
+ * was built over NFS. Source directory on a remote machine (one server many
+ * clients) NFS-mounted on to a directory on a local machine from which the
+ * kernel build was initiated. Apparently many defects/bugs were uncovered when
+ * multiple users tried to build the kernel by NFS mounting the kernel source
+ * from a remote machine and tried to build the kernel on a local machine.
+ *
+ * The test's aimed to stress NFS client/server and recreates such a senario.
+ * Spawn N number of threads. Each thread does the following:
+ *   * create a directory tree;
+ *   * populate it with ".c" files and makefiles;
+ *     hostname.1234
+ *             | - 1234.0.0.c
+ *             | - ..........
+ *             | - makefile
+ *             |_ 1234.0
+ *                    |
+ *                    | - 1234.1.0.c
+ *                    | - ..........
+ *                    | - makefile
+ *                    |_ 1234.1
+ *                           |....
+ *
+ *   * initate a build, executable will print hello world;
+ *   * clean up all the executables that were created;
+ *   * recurssively remove each subdir and its contents.
+ *
+ */
 
 #include <stdio.h>
 #include <sys/stat.h>
@@ -188,609 +59,174 @@
 #include <errno.h>
 #include <linux/unistd.h>
 
-#define gettid() syscall(__NR_gettid)
-
-#ifdef DEBUG
-#define dprt(fmt, args...)	printf(fmt, ## args)
-#else
-#define dprt(fmt, args...)
-#endif
-
-#define MAKE_EXE	1	/* initate a make                             */
-#define MAKE_CLEAN	0	/* initate a make clean                       */
-
-#define PTHREAD_EXIT(val)    do {\
-			exit_val = val; \
-                        dprt("pid[%d]: exiting with %d\n", gettid(),exit_val); \
-			pthread_exit((void *)exit_val); \
-				} while (0)
-
-#define OPT_MISSING(prog, opt)   do{\
-			       fprintf(stderr, "%s: option -%c ", prog, opt); \
-                               fprintf(stderr, "requires an argument\n"); \
-                               usage(prog); \
-                                   } while (0)
-
-#define MAXD	100		/* default number of directories to create.           */
-#define MAXF	100		/* default number of files to create.                 */
-#define MAXT	8		/* default number of threads to create.               */
-
-/******************************************************************************/
-/*								 	      */
-/* Function:	usage							      */
-/*									      */
-/* Description:	Print the usage message.				      */
-/*									      */
-/* Return:	exits with -1						      */
-/*									      */
-/******************************************************************************/
-static void usage(char *progname)
-{				/* name of this program                       */
-	fprintf(stderr,
-		"Usage: %s -d NUMDIR -f NUMFILES -h -t NUMTHRD\n"
-		"\t -d Number of subdirectories to generate:   Default: 100\n"
-		"\t -f Number of c files in each subdirectory: Default: 100\n"
-		"\t -h Help!\n"
-		"\t -t Number of threads to generate:          Default: 8\n",
-		progname);
-	exit(-1);
-}
+#include "lapi/mkdirat.h"
+#include "tst_safe_stdio.h"
+#include "tst_test.h"
 
-/******************************************************************************/
-/*								 	      */
-/* Function:	init_compile						      */
-/*									      */
-/* Description:	This function compiles the .c files and removes the exeutables*/
-/*		This function does the same function as the system() system   */
-/*		call, the code is available in the system() man page. When    */
-/*		called with the parameter MAKE_EXE it will initiate make in   */
-/*		the first directory created, the makefile is designed to build*/
-/*		recursively all the files in the subdirectories below.        */
-/*		When called with the MAKE_CLEAN parameter it will remove the  */
-/*		executables that were created design is similar to the case   */
-/*		were it initiates a make.                                     */
-/*									      */
-/* Return:	exits with 1 on error, 0 on success                           */
-/*									      */
-/******************************************************************************/
-static int init_compile(int what_todo,	/* do a compile or clean             */
-			char *base_dir,	/* base directory of the test        */
-			char *hname)
-{				/* hostname of the machine           */
-	int status;		/* return status of execve process            */
-	pid_t pid;		/* pid of the process that does compile       */
-	char *dirname;		/* location where compile is initated         */
-	char *command;		/* make or make clean command.                */
-
-	if ((dirname = malloc(sizeof(char) * 2048)) == NULL) {	/* just paranoid */
-		perror("init_compile(): dirname malloc()");
-		return 1;
-	}
+#define gettid() syscall(__NR_gettid)
 
-	if ((command = malloc(sizeof(char) * 1024)) == NULL) {	/* just paranoid */
-		perror("init_compile(): dirname malloc()");
-		return 1;
-	}
+static int thrd_num = 8;
+static int dirs_num = 100;
+static int file_num = 100;
 
-	what_todo ? sprintf(command, "make -s") : sprintf(command,
-							  "make -s clean");
+static char *t_arg, *d_arg, *f_arg;
 
-	sprintf(dirname, "%s/%s.%ld", base_dir, hname, gettid());
+static struct tst_option opts[] = {
+	{"t:", &t_arg, "-t x    Number of threads to generate, default: 8\n"},
+	{"d:", &d_arg, "-d x    Number of subdirs to generate, default: 100\n"},
+	{"f:", &f_arg, "-f x    Number of c files in each dir, default: 100\n"},
+	{NULL, NULL, NULL}
+};
 
-	if (chdir(dirname) == -1) {
-		dprt("pid[%d]: init_compile(): dir name = %s\n", gettid(),
-		     dirname);
-		perror("init_compile() chdir()");
-		free(dirname);
-		return 1;
-	}
+static void run_targets(const char *dirname, char *cfile, pid_t tid)
+{
+	int i, k, fd;
+	char subdir[PATH_MAX] = {0};
+	char *output_file;
+	char buf[11];
+	const char *const cmd_run[] = {cfile, NULL};
 
-	dprt("pid[%d]: init_compile(): command = %s\n", gettid(), command);
+	SAFE_ASPRINTF(&output_file, "%s/cmd.out", dirname);
 
-	if ((pid = fork()) == -1) {
-		perror("init_compile(): fork()");
-		return 1;
-	}
-	if (!pid) {
-		char *argv[4];
+	/* run each binary */
+	for (i = 0; i < dirs_num; ++i) {
+		for (k = 0; k < file_num; ++k) {
+			snprintf(cfile, PATH_MAX, "%s%s/%d.%d.%d",
+				 dirname, subdir, tid, i, k);
 
-		argv[0] = "/bin/sh";
-		argv[1] = "-c";
-		argv[2] = command;
-		argv[3] = 0;
+			tst_run_cmd(cmd_run, output_file, NULL, 0);
 
-		if (execv("/bin/sh", argv) == -1) {
-			perror("init_compile(): execv()");
-			return 1;
+			fd = SAFE_OPEN(output_file, O_RDONLY);
+			SAFE_READ(1, fd, buf, 11);
+			if (strncmp(buf, "hello world", 11))
+				tst_brk(TFAIL, "command printed wrong message");
+			SAFE_CLOSE(fd);
 		}
+		strcat(subdir, "/dir");
 	}
-	do {
-		if (waitpid(pid, &status, 0) == -1) {
-			if (errno != EINTR) {
-				fprintf(stderr,
-					"init_compile(): waitpid() failed\n");
-				return 1;
-			}
-		} else {
-			if (chdir(base_dir) == -1) {
-				dprt("pid[%d]: init_compile(): dir = %s\n",
-				     gettid(), dirname);
-				perror("init_compile(): chdir()");
-				return 1;
-			}
 
-			dprt("pid[%d]: init_compile(): status = %d\n",
-			     gettid(), status);
-			dprt("we are here %d\n", __LINE__);
-			return status;
-		}
-
-	} while (1);
+	free(output_file);
 }
 
-/******************************************************************************/
-/*								 	      */
-/* Function:	rm_file_dir						      */
-/*									      */
-/* Description: This function removes the .c files makefiles and directories. */
-/*		First removes the files in the files in the last directory    */
-/*		first then removes the last directory, then cycles through    */
-/*		each subdirectory and does the same.			      */
-/*									      */
-/* Return:	exits with 1 on error, 0 on success      		      */
-/*									      */
-/******************************************************************************/
-static int rm_file_dir(int numsdir,	/* how many subdirs to remove         */
-		       int numfiles,	/* number of files to remove per dir  */
-		       char *hname,	/* hostname of the client machine     */
-		       char *base_dir)
-{				/* directory where the test is located */
-	int filecnt;		/* index to the num of files to remove */
-	int dircnt;		/* index into directory tree          */
-	int sindex = numsdir;	/* num subdirectory tree to remove    */
-	char *dirname;		/* name of the directory to chdir()   */
-	char *tmpdirname;	/* temp name for directory, for swap  */
-	char *filename;		/* name of the cfile to remove        */
-	char *subdir;		/* name of the sub dir to remove      */
-
-	if ((dirname = malloc(sizeof(char) * 2048)) == NULL) {	/* just paranoid */
-		perror("crte_mk_rm(): dirname malloc()");
-		return 1;
-	}
-
-	if ((tmpdirname = malloc(sizeof(char) * 2048)) == NULL) {	/* just paranoid */
-		perror("crte_mk_rm(): tmpdirname malloc()");
-		return 1;
-	}
-
-	if ((filename = malloc(sizeof(char) * 2048)) == NULL) {	/* just paranoid */
-		perror("crte_mk_rm(): filename malloc()");
-		return 1;
-	}
-
-	if ((subdir = malloc(sizeof(char) * 2048)) == NULL) {	/* just paranoid */
-		perror("crte_mk_rm(): subdir malloc()");
-		return 1;
-	}
-
-	dprt("pid[%d]: base directory: %s\n", gettid(), base_dir);
-	while (sindex) {
-		/* get the name of the last directory created. */
-		for (dircnt = 0; dircnt < sindex; dircnt++) {
-			if (dircnt == 0)
-				sprintf(dirname, "%s/%s.%ld", base_dir, hname,
-					gettid());
-			else {
-				sprintf(tmpdirname, "%s/%ld.%d", dirname,
-					gettid(), dircnt);
-				sprintf(dirname, "%s", tmpdirname);
-			}
-			sync();
-		}
-
-		dprt("pid[%d]: cd'ing to last created dir: %s\n", gettid(),
-		     dirname);
-
-		sindex--;
-
-		/* remove all the ".c" files and makefile in this directory */
-		for (filecnt = 0; filecnt < numfiles; filecnt++) {
-			sprintf(filename, "%s/%ld.%d.%d.c", dirname, gettid(),
-				dircnt - 1, filecnt);
-			dprt("pid[%d]: removing file: %s\n", gettid(),
-			     filename);
-
-			if (unlink(filename)) {
-				dprt("pid[%d]: failed removing file: %s\n",
-				     gettid(), filename);
-				perror("rm_file_dir(): unlink()");
-				free(tmpdirname);
-				free(dirname);
-				free(filename);
-				free(subdir);
-				return 1;
+static void *thread_fn(LTP_ATTRIBUTE_UNUSED void *args)
+{
+	const char prog_buf[] = "#include <stdio.h>\n"
+				"int main(void)\n{\n"
+				"\tprintf(\"hello world\");\n"
+				"\treturn 0;\n}\n";
+
+	const char make_buf_n[] = "CFLAGS := -O -w -g\n"
+				  "SRCS=$(wildcard *.c)\n"
+				  "TARGETS=$(SRCS:.c=)\n"
+				  "all: $(TARGETS)\n"
+				  "$(TARGETS): %: %.c\n"
+				  "\t$(CC) -o $@ $<\n"
+				  "clean:\n\trm -f $(TARGETS)\n"
+				  ".PHONY: all clean\n";
+
+	const char make_buf[] = "CFLAGS := -O -w -g\n"
+				"SUBDIR = dir\n"
+				"SRCS=$(wildcard *.c)\n"
+				"TARGETS=$(SRCS:.c=)\n"
+				"all: $(SUBDIR) $(TARGETS)\n"
+				"$(TARGETS): %: %.c\n"
+				"\t$(CC) -o $@ $<\n"
+				"$(SUBDIR):\n\t$(MAKE) -C $@\n"
+				"clean:\n"
+				"\trm -f $(TARGETS)\n"
+				"\t$(MAKE) -C $(SUBDIR) clean\n"
+				".PHONY: all $(SUBDIR) clean\n";
+
+	int i, k, fd, dirfd, ret;
+	char *dirname;
+	char cfile[PATH_MAX];
+	char hostname[256];
+	pid_t tid = gettid();
+
+	SAFE_GETHOSTNAME(hostname, 256);
+	SAFE_ASPRINTF(&dirname, "%s.%ld", hostname, tid);
+
+	SAFE_MKDIR(dirname, 0755);
+	dirfd = SAFE_OPEN(dirname, O_DIRECTORY);
+
+	for (i = 0; i < dirs_num; ++i) {
+
+		fd = openat(dirfd, "makefile", O_CREAT | O_RDWR,
+			    S_IRWXU | S_IRWXG | S_IRWXO);
+		if (fd < 0)
+			tst_brk(TFAIL | TERRNO, "openat(makefile) failed");
+
+		if (i == dirs_num - 1)
+			SAFE_WRITE(1, fd, make_buf_n, sizeof(make_buf_n) - 1);
+		else
+			SAFE_WRITE(1, fd, make_buf, sizeof(make_buf) - 1);
+
+		SAFE_CLOSE(fd);
+
+		for (k = 0; k < file_num; ++k) {
+			snprintf(cfile, PATH_MAX, "%d.%d.%d.c", tid, i, k);
+			fd = openat(dirfd, cfile, O_CREAT | O_RDWR,
+				    S_IRWXU | S_IRWXG | S_IRWXO);
+			if (fd < 0) {
+				tst_brk(TFAIL | TERRNO,
+					"openat(%s) failed", cfile);
 			}
-			sync();
-		}
 
-		sprintf(filename, "%s/%s", dirname, "makefile");
-		dprt("pid[%d]: removing %s\n", gettid(), filename);
-		if (unlink(filename)) {
-			perror
-			    ("rm_file_dir() cound not remove makefile unlink()");
-			free(tmpdirname);
-			free(dirname);
-			free(filename);
-			free(subdir);
-			return 1;
+			SAFE_WRITE(1, fd, prog_buf, sizeof(prog_buf) - 1);
+			SAFE_CLOSE(fd);
 		}
-		sync();
-
-		/* the last directory does not have any more sub directories */
-		/* nothing to remove.                                    */
-		dprt("pid[%d]: in directory count(dircnt): %d\n", gettid(),
-		     dircnt);
-		dprt("pid[%d]: last directory(numsdir): %d\n", gettid(),
-		     numsdir);
-		if (dircnt < numsdir) {
-			/* remove the sub directory */
-			sprintf(subdir, "%s/%ld.%d", dirname, gettid(), dircnt);
-			dprt("pid[%d]: removing subdirectory: %s\n", gettid(),
-			     subdir);
-			if (rmdir(subdir) == -1) {
-				perror("rm_file_dir() rmdir()");
-				free(tmpdirname);
-				free(dirname);
-				free(filename);
-				free(subdir);
-				return 1;
-			}
-			sync();
-		}
-	}
-
-	free(tmpdirname);
-	free(dirname);
-	free(filename);
-	free(subdir);
-	return 0;
-}
-
-/******************************************************************************/
-/*								 	      */
-/* Function:	crte_mk_rm						      */
-/*									      */
-/* Description:	This function gets executed by each thread that is created.   */
-/*		crte_mk_rm() created the directory tree, polpulates it with   */
-/*		".c" files and a makefile that will compile the ".c" files and*/
-/*		initiate the makefile in the subdirectory under it. Once the  */
-/*		c source files are compiled it will remove them.              */
-/*									      */
-/* Input:	The argument pointer contains the following.                  */
-/*		arg[0] - number of directories to create, depth of the tree.  */
-/*		arg[1] - number of ".c" files to create in each dir branch.   */
-/*									      */
-/* Return:	-1 on failure						      */
-/*		 0 on success					              */
-/*									      */
-/******************************************************************************/
-static void *crte_mk_rm(void *args)
-{
-	int dircnt;		/* index to the number of subdirectories      */
-	int fd;			/* file discriptor of the files genetated     */
-	int filecnt;		/* index to the number of ".c" files created  */
-	int numchar[2];		/* number of characters written to buffer     */
-	char *dirname;		/* name of the directory/idirectory tree      */
-	char *tmpdirname;	/* name of a temporary directory, for swaping */
-	char *cfilename;	/* name of the ".c" file created              */
-	char *mkfilename;	/* name of the makefile - which is "makefile" */
-	char *hostname;		/* hostname of the client machine             */
-	char *prog_buf;		/* buffer containing contents of the ".c" file */
-	char *make_buf;		/* buffer the contents of the makefile        */
-	char *pwd;		/* contains the current working directory     */
-	long *locargptr =	/* local pointer to arguments                 */
-	    (long *)args;
-	volatile int exit_val = 0;	/* exit value of the pthreads                 */
-
-	if ((dirname = malloc(sizeof(char) * 2048)) == NULL) {	/* just paranoid */
-		perror("crte_mk_rm(): dirname malloc()");
-		PTHREAD_EXIT(-1);
-	}
-
-	if ((tmpdirname = malloc(sizeof(char) * 2048)) == NULL) {
-		perror("crte_mk_rm(): tmpdirname malloc()");
-		PTHREAD_EXIT(-1);
-	}
-
-	if ((cfilename = malloc(sizeof(char) * 2048)) == NULL) {
-		perror("crte_mk_rm(): cfilename malloc()");
-		PTHREAD_EXIT(-1);
-	}
-
-	if ((mkfilename = malloc(sizeof(char) * 2048)) == NULL) {
-		perror("crte_mk_rm(): mkfilename malloc()");
-		PTHREAD_EXIT(-1);
-	}
-
-	if ((prog_buf = malloc(sizeof(char) * 4096)) == NULL) {
-		perror("crte_mk_rm(): prog_buf malloc()");
-		PTHREAD_EXIT(-1);
-	}
-
-	if ((pwd = malloc(PATH_MAX)) == NULL) {
-		perror("crte_mk_rm(): pwd malloc()");
-		PTHREAD_EXIT(-1);
-	}
 
-	if ((hostname = malloc(sizeof(char) * 1024)) == NULL) {
-		perror("crte_mk_rm(): hostname malloc()");
-		PTHREAD_EXIT(-1);
-	}
-
-	if (gethostname(hostname, 255) == -1) {
-		perror("crte_mk_rm(): gethostname()");
-		PTHREAD_EXIT(-1);
-	}
-	if (!getcwd(pwd, PATH_MAX)) {
-		perror("crte_mk_rm(): getcwd()");
-		PTHREAD_EXIT(-1);
-	}
-
-	numchar[0] = sprintf(prog_buf,
-			     "main()\n{\n\t printf(\"hello world\");\n}\n");
-
-	for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++) {
-		/* First create the base directory, then create the subdirectories   */
-		if (dircnt == 0)
-			sprintf(dirname, "%s.%ld", hostname, gettid());
-		else {
-			sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(),
-				dircnt);
-			sprintf(dirname, "%s", tmpdirname);
-		}
-		sync();
+		if (i == dirs_num - 1)
+			break;
 
-		dprt("pid[%d] creating directory: %s\n", gettid(), dirname);
-		if (mkdir(dirname, 0777) == -1) {
-			perror("crte_mk_rm(): mkdir()");
-			PTHREAD_EXIT(-1);
-		}
+		ret = mkdirat(dirfd, "dir", 0755);
+		if (ret < 0)
+			tst_brk(TFAIL | TERRNO, "mkdirat('dir') failed");
+		dirfd = openat(dirfd, "dir", O_DIRECTORY);
+		if (dirfd < 0)
+			tst_brk(TFAIL | TERRNO, "openat('dir') failed");
 	}
 
-	sync();
-	usleep(10);
-	for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++) {
-		if (dircnt == 0)
-			sprintf(dirname, "%s/%s.%ld", pwd, hostname, gettid());
-		else {
-			sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(),
-				dircnt);
-			sprintf(dirname, "%s", tmpdirname);
-		}
-		sync();
-		if ((make_buf = malloc(sizeof(char) * 4096)) == NULL) {
-			perror("crte_mk_rm(): make_buf malloc()");
-			PTHREAD_EXIT(-1);
-		}
-		sprintf(mkfilename, "%s/makefile", dirname);
-		{
-			/* HACK! I could not write "%.c" to the makefile */
-			/* there is probably a correct way to do it      */
-			char *dotc = malloc(10);
-			dotc = ".c";
-			sync();
-			usleep(10);
-			if (dircnt == (locargptr[0] - 1)) {
-				numchar[1] = sprintf(make_buf,
-						     "CFLAGS := -O -w -g\n"
-						     "SUBDIRS = %ld.%d\n"
-						     "SRCS=$(wildcard *.c)\n"
-						     "TARGETS=$(patsubst %%%s,\%%,$(SRCS))\n"
-						     "all:\t $(TARGETS)\n"
-						     "clean:\n"
-						     "\trm -f $(TARGETS)\n",
-						     gettid(), dircnt + 1,
-						     dotc);
-			} else {
-				numchar[1] = sprintf(make_buf,
-						     "CFLAGS := -O -w -g\n"
-						     "SUBDIRS = %ld.%d\n"
-						     "SRCS=$(wildcard *.c)\n"
-						     "TARGETS=$(patsubst %%%s,\%%,$(SRCS))\n\n\n"
-						     "all:\t $(TARGETS)\n"
-						     "\t@for i in $(SUBDIRS); do $(MAKE) -C $$i ; done\n\n"
-						     "clean:\n"
-						     "\trm -f $(TARGETS)\n"
-						     "\t@for i in $(SUBDIRS); do $(MAKE) -C $$i clean ; done\n",
-						     gettid(), dircnt + 1,
-						     dotc);
-			}
-		}
-
-		sync();
-		usleep(10);
-		dprt("pid[%d]: creating in dir: %s\n", gettid(), mkfilename);
-		/* create the makefile, complies .c files and initiates make in   */
-		/* subdirectories.                                                */
-		if ((fd = open(mkfilename, O_CREAT | O_RDWR,
-			       S_IRWXU | S_IRWXG | S_IRWXO)) == -1) {
-			dprt(" pid[%d]: failed to create makefile\n", gettid());
-			dprt("pid[%d]: failed in directory %s\n", gettid(),
-			     dirname);
-			perror("crte_mk_rm() failed creating makefile: open()");
-			PTHREAD_EXIT(-1);
-		} else {
-			sync();
-			if (write(fd, make_buf, numchar[1]) == -1) {
-				perror("crte_mk_rm(): write()");
-				PTHREAD_EXIT(-1);
-			}
+	const char *const cmd_make[] = {"make", "-s", "-C", dirname, NULL};
+	const char *const cmd_make_clean[] = {
+		"make", "-C", dirname, "-s", "clean", NULL};
 
-			free(make_buf);
+	tst_run_cmd(cmd_make, NULL, NULL, 0);
 
-			if (close(fd) == -1) {
-				perror("crte_mk_rm(): close()");
-				PTHREAD_EXIT(-1);
-			}
-		}
-	}
+	run_targets(dirname, cfile, tid);
 
-	for (dircnt = 0; dircnt < (int)locargptr[0]; dircnt++) {
-		if (dircnt == 0)
-			sprintf(dirname, "%s/%s.%ld", pwd, hostname, gettid());
-		else {
-			sprintf(tmpdirname, "%s/%ld.%d", dirname, gettid(),
-				dircnt);
-			sprintf(dirname, "%s", tmpdirname);
-		}
-		sync();
-		/* In each directory create N ".c" files and a makefile. */
-		for (filecnt = 0; filecnt < (int)locargptr[1]; filecnt++) {
-			sprintf(cfilename, "%s/%ld.%d.%d.c", dirname, gettid(),
-				dircnt, filecnt);
-			dprt("pid[%d]: creating file: %s\n", gettid(),
-			     cfilename);
-			if ((fd =
-			     open(cfilename, O_CREAT | O_RDWR,
-				  S_IRWXU | S_IRWXG | S_IRWXO)) == -1) {
-				fprintf(stderr,
-					"open() failed to create file %s\n",
-					cfilename);
-				perror
-				    ("crte_mk_rm(): failed creating .c files: open()");
-				PTHREAD_EXIT(-1);
-			} else {
-				sync();
-				/* write the code, this program prints hello world */
-				if (write(fd, prog_buf, numchar[0]) == -1) {
-					perror("crte_mk_rm(): write()");
-					PTHREAD_EXIT(-1);
-				}
-
-				fsync(fd);
-
-				if (close(fd) == -1) {
-					perror("crte_mk_rm(): close()");
-					PTHREAD_EXIT(-1);
-				}
-			}
+	tst_run_cmd(cmd_make_clean, NULL, NULL, 0);
 
-		}
-	}
+	free(dirname);
 
-	if (init_compile(MAKE_EXE, pwd, hostname) == 1) {
-		fprintf(stderr, "init_compile() make failed\n");
-		PTHREAD_EXIT(-1);
-	} else {
-		if (init_compile(MAKE_CLEAN, pwd, hostname) == 1) {
-			fprintf(stderr, "init_compile() make clean failed\n");
-			PTHREAD_EXIT(-1);
-		}
-	}
+	return NULL;
+}
 
-	sync();
-	/* remove all the files makefiles and subdirecotries  */
-	if (rm_file_dir((int)locargptr[0], (int)locargptr[1], hostname, pwd)) {
-		fprintf(stderr, "crte_mk_rm(): rm_file_dir() failed\n");
-		PTHREAD_EXIT(-1);
-	}
-	/* if it made it this far exit with success */
-	PTHREAD_EXIT(0);
+static void setup(void)
+{
+	thrd_num = atoi(t_arg);
+	dirs_num = atoi(d_arg);
+	file_num = atoi(f_arg);
 }
 
-/******************************************************************************/
-/*								 	      */
-/* Function:	main							      */
-/*									      */
-/* Description:	This is the entry point to the program. This function will    */
-/*		parse the input arguments and set the values accordingly. If  */
-/*		no arguments (or desired) are provided default values are used*/
-/*		refer the usage function for the arguments that this program  */
-/*		takes. It also creates the threads which do most of the dirty */
-/*		work. If the threads exits with a value '0' the program exits */
-/*		with success '0' else it exits with failure '-1'.             */
-/*									      */
-/* Return:	-1 on failure						      */
-/*		 0 on success						      */
-/*									      */
-/******************************************************************************/
-int main(int argc,		/* number of input parameters                 */
-	 char **argv)
-{				/* pointer to the command line arguments.     */
-	int c;			/* command line options                       */
-	int num_thrd = MAXT;	/* number of threads to create                */
-	int num_dirs = MAXD;	/* number of subdirectories to create         */
-	int num_files = MAXF;	/* number of files in each subdirectory      */
-	int thrd_ndx;		/* index into the array of thread ids         */
-	void *th_status;	/* exit status of LWP's                       */
-	pthread_t thrdid[30];	/* maxinum of 30 threads allowed              */
-	long chld_args[3];	/* arguments to the thread function           */
-	extern int optopt;	/* options to the program                     */
-
-	while ((c = getopt(argc, argv, "d:f:ht:")) != -1) {
-		switch (c) {
-		case 'd':	/* specify how deep the tree needs to grow    */
-			if ((num_dirs = atoi(optarg)) == 0)
-				OPT_MISSING(argv[0], optopt);
-			else if (num_dirs < 0) {
-				fprintf(stdout,
-					"WARNING: bad argument. Using default\n");
-				num_dirs = MAXD;
-			}
-			break;
-		case 'f':	/* how many ".c" files in each directory.     */
-			if ((num_files = atoi(optarg)) == 0)
-				OPT_MISSING(argv[0], optopt);
-			else if (num_files < 0) {
-				fprintf(stdout,
-					"WARNING: bad argument. Using default\n");
-				num_files = MAXF;
-			}
-			break;
-		case 'h':
-			usage(argv[0]);
-			break;
-		case 't':
-			if ((num_thrd = atoi(optarg)) == 0)
-				OPT_MISSING(argv[0], optopt);
-			else if (num_thrd < 0) {
-				fprintf(stdout,
-					"WARNING: bad argument. Using default\n");
-				num_thrd = MAXT;
-			}
-			break;
-		default:
-			usage(argv[0]);
-			break;
-		}
-	}
+static void do_test(void)
+{
+	int i;
+	pthread_t id[thrd_num];
 
-	chld_args[0] = num_dirs;
-	chld_args[1] = num_files;
+	for (i = 0; i < thrd_num; ++i)
+		SAFE_PTHREAD_CREATE(id + i, NULL, thread_fn, NULL);
 
-	for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++) {
-		if (pthread_create
-		    (&thrdid[thrd_ndx], NULL, crte_mk_rm, chld_args)) {
-			perror("crte_mk_rm(): pthread_create()");
-			exit(-1);
-		}
-	}
+	for (i = 0; i < thrd_num; ++i)
+		SAFE_PTHREAD_JOIN(id[i], NULL);
 
-	sync();
-
-	for (thrd_ndx = 0; thrd_ndx < num_thrd; thrd_ndx++) {
-		if (pthread_join(thrdid[thrd_ndx], &th_status) != 0) {
-			perror("crte_mk_rm(): pthread_join()");
-			exit(-1);
-		} else {
-			dprt("WE ARE HERE %d\n", __LINE__);
-			if (th_status == (void *)-1) {
-				fprintf(stderr,
-					"thread [%ld] - process exited with errors\n",
-					thrdid[thrd_ndx]);
-				exit(-1);
-			}
-		}
-	}
-	return (0);
+	tst_res(TPASS, "'make' successfully build and clean all targets");
 }
+
+static struct tst_test test = {
+	.tid = "nfs05_make_tree",
+	.options = opts,
+	.needs_tmpdir = 1,
+	.test_all = do_test,
+	.setup = setup,
+};
-- 
1.7.1



More information about the ltp mailing list