public inbox for fstests@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] fsstress: new writev and readv operations test
@ 2017-07-18 14:37 Zorro Lang
  2017-07-18 14:37 ` [PATCH v2 2/3] fsstress: add AIO read/write and fsync test Zorro Lang
  2017-07-18 14:37 ` [PATCH v2 3/3] xfs/068: update golden output due to new operations in fsstress Zorro Lang
  0 siblings, 2 replies; 3+ messages in thread
From: Zorro Lang @ 2017-07-18 14:37 UTC (permalink / raw)
  To: fstests

We found some bugs by writev operations recently, writev can cover
different test than normal write operation, so add writev and
readv operations into fsstress.

Signed-off-by: Zorro Lang <zlang@redhat.com>
---

V2 patchset did below things:
1) changed writev_f and readv_f, write/read exact len bytes once,
   not random len and offset for writev/readv.
2) don't check errno after call io_setup/io_destroy
3) drop that randomly memset patch.
4) modify the garden image of xfs/068.out

Thanks,
Zorro

 ltp/fsstress.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 163 insertions(+)

diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index e9fd2769..0ecc214c 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -18,6 +18,7 @@
 
 #include <linux/fs.h>
 #include <setjmp.h>
+#include <sys/uio.h>
 #include "global.h"
 
 #ifdef HAVE_ATTR_XATTR_H
@@ -47,6 +48,9 @@
 #define XFS_ERRTAG_MAX		17
 #define XFS_IDMODULO_MAX	31	/* user/group IDs (1 << x)  */
 #define XFS_PROJIDMODULO_MAX	16	/* project IDs (1 << x)     */
+#ifndef IOV_MAX
+#define IOV_MAX 1024
+#endif
 
 #define FILELEN_MAX		(32*4096)
 
@@ -78,6 +82,7 @@ typedef enum {
 	OP_INSERT,
 	OP_READ,
 	OP_READLINK,
+	OP_READV,
 	OP_RENAME,
 	OP_RESVSP,
 	OP_RMDIR,
@@ -90,6 +95,7 @@ typedef enum {
 	OP_UNLINK,
 	OP_UNRESVSP,
 	OP_WRITE,
+	OP_WRITEV,
 	OP_LAST
 } opty_t;
 
@@ -179,6 +185,7 @@ void	collapse_f(int, long);
 void	insert_f(int, long);
 void	read_f(int, long);
 void	readlink_f(int, long);
+void	readv_f(int, long);
 void	rename_f(int, long);
 void	resvsp_f(int, long);
 void	rmdir_f(int, long);
@@ -191,6 +198,7 @@ void	truncate_f(int, long);
 void	unlink_f(int, long);
 void	unresvsp_f(int, long);
 void	write_f(int, long);
+void	writev_f(int, long);
 
 opdesc_t	ops[] = {
      /* { OP_ENUM, "name", function, freq, iswrite }, */
@@ -221,6 +229,7 @@ opdesc_t	ops[] = {
 	{ OP_INSERT, "insert", insert_f, 1, 1 },
 	{ OP_READ, "read", read_f, 1, 0 },
 	{ OP_READLINK, "readlink", readlink_f, 1, 0 },
+	{ OP_READV, "readv", readv_f, 1, 0 },
 	{ OP_RENAME, "rename", rename_f, 2, 1 },
 	{ OP_RESVSP, "resvsp", resvsp_f, 1, 1 },
 	{ OP_RMDIR, "rmdir", rmdir_f, 1, 1 },
@@ -233,6 +242,7 @@ opdesc_t	ops[] = {
 	{ OP_UNLINK, "unlink", unlink_f, 1, 1 },
 	{ OP_UNRESVSP, "unresvsp", unresvsp_f, 1, 1 },
 	{ OP_WRITE, "write", write_f, 4, 1 },
+	{ OP_WRITEV, "writev", writev_f, 4, 1 },
 }, *ops_end;
 
 flist_t	flist[FT_nft] = {
@@ -2948,6 +2958,85 @@ readlink_f(int opno, long r)
 }
 
 void
+readv_f(int opno, long r)
+{
+	char		*buf;
+	int		e;
+	pathname_t	f;
+	int		fd;
+	size_t		len;
+	__int64_t	lr;
+	off64_t		off;
+	struct stat64	stb;
+	int		v;
+	char		st[1024];
+	struct iovec	*iov = NULL;
+	int		iovcnt;
+	size_t		iovb;
+	size_t		iovl;
+	int		i;
+
+	init_pathname(&f);
+	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+		if (v)
+			printf("%d/%d: readv - no filename\n", procid, opno);
+		free_pathname(&f);
+		return;
+	}
+	fd = open_path(&f, O_RDONLY);
+	e = fd < 0 ? errno : 0;
+	check_cwd();
+	if (fd < 0) {
+		if (v)
+			printf("%d/%d: readv - open %s failed %d\n",
+				procid, opno, f.path, e);
+		free_pathname(&f);
+		return;
+	}
+	if (fstat64(fd, &stb) < 0) {
+		if (v)
+			printf("%d/%d: readv - fstat64 %s failed %d\n",
+				procid, opno, f.path, errno);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+	inode_info(st, sizeof(st), &stb, v);
+	if (stb.st_size == 0) {
+		if (v)
+			printf("%d/%d: readv - %s%s zero size\n", procid, opno,
+			       f.path, st);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+	lr = ((__int64_t)random() << 32) + random();
+	off = (off64_t)(lr % stb.st_size);
+	lseek64(fd, off, SEEK_SET);
+	len = (random() % FILELEN_MAX) + 1;
+	buf = malloc(len);
+
+	iovcnt = (random() % MIN(len, IOV_MAX)) + 1;
+	iov = calloc(iovcnt, sizeof(struct iovec));
+	iovl = len / iovcnt;
+	iovb = 0;
+	for (i=0; i<iovcnt; i++) {
+		(iov + i)->iov_base = (buf + iovb);
+		(iov + i)->iov_len  = iovl;
+		iovb += iovl;
+	}
+
+	e = readv(fd, iov, iovcnt) < 0 ? errno : 0;
+	free(buf);
+	if (v)
+		printf("%d/%d: readv %s%s [%lld,%d,%d] %d\n",
+		       procid, opno, f.path, st, (long long)off, (int)iovl,
+		       iovcnt, e);
+	free_pathname(&f);
+	close(fd);
+}
+
+void
 rename_f(int opno, long r)
 {
 	fent_t		*dfep;
@@ -3379,3 +3468,77 @@ write_f(int opno, long r)
 	free_pathname(&f);
 	close(fd);
 }
+
+void
+writev_f(int opno, long r)
+{
+	char		*buf;
+	int		e;
+	pathname_t	f;
+	int		fd;
+	size_t		len;
+	__int64_t	lr;
+	off64_t		off;
+	struct stat64	stb;
+	int		v;
+	char		st[1024];
+	struct iovec	*iov = NULL;
+	int		iovcnt;
+	size_t		iovb;
+	size_t		iovl;
+	int		i;
+
+	init_pathname(&f);
+	if (!get_fname(FT_REGm, r, &f, NULL, NULL, &v)) {
+		if (v)
+			printf("%d/%d: writev - no filename\n", procid, opno);
+		free_pathname(&f);
+		return;
+	}
+	fd = open_path(&f, O_WRONLY);
+	e = fd < 0 ? errno : 0;
+	check_cwd();
+	if (fd < 0) {
+		if (v)
+			printf("%d/%d: writev - open %s failed %d\n",
+				procid, opno, f.path, e);
+		free_pathname(&f);
+		return;
+	}
+	if (fstat64(fd, &stb) < 0) {
+		if (v)
+			printf("%d/%d: writev - fstat64 %s failed %d\n",
+				procid, opno, f.path, errno);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+	inode_info(st, sizeof(st), &stb, v);
+	lr = ((__int64_t)random() << 32) + random();
+	off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+	off %= maxfsize;
+	lseek64(fd, off, SEEK_SET);
+	len = (random() % FILELEN_MAX) + 1;
+	buf = malloc(len);
+	memset(buf, nameseq & 0xff, len);
+
+	iovcnt = (random() % MIN(len, IOV_MAX)) + 1;
+	iov = calloc(iovcnt, sizeof(struct iovec));
+	iovl = len / iovcnt;
+	iovb = 0;
+	for (i=0; i<iovcnt; i++) {
+		(iov + i)->iov_base = (buf + iovb);
+		(iov + i)->iov_len  = iovl;
+		iovb += iovl;
+	}
+
+	e = writev(fd, iov, iovcnt) < 0 ? errno : 0;
+	free(buf);
+	free(iov);
+	if (v)
+		printf("%d/%d: writev %s%s [%lld,%d,%d] %d\n",
+		       procid, opno, f.path, st, (long long)off, (int)iovl,
+		       iovcnt, e);
+	free_pathname(&f);
+	close(fd);
+}
-- 
2.13.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v2 2/3] fsstress: add AIO read/write and fsync test
  2017-07-18 14:37 [PATCH v2 1/3] fsstress: new writev and readv operations test Zorro Lang
@ 2017-07-18 14:37 ` Zorro Lang
  2017-07-18 14:37 ` [PATCH v2 3/3] xfs/068: update golden output due to new operations in fsstress Zorro Lang
  1 sibling, 0 replies; 3+ messages in thread
From: Zorro Lang @ 2017-07-18 14:37 UTC (permalink / raw)
  To: fstests

We found some bugs by aio read/write test, but there's not related
operations in fsstress. So add AIO test into fsstress to increase
AIO stress test.

Due to most kernels don't support aio fsync, so set its test
frequency to zero as default.

Signed-off-by: Zorro Lang <zlang@redhat.com>
---
 ltp/fsstress.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 214 insertions(+)

diff --git a/ltp/fsstress.c b/ltp/fsstress.c
index 0ecc214c..7ae7fdf2 100644
--- a/ltp/fsstress.c
+++ b/ltp/fsstress.c
@@ -36,6 +36,10 @@
 #ifdef HAVE_SYS_PRCTL_H
 #include <sys/prctl.h>
 #endif
+#ifdef AIO
+#include <libaio.h>
+io_context_t	io_ctx;
+#endif
 
 #ifndef FS_IOC_GETFLAGS
 #define FS_IOC_GETFLAGS                 _IOR('f', 1, long)
@@ -55,9 +59,12 @@
 #define FILELEN_MAX		(32*4096)
 
 typedef enum {
+	OP_AFSYNC,
 	OP_ALLOCSP,
+	OP_AREAD,
 	OP_ATTR_REMOVE,
 	OP_ATTR_SET,
+	OP_AWRITE,
 	OP_BULKSTAT,
 	OP_BULKSTAT1,
 	OP_CHOWN,
@@ -158,9 +165,12 @@ struct print_string {
 #define	MAXFSIZE	((1ULL << 63) - 1ULL)
 #define	MAXFSIZE32	((1ULL << 40) - 1ULL)
 
+void	afsync_f(int, long);
 void	allocsp_f(int, long);
+void	aread_f(int, long);
 void	attr_remove_f(int, long);
 void	attr_set_f(int, long);
+void	awrite_f(int, long);
 void	bulkstat_f(int, long);
 void	bulkstat1_f(int, long);
 void	chown_f(int, long);
@@ -202,9 +212,12 @@ void	writev_f(int, long);
 
 opdesc_t	ops[] = {
      /* { OP_ENUM, "name", function, freq, iswrite }, */
+	{ OP_AFSYNC, "afsync", afsync_f, 0, 1 },
 	{ OP_ALLOCSP, "allocsp", allocsp_f, 1, 1 },
+	{ OP_AREAD, "aread", aread_f, 1, 0 },
 	{ OP_ATTR_REMOVE, "attr_remove", attr_remove_f, /* 1 */ 0, 1 },
 	{ OP_ATTR_SET, "attr_set", attr_set_f, /* 2 */ 0, 1 },
+	{ OP_AWRITE, "awrite", awrite_f, 1, 1 },
 	{ OP_BULKSTAT, "bulkstat", bulkstat_f, 1, 0 },
 	{ OP_BULKSTAT1, "bulkstat1", bulkstat1_f, 1, 0 },
 	{ OP_CHOWN, "chown", chown_f, 3, 1 },
@@ -587,8 +600,20 @@ int main(int argc, char **argv)
 				}
 			}
 			procid = i;
+#ifdef AIO
+			if (io_setup(128, &io_ctx) != 0) {
+				fprintf(stderr, "io_setup failed");
+				exit(1);
+			}
+#endif
 			for (i = 0; !loops || (i < loops); i++)
 				doproc();
+#ifdef AIO
+			if(io_destroy(io_ctx) != 0) {
+				fprintf(stderr, "io_destroy failed");
+				return 1;
+			}
+#endif
 			return 0;
 		}
 	}
@@ -1708,6 +1733,62 @@ void inode_info(char *str, size_t sz, struct stat64 *s, int verbose)
 }
 
 void
+afsync_f(int opno, long r)
+{
+#ifdef AIO
+	int		e;
+	pathname_t	f;
+	int		fd;
+	int		v;
+	struct iocb	iocb;
+	struct iocb	*iocbs[] = { &iocb };
+	struct io_event	event;
+
+	init_pathname(&f);
+	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+		if (v)
+			printf("%d/%d: afsync - no filename\n", procid, opno);
+		free_pathname(&f);
+		return;
+	}
+	fd = open_path(&f, O_WRONLY | O_DIRECT);
+	e = fd < 0 ? errno : 0;
+	check_cwd();
+	if (fd < 0) {
+		if (v)
+			printf("%d/%d: afsync - open %s failed %d\n",
+			       procid, opno, f.path, e);
+		free_pathname(&f);
+		return;
+	}
+
+	io_prep_fsync(&iocb, fd);
+	if ((e = io_submit(io_ctx, 1, iocbs)) != 1) {
+		if (v)
+			printf("%d/%d: afsync - io_submit %s %d\n",
+			       procid, opno, f.path, e);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+	if ((e = io_getevents(io_ctx, 1, 1, &event, NULL)) != 1) {
+		if (v)
+			printf("%d/%d: afsync - io_getevents failed %d\n",
+			       procid, opno, e);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+
+	e = event.res2;
+	if (v)
+		printf("%d/%d: afsync %s %d\n", procid, opno, f.path, e);
+	free_pathname(&f);
+	close(fd);
+#endif
+}
+
+void
 allocsp_f(int opno, long r)
 {
 	int		e;
@@ -1761,6 +1842,131 @@ allocsp_f(int opno, long r)
 	close(fd);
 }
 
+#ifdef AIO
+void
+do_aio_rw(int opno, long r, int flags)
+{
+	__int64_t	align;
+	char		*buf;
+	struct dioattr	diob;
+	int		e;
+	pathname_t	f;
+	int		fd;
+	size_t		len;
+	__int64_t	lr;
+	off64_t		off;
+	struct stat64	stb;
+	int		v;
+	char		st[1024];
+	char		*dio_env;
+	struct iocb	iocb;
+	struct io_event	event;
+	struct iocb	*iocbs[] = { &iocb };
+	int		iswrite = (flags & (O_WRONLY | O_RDWR)) ? 1 : 0;
+
+	init_pathname(&f);
+	if (!get_fname(FT_REGFILE, r, &f, NULL, NULL, &v)) {
+		if (v)
+			printf("%d/%d: do_aio_rw - no filename\n", procid, opno);
+		free_pathname(&f);
+		return;
+	}
+	fd = open_path(&f, flags|O_DIRECT);
+	e = fd < 0 ? errno : 0;
+	check_cwd();
+	if (fd < 0) {
+		if (v)
+			printf("%d/%d: do_aio_rw - open %s failed %d\n",
+			       procid, opno, f.path, e);
+		free_pathname(&f);
+		return;
+	}
+	if (fstat64(fd, &stb) < 0) {
+		if (v)
+			printf("%d/%d: do_aio_rw - fstat64 %s failed %d\n",
+			       procid, opno, f.path, errno);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+	inode_info(st, sizeof(st), &stb, v);
+	if (!iswrite && stb.st_size == 0) {
+		if (v)
+			printf("%d/%d: do_aio_rw - %s%s zero size\n", procid, opno,
+			       f.path, st);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+	if (xfsctl(f.path, fd, XFS_IOC_DIOINFO, &diob) < 0) {
+		if (v)
+			printf(
+			"%d/%d: do_aio_rw - xfsctl(XFS_IOC_DIOINFO) %s%s failed %d\n",
+				procid, opno, f.path, st, errno);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+	dio_env = getenv("XFS_DIO_MIN");
+	if (dio_env)
+		diob.d_mem = diob.d_miniosz = atoi(dio_env);
+	align = (__int64_t)diob.d_miniosz;
+	lr = ((__int64_t)random() << 32) + random();
+	len = (random() % FILELEN_MAX) + 1;
+	len -= (len % align);
+	if (len <= 0)
+		len = align;
+	else if (len > diob.d_maxiosz)
+		len = diob.d_maxiosz;
+	buf = memalign(diob.d_mem, len);
+
+	if (iswrite) {
+		off = (off64_t)(lr % MIN(stb.st_size + (1024 * 1024), MAXFSIZE));
+		off -= (off % align);
+		off %= maxfsize;
+		memset(buf, nameseq & 0xff, len);
+		io_prep_pwrite(&iocb, fd, buf, len, off);
+	} else {
+		off = (off64_t)(lr % stb.st_size);
+		off -= (off % align);
+		io_prep_pread(&iocb, fd, buf, len, off);
+	}
+	if ((e = io_submit(io_ctx, 1, iocbs)) != 1) {
+		if (v)
+			printf("%d/%d: %s - io_submit failed %d\n",
+			       procid, opno, iswrite ? "awrite" : "aread", e);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+	if ((e = io_getevents(io_ctx, 1, 1, &event, NULL)) != 1) {
+		if (v)
+			printf("%d/%d: %s - io_getevents failed %d\n",
+			       procid, opno, iswrite ? "awrite" : "aread", e);
+		free_pathname(&f);
+		close(fd);
+		return;
+	}
+
+	e = event.res != len ? event.res2 : 0;
+	free(buf);
+	if (v)
+		printf("%d/%d: %s %s%s [%lld,%d] %d\n",
+		       procid, opno, iswrite ? "awrite" : "aread",
+		       f.path, st, (long long)off, (int)len, e);
+	free_pathname(&f);
+	close(fd);
+}
+#endif
+
+void
+aread_f(int opno, long r)
+{
+#ifdef AIO
+	do_aio_rw(opno, r, O_RDONLY);
+#endif
+}
+
 void
 attr_remove_f(int opno, long r)
 {
@@ -1865,6 +2071,14 @@ attr_set_f(int opno, long r)
 }
 
 void
+awrite_f(int opno, long r)
+{
+#ifdef AIO
+	do_aio_rw(opno, r, O_WRONLY);
+#endif
+}
+
+void
 bulkstat_f(int opno, long r)
 {
 	int		count;
-- 
2.13.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH v2 3/3] xfs/068: update golden output due to new operations in fsstress
  2017-07-18 14:37 [PATCH v2 1/3] fsstress: new writev and readv operations test Zorro Lang
  2017-07-18 14:37 ` [PATCH v2 2/3] fsstress: add AIO read/write and fsync test Zorro Lang
@ 2017-07-18 14:37 ` Zorro Lang
  1 sibling, 0 replies; 3+ messages in thread
From: Zorro Lang @ 2017-07-18 14:37 UTC (permalink / raw)
  To: fstests

I added some new operatoins to fsstress, and it changed the total
number of test operstions.

xfs/068 use a fixed seed (-s) and number of operations (-n) to run
fsstress, to get fixed number of files and directories. Due to my
patches break these fixed things, so update its expected result
in golden image.

Signed-off-by: Zorro Lang <zlang@redhat.com>
---
 tests/xfs/068.out | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/xfs/068.out b/tests/xfs/068.out
index b20604f7..fa3a5523 100644
--- a/tests/xfs/068.out
+++ b/tests/xfs/068.out
@@ -22,7 +22,7 @@ xfsrestore: session id: ID
 xfsrestore: media ID: ID
 xfsrestore: searching media for directory dump
 xfsrestore: reading directories
-xfsrestore: 474 directories and 1592 entries processed
+xfsrestore: 383 directories and 1335 entries processed
 xfsrestore: directory post-processing
 xfsrestore: restoring non-directory files
 xfsrestore: restore complete: SECS seconds elapsed
-- 
2.13.3


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-07-18 14:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-18 14:37 [PATCH v2 1/3] fsstress: new writev and readv operations test Zorro Lang
2017-07-18 14:37 ` [PATCH v2 2/3] fsstress: add AIO read/write and fsync test Zorro Lang
2017-07-18 14:37 ` [PATCH v2 3/3] xfs/068: update golden output due to new operations in fsstress Zorro Lang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox