lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Thu, 27 Aug 2009 15:46:46 +0530
From:	Subrata Modak <subrata@...ux.vnet.ibm.com>
To:	Andreas Dilger <adilger@....com>
Cc:	Subrata Modak <subrata@...ux.vnet.ibm.com>,
	linux-ext4@...r.kernel.org, Dave Jones <davej@...hat.com>,
	LTP List <ltp-list@...ts.sourceforge.net>
Subject: [PATCH] Updated fsx.c program

Hi Andreas,

>On Tue, 2009-08-25 at 23:25 -0600, Andreas Dilger wrote:
>I've done some work to merge some of the existing fsx.c mods into a
> single version.  Over & above the version that is in the LTP, I've
> included AKPM's O_DIRECT fixes (with a twist), the BSD mmap page and
> segfault handling, and per-write fsync.
> 
> The twist for the O_DIRECT feature is that it will randomly open file
> descriptors with O_DIRECT, and if you use the Lustre-inspired multi-fd
> support fsx will be testing concurrent buffered and O_DIRECT and mmap
> IO on the same file.

The following patch will integrate your new fsx.c program in LTP, by replacing
(http://ltp.cvs.sourceforge.net/viewvc/ltp/ltp/testcases/kernel/fs/fsx-linux/fsx-linux.c)
the existing one. Would you mind providing a Sign-off for the below Patch ?

Patch-prepared-for-ltp-by: Subrata Modak <subrata@...ux.vnet.ibm.com>
---

--- ltp-intermediate-20090822/testcases/kernel/fs/fsx-linux/fsx-linux.c.orig	2009-08-27 15:36:30.000000000 +0530
+++ ltp-intermediate-20090822/testcases/kernel/fs/fsx-linux/fsx-linux.c	2009-08-27 15:36:41.000000000 +0530
@@ -1,5 +1,4 @@
 /*
- * Copyright (C) 1991, NeXT Computer, Inc.  All Rights Reserverd.
  * Copyright (c) 1998-2001 Apple Computer, Inc. All rights reserved.
  *
  * @APPLE_LICENSE_HEADER_START@
@@ -32,9 +31,14 @@
  *	Small changes to work under Linux -- davej@...e.de
  *
  *	Sundry porting patches from Guy Harris 12/2001
- * $FreeBSD: src/tools/regression/fsx/fsx.c,v 1.1 2001/12/20 04:15:57 jkh Exp $
+ *
+ *	Checks for mmap last-page zero fill.
  *
  *	Add multi-file testing feature -- Zach Brown <zab@...sterfs.com>
+ *
+ * $FreeBSD: src/tools/regression/fsx/fsx.c,v 1.2 2003/04/23 23:42:23 jkh Exp $
+ * $DragonFly: src/test/stress/fsx/fsx.c,v 1.2 2005/05/02 19:31:56 dillon Exp $
+ *
  */
 
 #include <sys/types.h>
@@ -59,6 +63,7 @@
 #include <unistd.h>
 #include <stdarg.h>
 #include <errno.h>
+#include <setjmp.h>
 
 /*
  *	A log entry is an operation and a bunch of arguments.
@@ -66,15 +71,17 @@
 
 struct log_entry {
 	int	operation;
-	struct timeval tv;
 	int	args[3];
+	struct timeval tv;
 };
 
-#define	LOGSIZE	1000
+#define	LOGSIZE	100000
 
 struct log_entry	oplog[LOGSIZE];	/* the log */
 int			logptr = 0;	/* current position in log */
 int			logcount = 0;	/* total ops */
+int			jmpbuf_good;
+jmp_buf			jmpbuf;
 
 /*
  *	Define operations
@@ -107,6 +114,7 @@ unsigned long	simulatedopcount = 0;	/* -
 int	closeprob = 0;			/* -c flag */
 int	debug = 0;			/* -d flag */
 unsigned long	debugstart = 0;		/* -D flag */
+int	do_fsync = 0;			/* -f flag */
 unsigned long	maxfilelen = 256 * 1024;	/* -l flag */
 int	sizechecks = 1;			/* -n flag disables them */
 int	maxoplen = 64 * 1024;		/* -o flag */
@@ -122,11 +130,13 @@ int	lite = 0;			/* -L flag */
 long	numops = -1;			/* -N flag */
 int	randomoplen = 1;		/* -O flag disables it */
 int	seed = 1;			/* -S flag */
-int     mapped_writes = 1;              /* -W flag disables */
-int 	mapped_reads = 1;		/* -R flag disables it */
+int     mapped_writes = 1;		/* -W flag disables */
+int	mapped_reads = 1;		/* -R flag disables it */
+int	prealloc = 0;			/* -x [0|1|2] run with prealloc */
+int	o_direct = 0;			/* -Z flag */
 int	fsxgoodfd = 0;
-FILE *	fsxlogf = NULL;
-int badoff = -1;
+FILE	*fsxlogf = NULL;
+int	badoff = -1;
 
 
 void
@@ -153,6 +163,13 @@ warn(const char * fmt, ...)
 	va_end(ap);
 }
 
+static void *round_up(void *ptr, unsigned long align)
+{
+	unsigned long ret = (unsigned long)ptr;
+
+	ret = ((ret + align - 1) & ~(align - 1));
+	return (void *)ret;
+}
 
 void
 __attribute__((format(printf, 1, 2)))
@@ -223,20 +240,22 @@ logdump(void)
 			prt("MAPREAD  0x%x thru 0x%x (0x%x bytes)",
 			    lp->args[0], lp->args[0] + lp->args[1] - 1,
 			    lp->args[1]);
-			if (badoff >= lp->args[0] && badoff <
-						     lp->args[0] + lp->args[1])
+			if (badoff >= lp->args[0] &&
+			    badoff < lp->args[0] + lp->args[1])
 				prt("\t***RRRR***");
 			break;
 		case OP_MAPWRITE:
 			prt("MAPWRITE 0x%x thru 0x%x (0x%x bytes)",
 			    lp->args[0], lp->args[0] + lp->args[1] - 1,
 			    lp->args[1]);
-			if (badoff >= lp->args[0] && badoff <
-						     lp->args[0] + lp->args[1])
+			if (badoff >= lp->args[0] &&
+			    badoff < lp->args[0] + lp->args[1])
 				prt("\t******WWWW");
 			break;
 		case OP_READ:
-			prt("READ     0x%x thru 0x%x (0x%x bytes)",
+		case OP_READ + O_DIRECT:
+			prt("READ%s  0x%x thru 0x%x (0x%x bytes)",
+			    lp->operation & O_DIRECT ? "_OD" : "   ",
 			    lp->args[0], lp->args[0] + lp->args[1] - 1,
 			    lp->args[1]);
 			if (badoff >= lp->args[0] &&
@@ -244,7 +263,9 @@ logdump(void)
 				prt("\t***RRRR***");
 			break;
 		case OP_WRITE:
-			prt("WRITE    0x%x thru 0x%x (0x%x bytes)",
+		case OP_WRITE + O_DIRECT:
+			prt("WRITE%s 0x%x thru 0x%x (0x%x bytes)",
+			    lp->operation & O_DIRECT ? "_OD" : "   ",
 			    lp->args[0], lp->args[0] + lp->args[1] - 1,
 			    lp->args[1]);
 			if (lp->args[0] > lp->args[2])
@@ -264,7 +285,9 @@ logdump(void)
 				prt("\t******WWWW");
 			break;
 		case OP_CLOSEOPEN:
-			prt("CLOSE/OPEN");
+		case OP_CLOSEOPEN + O_DIRECT:
+			prt("CLOSE/OPEN%s",
+			    lp->operation & O_DIRECT ? "_OD" : "   ");
 			break;
 		case OP_SKIPPED:
 			prt("SKIPPED (no operation)");
@@ -392,6 +415,7 @@ check_buffers(unsigned offset, unsigned 
 struct test_file {
 	char *path;
 	int fd;
+	int o_direct;
 } *test_files = NULL;
 
 int num_test_files = 0;
@@ -446,6 +470,33 @@ get_fd(void)
 	return tf->fd;
 }
 
+static const char *my_basename(const char *path)
+{
+	char *c = strrchr(path, '/');
+
+	return c ? c++ : path;
+}
+
+int do_fallocate(int fd, int flags, loff_t offset, loff_t maxlen)
+{
+#ifdef FALLOC_FL_KEEP_SIZE
+	return fallocate(fd, flags, offset, maxlen);
+#else
+#define FALLOC_FL_KEEP_SIZE 0x01
+#ifdef __i386__
+#define __NR_fallocate		324
+	return syscall(__NR_fallocate, fd, flags, offset, maxlen);
+#elif defined (__powerpc__)
+#define __NR_fallocate          309
+	return syscall(__NR_fallocate, fd, flags, offset >> 32,
+		       offset & 0xffffffff, maxlen >> 32, maxlen & 0xffffffff);
+#else  /* !__i386__ && !__powerpc__ */
+	errno = ENOSYS;
+	return -1;
+#endif /* __i386__ */
+#endif /* FALLOC_FL_KEEP_SIZE */
+}
+
 void
 open_test_files(char **argv, int argc)
 {
@@ -463,14 +514,32 @@ open_test_files(char **argv, int argc)
 	}
 
 	for (i = 0, tf = test_files; i < num_test_files; i++, tf++) {
-
 		tf->path = argv[i];
-		tf->fd = open(tf->path, O_RDWR|(lite ? 0 : O_CREAT|O_TRUNC),
+		tf->o_direct = (o_direct && (random() % o_direct == 0)) ?
+			O_DIRECT : 0;
+		tf->fd = open(tf->path, O_RDWR | (lite ? 0 : O_CREAT|O_TRUNC) |
+			                tf->o_direct,
 				0666);
 		if (tf->fd < 0) {
 			prterr(tf->path);
 			exit(91);
 		}
+
+		if (prealloc == 1) {
+			if (do_fallocate(tf->fd, 0, 0, maxfilelen) < 0) {
+				(void)ftruncate(tf->fd, maxfilelen);
+				prt("%s: fallocate(0, %lu): %s\n",
+				    tf->path, maxfilelen, strerror(errno));
+				//exit(89);
+			}
+		} else if (prealloc == 2) {
+			if (do_fallocate(tf->fd, FALLOC_FL_KEEP_SIZE, 0,
+					 maxfilelen) < 0){
+				prt("%s: fallocate(KEEP_SIZE, 0, %lu): %s\n",
+				    tf->path, maxfilelen, strerror(errno));
+				//exit(89);
+			}
+		}
 	}
 
 	if (quiet || fd_policy == FD_SINGLE)
@@ -581,7 +650,7 @@ fill_tf_buf(struct test_file *tf)
 
 void
 output_line(struct test_file *tf, int op, unsigned offset,
-		unsigned size, struct timeval *tv)
+	    unsigned size, struct timeval *tv)
 {
 	char *tf_num = "";
 
@@ -591,8 +660,13 @@ output_line(struct test_file *tf, int op
 		[OP_TRUNCATE] = "trunc from",
 		[OP_MAPREAD] = "mapread",
 		[OP_MAPWRITE] = "mapwrite",
+		[OP_READ + O_DIRECT] = "read_OD",
+		[OP_WRITE + O_DIRECT] = "write_OD",
 	};
 
+	if (fd_policy != FD_SINGLE)
+		tf_num = fill_tf_buf(tf);
+
 	/* W. */
 	if (!(!quiet && ((progressinterval &&
 			testcalls % progressinterval == 0) ||
@@ -602,9 +676,6 @@ output_line(struct test_file *tf, int op
 			  (monitorend == -1 || offset <= monitorend)))))))
 		return;
 
-	if (fd_policy != FD_SINGLE)
-		tf_num = fill_tf_buf(tf);
-
 	prt("%06lu %lu.%06lu %.*s%-10s %#08x %s %#08x\t(0x%x bytes)\n",
 		testcalls, tv->tv_sec, tv->tv_usec, max_tf_len,
 		tf_num, ops[op],
@@ -612,6 +683,19 @@ output_line(struct test_file *tf, int op
 		offset + size - 1, size);
 }
 
+void output_debug(unsigned offset, unsigned size, const char *what)
+{
+	if (!quiet && (debug > 1 &&
+		        (monitorstart == -1 ||
+			 (offset + size >= monitorstart &&
+			  (monitorend == -1 || offset <= monitorend))))) {
+		struct timeval t;
+
+		gettimeofday(&t, NULL);
+		prt("       %lu.%06lu %s\n", t.tv_sec, t.tv_usec, what);
+	}
+}
+
 void
 doread(unsigned offset, unsigned size)
 {
@@ -621,10 +705,15 @@ doread(unsigned offset, unsigned size)
 	struct test_file *tf = get_tf();
 	int fd = tf->fd;
 
-	offset -= offset % readbdy;
+	if (tf->o_direct) {
+		offset -= offset % (readbdy == 1 ? page_size : readbdy);
+		size += page_size - size % (readbdy == 1 ? page_size : readbdy);
+	} else {
+		offset -= offset % readbdy;
+	}
 	gettimeofday(&t, NULL);
 	if (size == 0) {
-		if (!quiet && testcalls > simulatedopcount)
+		if (!quiet && testcalls > simulatedopcount && !tf->o_direct)
 			prt("skipping zero size read\n");
 		log4(OP_SKIPPED, OP_READ, offset, size, &t);
 		return;
@@ -636,12 +725,12 @@ doread(unsigned offset, unsigned size)
 		return;
 	}
 
-	log4(OP_READ, offset, size, 0, &t);
+	log4(OP_READ + tf->o_direct, offset, size, 0, &t);
 
 	if (testcalls <= simulatedopcount)
 		return;
 
-	output_line(tf, OP_READ, offset, size, &t);
+	output_line(tf, OP_READ + tf->o_direct, offset, size, &t);
 
 	ret = lseek(fd, (off_t)offset, SEEK_SET);
 	if (ret == (off_t)-1) {
@@ -649,13 +738,7 @@ doread(unsigned offset, unsigned size)
 		report_failure(140);
 	}
 	iret = read(fd, temp_buf, size);
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu read done\n", t.tv_sec, t.tv_usec);
-	}
+	output_debug(offset, size, "read done");
 	if (iret != size) {
 		if (iret == -1)
 			prterr("doread: read");
@@ -669,6 +752,33 @@ doread(unsigned offset, unsigned size)
 
 
 void
+check_eofpage(char *s, unsigned offset, char *p, int size)
+{
+	long last_page, should_be_zero;
+
+	if (offset + size <= (file_size & ~page_mask))
+		return;
+	/*
+	 * we landed in the last page of the file
+	 * test to make sure the VM system provided 0's
+	 * beyond the true end of the file mapping
+	 * (as required by mmap def in 1996 posix 1003.1)
+	 */
+	last_page = ((long)p + (offset & page_mask) + size) & ~page_mask;
+
+	for (should_be_zero = last_page + (file_size & page_mask);
+	     should_be_zero < last_page + page_size;
+	     should_be_zero++)
+		if (*(char *)should_be_zero) {
+			prt("non-zero mmap past EOF %#llx page @ %#lx is %#x\n",
+			    (long long)file_size -1, should_be_zero & page_mask,
+			    short_at(should_be_zero));
+			report_failure(205);
+		}
+}
+
+
+void
 domapread(unsigned offset, unsigned size)
 {
 	struct timeval t;
@@ -678,6 +788,11 @@ domapread(unsigned offset, unsigned size
 	struct test_file *tf = get_tf();
 	int fd = tf->fd;
 
+	if (tf->o_direct) {
+		doread(offset, size);
+		return;
+	}
+
 	offset -= offset % readbdy;
 	gettimeofday(&t, NULL);
 	if (size == 0) {
@@ -708,32 +823,21 @@ domapread(unsigned offset, unsigned size
 	        prterr("domapread: mmap");
 		report_failure(190);
 	}
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu mmap done\n", t.tv_sec, t.tv_usec);
-	}
-	memcpy(temp_buf, p + pg_offset, size);
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu memcpy done\n", t.tv_sec, t.tv_usec);
+	output_debug(offset, size, "mmap done");
+	if (setjmp(jmpbuf) == 0) {
+		jmpbuf_good = 1;
+		memcpy(temp_buf, p + pg_offset, size);
+		check_eofpage("Read", offset, p, size);
+		jmpbuf_good = 0;
+	} else {
+		report_failure(1901);
 	}
+	output_debug(offset, size, "memcpy done");
 	if (munmap(p, map_size) != 0) {
 		prterr("domapread: munmap");
 		report_failure(191);
 	}
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu munmap done\n", t.tv_sec, t.tv_usec);
-	}
+	output_debug(offset, size, "munmap done");
 
 	check_buffers(offset, size);
 }
@@ -760,16 +864,21 @@ dowrite(unsigned offset, unsigned size)
 	struct test_file *tf = get_tf();
 	int fd = tf->fd;
 
-	offset -= offset % writebdy;
+	if (tf->o_direct) {
+		offset -= offset % (writebdy == 1 ? page_size : writebdy);
+		size += page_size - (size % (writebdy == 1 ? page_size : writebdy));
+	} else {
+		offset -= offset % writebdy;
+	}
 	gettimeofday(&t, NULL);
 	if (size == 0) {
-		if (!quiet && testcalls > simulatedopcount)
+		if (!quiet && testcalls > simulatedopcount && !tf->o_direct)
 			prt("skipping zero size write\n");
 		log4(OP_SKIPPED, OP_WRITE, offset, size, &t);
 		return;
 	}
 
-	log4(OP_WRITE, offset, size, file_size, &t);
+	log4(OP_WRITE + tf->o_direct, offset, size, file_size, &t);
 
 	gendata(original_buf, good_buf, offset, size);
 	if (file_size < offset + size) {
@@ -785,7 +894,7 @@ dowrite(unsigned offset, unsigned size)
 	if (testcalls <= simulatedopcount)
 		return;
 
-	output_line(tf, OP_WRITE, offset, size, &t);
+	output_line(tf, OP_WRITE + tf->o_direct, offset, size, &t);
 
 	ret = lseek(fd, (off_t)offset, SEEK_SET);
 	if (ret == (off_t)-1) {
@@ -793,13 +902,7 @@ dowrite(unsigned offset, unsigned size)
 		report_failure(150);
 	}
 	iret = write(fd, good_buf + offset, size);
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu write done\n", t.tv_sec, t.tv_usec);
-	}
+	output_debug(offset, size, "write done");
 	if (iret != size) {
 		if (iret == -1)
 			prterr("dowrite: write");
@@ -808,6 +911,13 @@ dowrite(unsigned offset, unsigned size)
 			    iret, size);
 		report_failure(151);
 	}
+	if (do_fsync) {
+		if (fsync(fd)) {
+			prt("fsync() failed: %s\n", strerror(errno));
+			report_failure(152);
+		}
+		output_debug(offset, size, "fsync done");
+	}
 }
 
 
@@ -822,6 +932,11 @@ domapwrite(unsigned offset, unsigned siz
 	struct test_file *tf = get_tf();
 	int fd = tf->fd;
 
+	if (tf->o_direct) {
+		dowrite(offset, size);
+		return;
+	}
+
 	offset -= offset % writebdy;
 	gettimeofday(&t, NULL);
 	if (size == 0) {
@@ -855,13 +970,7 @@ domapwrite(unsigned offset, unsigned siz
 		        prterr("domapwrite: ftruncate");
 			exit(201);
 		}
-		if (!quiet && (debug > 1 &&
-			       (monitorstart == -1 ||
-				(offset + size > monitorstart &&
-				 (monitorend == -1 || offset <= monitorend))))) {
-			gettimeofday(&t, NULL);
-			prt("       %lu.%06lu truncate done\n", t.tv_sec, t.tv_usec);
-	}
+		output_debug(offset, size, "truncate done");
 	}
 	pg_offset = offset & page_mask;
 	map_size  = pg_offset + size;
@@ -871,43 +980,31 @@ domapwrite(unsigned offset, unsigned siz
 	        prterr("domapwrite: mmap");
 		report_failure(202);
 	}
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu mmap done\n", t.tv_sec, t.tv_usec);
-	}
-	memcpy(p + pg_offset, good_buf + offset, size);
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu memcpy done\n", t.tv_sec, t.tv_usec);
+	output_debug(offset, map_size, "mmap done");
+	if (setjmp(jmpbuf) == 0) {
+		jmpbuf_good = 1;
+		memcpy(p + pg_offset, good_buf + offset, size);
+		if (msync(p, map_size, 0) != 0) {
+			prterr("domapwrite: msync");
+			report_failure(203);
+		}
+		check_eofpage("Write", offset, p, size);
+		jmpbuf_good = 0;
+	} else {
+		report_failure(2021);
 	}
+
+	output_debug(offset, size, "memcpy done");
 	if (msync(p, map_size, 0) != 0) {
 		prterr("domapwrite: msync");
 		report_failure(203);
 	}
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu msync done\n", t.tv_sec, t.tv_usec);
-	}
+	output_debug(offset, map_size, "msync done");
 	if (munmap(p, map_size) != 0) {
 		prterr("domapwrite: munmap");
 		report_failure(204);
 	}
-	if (!quiet && (debug > 1 &&
-		        (monitorstart == -1 ||
-			 (offset + size > monitorstart &&
-			  (monitorend == -1 || offset <= monitorend))))) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu munmap done\n", t.tv_sec, t.tv_usec);
-	}
+	output_debug(offset, map_size, "munmap done");
 }
 
 
@@ -943,10 +1040,7 @@ dotruncate(unsigned size)
 		prterr("dotruncate: ftruncate");
 		report_failure(160);
 	}
-	if (!quiet && debug > 1) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu trunc done\n", t.tv_sec, t.tv_usec);
-	}
+	output_debug(size, 0, "truncate done");
 }
 
 
@@ -983,33 +1077,36 @@ docloseopen(void)
 {
 	struct timeval t;
 	struct test_file *tf = get_tf();
+	int direct = (o_direct && (random() % o_direct == 0)) ? O_DIRECT : 0;
+	char *tf_num = "";
 
 	if (testcalls <= simulatedopcount)
 		return;
 
 	gettimeofday(&t, NULL);
-	log4(OP_CLOSEOPEN, file_size, (unsigned)file_size, 0, &t);
+	log4(OP_CLOSEOPEN + direct, file_size, (unsigned)file_size, 0, &t);
+
+	if (fd_policy != FD_SINGLE)
+		tf_num = fill_tf_buf(tf);
 
 	if (debug)
-		prt("%06lu %lu.%06lu close/open\n", testcalls, t.tv_sec,
-		    t.tv_usec);
+		prt("%06lu %lu.%06lu %sclose/open%s\n", testcalls, t.tv_sec,
+		    t.tv_usec, tf_num, direct ? "(O_DIRECT)" : "");
 	if (close(tf->fd)) {
-		prterr("docloseopen: close");
+		prterr(tf->o_direct ?
+		       "docloseopen: close(O_DIRECT)" : "docloseopen: close");
 		report_failure(180);
 	}
-	if (!quiet && debug > 1) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu close done\n", t.tv_sec, t.tv_usec);
-	}
-	tf->fd = open(tf->path, O_RDWR, 0);
+	output_debug(monitorstart, 0, "close done");
+	tf->o_direct = direct;
+	tf->fd = open(tf->path, O_RDWR | tf->o_direct, 0);
 	if (tf->fd < 0) {
-		prterr("docloseopen: open");
+		prterr(tf->o_direct ?
+		       "docloseopen: open(O_DIRECT)" : "docloseopen: open");
 		report_failure(181);
 	}
-	if (!quiet && debug > 1) {
-		gettimeofday(&t, NULL);
-		prt("       %lu.%06lu open done\n", t.tv_sec, t.tv_usec);
-	}
+	output_debug(monitorstart, 0,
+		     tf->o_direct ? "open done" : "open(O_DIRECT) done");
 }
 
 
@@ -1081,6 +1178,15 @@ test(void)
 		docloseopen();
 }
 
+void
+segv(int sig)
+{
+	if (jmpbuf_good) {
+	    jmpbuf_good = 0;
+	    longjmp(jmpbuf, 1);
+	}
+	report_failure(9999);
+}
 
 void
 cleanup(sig)
@@ -1096,36 +1202,57 @@ cleanup(sig)
 void
 usage(void)
 {
-	fprintf(stdout, "usage: %s",
-		"fsx [-dnqLOW] [-b opnum] [-c Prob] [-l flen] [-m "
-"start:end] [-o oplen] [-p progressinterval] [-r readbdy] [-s style] [-t "
-"truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath] [-S seed] "
-"[ -I random|rotate ] fname [additional paths to fname..]\n"
+	fprintf(stdout, "usage: fsx [-dfnqLOW] [-b opnum] [-c Prob] [-l flen]\n"
+"\t\t[-m start:end] [-o oplen] [-p progressinterval] [-r readbdy] [-s style]\n"
+"\t\t[-t truncbdy] [-w writebdy] [-D startingop] [-N numops] [-P dirpath]\n"
+"\t\t[-S seed] [-Z [prob]] [ -I random|rotate ] fname [more paths to fname..]\n"
 "	-b opnum: beginning operation number (default 1)\n"
 "	-c P: 1 in P chance of file close+open at each op (default infinity)\n"
 "	-d: debug output for all operations [-d -d = more debugging]\n"
+/* OSX: -d duration: number of hours for the tool to run\n" */
+/* OSX: -e: tests using an extended attribute rather than a file\n" */
+"	-f: fsync after every write operation\n"
+/* OSX: -f forkname: test the named fork of fname\n" */
+/* OSX: -g logpath: path for .fsxlog file\n" */
+/* OSX: -h: write 0s instead of creating holes (i.e. sparse file)\n" */
+/* OSX: -i: interactive mode, hit return before performing each operation\n" */
 "	-l flen: the upper bound on file size (default 262144)\n"
-"	-m start:end: monitor (print debug) specified byte range (default 0:infinity)\n"
+/* OSX: -l logpath: path for XILog file\n" */
+"	-m startop:endop: monitor (print debug output) specified byte rang"
+"(default 0:infinity)\n"
 "	-n: no verifications of file size\n"
 "	-o oplen: the upper bound on operation size (default 65536)\n"
 "	-p progressinterval: debug output at specified operation interval\n"
 "	-q: quieter operation\n"
-"	-r readbdy: 4096 would make reads page aligned (default 1)\n"
+"	-r readbdy: %u would make reads page aligned (default 1)\n"
 "	-s style: 1 gives smaller truncates (default 0)\n"
-"	-t truncbdy: 4096 would make truncates page aligned (default 1)\n"
-"	-w writebdy: 4096 would make writes page aligned (default 1)\n"
+"	-t truncbdy: %u would make truncates page aligned (default 1)\n"
+/* OSX: -v: debug output for all operations\n" */
+"	-w writebdy: %u would make writes page aligned (default 1)\n"
+"	-x[1|2]: preallocate file space (2 does no size update)\n"
+/* OSX: -x: write output in XML (XILOG)\n" */
+/* OSX: -y: call fsync before closing the file\n" */
+/* AKPM:-A: Use the AIO system calls\n" */
+/* OSX: -C mix cached and un-cached read/write ops\n" */
 "	-D startingop: debug output starting at specified operation\n"
+/* OSX: -F flen: the upper bound on file size (default 262144)\n" */
+/* OSX: -G logsize: #entries in oplog (default 1024)\n" */
+"	-I {rotate|random}: When multiple paths to the file are given,\n"
+"	    each operation uses a different path.  Iterate through them in\n"
+"	    order with 'rotate' or chose then at 'random'.  (defaults random)\n"
+/* OSX: -I: start interactive mode since operation opnum\n" */
 "	-L: fsxLite - no file creations & no file size changes\n"
+/* OSX: -M: slow motion mode, wait 1 second before each op\n" */
 "	-N numops: total # operations to do (default infinity)\n"
 "	-O: use oplen (see -o flag) for every op (default random)\n"
 "	-P: save .fsxlog and .fsxgood files in dirpath (default ./)\n"
+"	-R: read() system calls only (mapped reads disabled)\n"
 "	-S seed: for random # generator (default 1) 0 gets timestamp\n"
+/* OSX: -T datasize: size of atomic data element writes [1,2,4] (default 4)\n" */
 "	-W: mapped write operations DISabled\n"
-"	-R: read() system calls only (mapped reads disabled)\n"
-"	-I: When multiple paths to the file are given each operation uses\n"
-"	    a different path.  Iterate through them in order with 'rotate'\n"
-"	    or chose then at 'random'.  (defaults to random)\n"
-"	fname: this filename is REQUIRED (no default)\n");
+"	-Z[P]: O_DIRECT file IO [1 in P chance for each open] (default off)\n"
+"	fname: this filename is REQUIRED (no default)\n",
+	page_size, page_size, page_size);
 	exit(90);
 }
 
@@ -1167,6 +1294,7 @@ int
 main(int argc, char **argv)
 {
 	int	i, style, ch;
+	char    *orig_good_buf, *orig_temp_buf;
 	char	*endp;
 	int  dirpath = 0;
 
@@ -1179,14 +1307,13 @@ main(int argc, char **argv)
 	setvbuf(stdout, (char *)0, _IOLBF, 0); /* line buffered stdout */
 
 	while ((ch = getopt(argc, argv,
-				"b:c:dl:m:no:p:qr:s:t:w:D:I:LN:OP:RS:W"))
+			    "b:c:dfl:m:no:p:qr:s:t:w:x::D:I:LN:OP:RS:WZ::"))
 	       != EOF)
 		switch (ch) {
 		case 'b':
 			simulatedopcount = getnum(optarg, &endp);
 			if (!quiet)
-				fprintf(stdout, "Will begin at operation"
-					"%ld\n",
+				fprintf(stdout, "Will begin at operation %ld\n",
 					simulatedopcount);
 			if (simulatedopcount == 0)
 				usage();
@@ -1204,6 +1331,9 @@ main(int argc, char **argv)
 		case 'd':
 			debug++;
 			break;
+		case 'f':
+			do_fsync = 1;
+			break;
 		case 'l':
 			maxfilelen = getnum(optarg, &endp);
 			if (maxfilelen <= 0)
@@ -1257,6 +1387,10 @@ main(int argc, char **argv)
 			if (writebdy <= 0)
 				usage();
 			break;
+		case 'x':
+			if (optarg == NULL || (prealloc = getnum(optarg, &endp)) <= 0)
+				prealloc = 1;
+			break;
 		case 'D':
 			debugstart = getnum(optarg, &endp);
 			if (debugstart < 1)
@@ -1300,7 +1434,10 @@ main(int argc, char **argv)
 			if (!quiet)
 				fprintf(stdout, "mapped writes DISABLED\n");
 			break;
-
+		case 'Z':
+			if (optarg == NULL || (o_direct = getnum(optarg, &endp)) == 0)
+				o_direct = 1;
+			break;
 		default:
 			usage();
 			/* NOTREACHED */
@@ -1321,20 +1458,21 @@ main(int argc, char **argv)
 	signal(SIGVTALRM,	cleanup);
 	signal(SIGUSR1,	cleanup);
 	signal(SIGUSR2,	cleanup);
+	signal(SIGSEGV,	segv);
 
 	initstate(seed, state, 256);
 	setstate(state);
 
 	open_test_files(argv, argc);
 
-	strncat(goodfile, dirpath ? basename(fname) : fname, 256);
+	strncat(goodfile, dirpath ? my_basename(fname) : fname, 256);
 	strcat (goodfile, ".fsxgood");
 	fsxgoodfd = open(goodfile, O_RDWR|O_CREAT|O_TRUNC, 0666);
 	if (fsxgoodfd < 0) {
 		prterr(goodfile);
 		exit(92);
 	}
-	strncat(logfile, dirpath ? basename(fname) : fname, 256);
+	strncat(logfile, dirpath ? my_basename(fname) : fname, 256);
 	strcat (logfile, ".fsxlog");
 	fsxlogf = fopen(logfile, "w");
 	if (fsxlogf == NULL) {
@@ -1363,14 +1501,16 @@ main(int argc, char **argv)
 	for (i = 0; i < maxfilelen; i++)
 		original_buf[i] = random() % 256;
 
-	good_buf = (char *) malloc(maxfilelen);
-	if (good_buf == NULL)
+	orig_good_buf = malloc(maxfilelen + page_size);
+	if (orig_good_buf == NULL)
 		exit(97);
+	good_buf = round_up(orig_good_buf, page_size);
 	memset(good_buf, '\0', maxfilelen);
 
-	temp_buf = (char *) malloc(maxoplen);
-	if (temp_buf == NULL)
+	orig_temp_buf = malloc(maxoplen + page_size);
+	if (orig_temp_buf == NULL)
 		exit(99);
+	temp_buf = round_up(orig_temp_buf, page_size);
 	memset(temp_buf, '\0', maxoplen);
 
 	if (lite) {	/* zero entire existing file */
@@ -1388,8 +1528,9 @@ main(int argc, char **argv)
 				     (unsigned)written, maxfilelen);
 			exit(98);
 		}
-	} else
+	} else {
 		check_trunc_hack();
+	}
 
 	while (numops == -1 || numops--)
 		test();
@@ -1401,10 +1542,8 @@ main(int argc, char **argv)
 		free(tf_buf);
 
 	free(original_buf);
-	free(good_buf);
-	free(temp_buf);
+	free(orig_good_buf);
+	free(orig_temp_buf);
 
 	return 0;
 }
-
- 	  

---
Regards--
Subrata

> Cheers, Andreas
> --
> Andreas Dilger
> Sr. Staff Engineer, Lustre Group
> Sun Microsystems of Canada, Inc.
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ