Merge pull request #7 from hjelmn/master

Add mdtest to IOR repo and update backends to support mdtest
master
Glenn K. Lockwood 2017-10-23 12:03:48 -07:00 committed by GitHub
commit e1968cd4ad
18 changed files with 2911 additions and 647 deletions

0
AUTHORS Normal file
View File

9
NEWS Normal file
View File

@ -0,0 +1,9 @@
IOR NEWS
========
Last updated 2017-06
3.0.2
- IOR and mdtest now share a common codebase. This will make it easier
run performance benchmarks on new hardware.

View File

@ -1,11 +1,3 @@
#!/bin/sh
set -x
aclocal -I config || exit 1
#libtoolize --automake --copy --force || exit 1
autoheader || exit 1
automake --add-missing --copy --force-missing --foreign || exit 1
#autoconf --force --warnings=all || exit 1
autoconf --force || exit 1
rm -fr autom4te*.cache
exit 0
autoreconf -ivf

View File

@ -11,6 +11,10 @@
# Read metadata from the META file.
##*****************************************************************************
m4_define([META_FILE], m4_include([META]))
m4_define([META_PACKAGE_NAME], regexp(META_FILE, [^Package:\s*\(.*\)], [\1]))
m4_define([META_PACKAGE_VERSION], regexp(META_FILE, [^Version:\s*\(.*\)$], [\1]))
AC_DEFUN([X_AC_META], [
AC_MSG_CHECKING([metadata])

View File

@ -2,8 +2,12 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.62])
AC_INIT
AC_CONFIG_MACRO_DIR([config])
AC_INIT([META_PACKAGE_NAME],[META_PACKAGE_VERSION],[],[META_PACKAGE_NAME])
X_AC_META
AC_CONFIG_AUX_DIR([config])
AC_CONFIG_SRCDIR([src/ior.c])
AC_CONFIG_HEADER([src/config.h])
@ -11,22 +15,25 @@ AC_CONFIG_HEADER([src/config.h])
AC_CANONICAL_HOST
# Automake support
AM_INIT_AUTOMAKE([$META_NAME], [$META_VERSION], [check-news dist-bzip2 gnu no-define])
AM_INIT_AUTOMAKE([check-news dist-bzip2 gnu no-define])
AM_MAINTAINER_MODE
# Checks for programs.
AX_PROG_CC_MPI
# No reason not to require modern C at this point
AC_PROG_CC_C99
# Checks for libraries.
# Checks for header files.
AC_CHECK_HEADERS([fcntl.h libintl.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h sys/statfs.h sys/statvfs.h sys/time.h unistd.h wchar.h plfs.h hdfs.h beegfs/beegfs.h])
AC_CHECK_HEADERS([fcntl.h libintl.h stdlib.h string.h strings.h sys/ioctl.h sys/param.h sys/statfs.h sys/statvfs.h sys/time.h sys/param.h sys/mount.h unistd.h wchar.h hdfs.h beegfs/beegfs.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
# Checks for library functions.
AC_CHECK_FUNCS([getpagesize gettimeofday memset mkdir pow putenv realpath regcomp sqrt strcasecmp strchr strerror strncasecmp strstr uname])
AC_CHECK_FUNCS([getpagesize gettimeofday memset mkdir pow putenv realpath regcomp sqrt strcasecmp strchr strerror strncasecmp strstr uname statfs statvfs])
AC_SEARCH_LIBS([sqrt], [m], [],
[AC_MSG_ERROR([Math library not found])])
@ -109,17 +116,6 @@ AM_COND_IF([USE_NCMPI_AIORI],[
AC_DEFINE([USE_NCMPI_AIORI], [], [Build NCMPI backend AIORI])
])
# PLFS IO support
AC_ARG_WITH([plfs],
[AS_HELP_STRING([--with-plfs],
[support IO with PLFS backend @<:@default=no@:>@])],
[],
[with_plfs=no])
AM_CONDITIONAL([USE_PLFS_AIORI], [test x$with_plfs = xyes])
AM_COND_IF([USE_PLFS_AIORI],[
AC_DEFINE([USE_PLFS_AIORI], [], [Build PLFS backend AIORI])
])
# POSIX IO support
AC_ARG_WITH([posix],
[AS_HELP_STRING([--with-posix],

View File

@ -1 +1,2 @@
dist_data_DATA = USER_GUIDE
dist_man_MANS = mdtest.1

188
doc/mdtest.1 Normal file
View File

@ -0,0 +1,188 @@
.TH mdtest 1 "2010-05-05" "mdtest-1.8.3" "mdtest"
.SH NAME
mdtest \- test file system metadata performance
.SH SYNOPSIS
.B mdtest
.I "[-options]"
.SH DESCRIPTION
.B mdtest
is a file system metadata performance test designed to run
in a cluster MPI environment against parallel file systems.
.PP
In each iteration of the test, each MPI task creates, stats, and removes
the specified number of directories and/or files and measures the performance
in ops/second. After all the iterations complete, the maximum, minimum,
mean ops/sec and the std. deviation are reported for each operation.
.SH OPTIONS
.TP
.I "-b" branching_factor
The branching factor of the hierarchical directory structure [default: 1].
.TP
.I "-B"
No barriers will be taken between the phases (create/stat/remove) of the tests.
.TP
.I "-c"
Use ``collective creates'', meaning task 0 does all the creates.
.TP
.I "-C"
Only perform the create phase of the tests.
.TP
.I "-d" testdir[@testdir2]
The directory in which the tests will run. For multiple pathes, must use fully-qualified pathnames.
[default: working directory of mdtest].
.TP
.I "-D"
Perform test on directories only (no files).
.TP
.I "-e" bytes
Set the number of Bytes to read from each file [default: 0].
.TP
.I "-E"
Only perform the read phase of the tests.
.TP
.I "-f" first
The first number of tasks on which the test will run
[default: 0].
.TP
.I "-F"
Perform test on files only (no directories).
.TP
.I "-h"
Display help message.
.TP
.I "-i" iterations
The number of iterations the test will run
[default: 1].
.TP
.I "-I" items_per_directory
The number of items per directory in the tree [default: 0].
.TP
.I "-l" last
The last number of tasks on which the test will run
[default: 0].
.TP
.I "-L"
Files/directories only created at the leaf level of the tree.
.TP
.I "-n" number_of_items
Every process will creat/stat/remove # directories and files
[default: 0].
.TP
.I "-N" stride
Stride # between neighbor tasks for file/dir stat, 0 = local
[default: 0].
.TP
.I "-p" seconds
Pre-iteration delay (in seconds).
.TP
.I "-r"
Only perform the remove phase of the tests.
.TP
.I "-R[seed]"
Randomly stat files. There is an optional argument that provides a seed
to the random number generator. (Note: There is no space between the
.I "-R"
and
the seed if one is provided.)
.TP
.I "-s" stride
Stride between the number of tasks for each test
[default: 1].
.TP
.I "-S"
Shared file access (file only, no directories).
.TP
.I "-t"
Include unique working directory management overhead in the results
(presumes
.I "-u"
option).
.TP
.I "-T"
Only perform the stat phase of the tests.
.TP
.I "-u"
Create a unique working directory for each task
(presumes
.I "-d"
option).
.TP
.I "-v"
Increase verbosity (each instance of option increments by one).
.TP
.I "-V" value
Set verbosity value
[default: 0].
.TP
.I "-w" bytes
Set the number of Bytes to write to each file after it is created
[default: 0].
.TP
.I "-z" tree_depth
The depth of the hierarchical directory tree [default: 0].
.SH EXAMPLES
.SS "Example 1"
.nf
$ mpirun -n 2 ./mdtest -d /tmp/z -n 100 -i 2
-- started at 11/23/2009 09:05:29 --
mdtest-1.8.1 was launched with 2 total task(s) on 1 nodes
Command line used: ./mdtest -d /tmp/z -n 100 -i 2
Path: /tmp
FS: 28.8 GiB Used FS: 8.6% 8.6%Inodes: 1.8 Mi Used Inodes: 5.1%
time to create tree: 0.000078 sec
tree creation rate: 12826.617737 ops/sec
2 tasks, 200 files/directories
SUMMARY: (of 2 iterations)
Operation Max Min Mean Std Dev
--------- --- --- ---- -------
Directory creation: 21489.415 17447.551 19468.483 2020.932
Directory stat : 154657.227 28731.061 91694.144 62963.083
Directory removal : 146756.613 21489.415 84123.014 62633.599
File creation : 42024.989 28731.061 35378.025 6646.964
File stat : 146756.613 17447.551 82102.082 64654.531
File removal : 156884.384 42024.989 99454.686 57429.698
time to remove tree: 0.001031 sec
tree removal rate: 970.005550 ops/sec
-- finished at 11/23/2009 09:05:29 --
.fi
.SS "Example 2"
.nf
$ mpirun -np 2 -H pc6 ./mdtest -d /tmp/z -b 2 -z 3 -I 10
-- started at 11/23/2009 09:09:23 --
mdtest-1.8.1 was launched with 2 total task(s) on 1 nodes
Command line used: ./mdtest -d /tmp/z -b 2 -z 3 -I 10
Path: /tmp
FS: 28.8 GiB Used FS: 8.6% 8.6%Inodes: 1.8 Mi Used Inodes: 5.1%
time to create tree: 0.000765 sec
tree creation rate: 19605.659084 ops/sec
2 tasks, 300 files/directories
SUMMARY: (of 1 iterations)
Operation Max Min Mean Std Dev
--------- --- --- ---- -------
Directory creation: 29365.707 29365.707 29365.707 0.000
Directory stat : 123701.455 123701.455 123701.455 0.000
Directory removal : 25623.459 25623.459 25623.459 0.000
File creation : 38704.743 38704.743 38704.743 0.000
File stat : 125477.782 125477.782 125477.782 0.000
File removal : 51911.845 51911.845 51911.845 0.000
time to remove tree: 0.000940 sec
tree removal rate: 15960.060883 ops/sec
-- finished at 11/23/2009 09:09:23 --
.fi
.SH "SEE ALSO"
\fBhttp://sourceforge.net/projects/mdtest\fR

View File

@ -1,70 +1,82 @@
bin_PROGRAMS = ior
bin_PROGRAMS = ior mdtest
if USE_CAPS
bin_PROGRAMS += IOR
bin_PROGRAMS += IOR MDTEST
endif
ior_SOURCES =
noinst_HEADERS = ior.h utilities.h parse_options.h aiori.h iordef.h
extraSOURCES = aiori.c
extraLDADD =
extraLDFLAGS =
extraCPPFLAGS =
ior_SOURCES = ior.c utilities.c parse_options.c
ior_LDFLAGS =
ior_LDADD =
ior_CPPFLAGS =
ior_LDFLAGS =
ior_LDADD =
ior_SOURCES += ior.c utilities.c parse_options.c
ior_SOURCES += ior.h utilities.h parse_options.h aiori.h iordef.h
mdtest_SOURCES = mdtest.c utilities.c
mdtest_LDFLAGS =
mdtest_LDADD =
mdtest_CPPFLAGS =
if USE_HDFS_AIORI
# TBD: figure out how to find the appropriate -I and -L dirs. Maybe we can
# get them from the corresponding bin/ dir in $PATH, or pick an
# environment var to use (and set it in modulefiles), or provide a
# config-flag, to set a variable we use here.
ior_SOURCES += aiori-HDFS.c
ior_CPPFLAGS += -I/opt/hadoop-2.2.0/include
ior_LDFLAGS += -L/opt/hadoop-2.2.0/lib/native
ior_LDADD += -lhdfs
extraSOURCES += aiori-HDFS.c
extraCPPFLAGS += -I/opt/hadoop-2.2.0/include
extraLDFLAGS += -L/opt/hadoop-2.2.0/lib/native
extraLDADD += -lhdfs
endif
if USE_HDF5_AIORI
ior_SOURCES += aiori-HDF5.c
ior_LDADD += -lhdf5 -lz
extraSOURCES += aiori-HDF5.c
extraLDADD += -lhdf5 -lz
endif
if USE_MPIIO_AIORI
ior_SOURCES += aiori-MPIIO.c
extraSOURCES += aiori-MPIIO.c
endif
if USE_NCMPI_AIORI
ior_SOURCES += aiori-NCMPI.c
ior_LDADD += -lpnetcdf
endif
if USE_PLFS_AIORI
# TBD: modulefiles don't add PLFS_VER to env, but you can find it embedded in
# $PLFS_HOME. configure.ac should extract this for us. Then we should
# add -D... to ior_CPPFLAGS, here. Then aiori-PLFS.c can conditionalize
# compilation of calls that vary according to PLFS version.
ior_SOURCES += aiori-PLFS.c
ior_LDADD += -lplfs
extraSOURCES += aiori-NCMPI.c
extraLDADD += -lpnetcdf
endif
if USE_POSIX_AIORI
ior_SOURCES += aiori-POSIX.c
extraSOURCES += aiori-POSIX.c
endif
if USE_S3_AIORI
ior_SOURCES += aiori-S3.c
extraSOURCES += aiori-S3.c
if AWS4C_DIR
ior_CPPFLAGS += $(AWS4C_CPPFLAGS)
ior_LDFLAGS += $(AWS4C_LDFLAGS)
extraCPPFLAGS += $(AWS4C_CPPFLAGS)
extraLDFLAGS += $(AWS4C_LDFLAGS)
endif
ior_LDADD += -lcurl
ior_LDADD += -lxml2
ior_LDADD += -laws4c
ior_LDADD += -laws4c_extra
extraLDADD += -lcurl
extraLDADD += -lxml2
extraLDADD += -laws4c
extraLDADD += -laws4c_extra
endif
ior_SOURCES += $(extraSOURCES)
ior_LDFLAGS += $(extraLDFLAGS)
ior_LDADD += $(extraLDADD)
ior_CPPFLAGS += $(extraCPPFLAGS)
mdtest_SOURCES += $(extraSOURCES)
mdtest_LDFLAGS += $(extraLDFLAGS)
mdtest_LDADD += $(extraLDADD)
mdtest_CPPFLAGS += $(extraCPPFLAGS)
IOR_SOURCES = $(ior_SOURCES)
IOR_LDADD = $(ior_LDADD)
IOT_CPPFLAGS = $(ior_CPPFLAGS)
MDTEST_SOURCES = $(mdtest_SOURCES)
MDTEST_LDADD = $(mdtest_LDADD)
MDTEST_CPPFLAGS = $(mdtest_CPPFLAGS)

View File

@ -96,15 +96,15 @@ static IOR_offset_t HDF5_GetFileSize(IOR_param_t *, MPI_Comm, char *);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t hdf5_aiori = {
"HDF5",
HDF5_Create,
HDF5_Open,
HDF5_Xfer,
HDF5_Close,
HDF5_Delete,
HDF5_SetVersion,
HDF5_Fsync,
HDF5_GetFileSize
.name = "HDF5",
.create = HDF5_Create,
.open = HDF5_Open,
.xfer = HDF5_Xfer,
.close = HDF5_Close,
.delete = HDF5_Delete,
.set_version = HDF5_SetVersion,
.fsync = HDF5_Fsync,
.get_file_size = HDF5_GetFileSize,
};
static hid_t xferPropList; /* xfer property list */

View File

@ -114,15 +114,15 @@ static IOR_offset_t HDFS_GetFileSize(IOR_param_t *, MPI_Comm, char *);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t hdfs_aiori = {
"HDFS",
HDFS_Create,
HDFS_Open,
HDFS_Xfer,
HDFS_Close,
HDFS_Delete,
HDFS_SetVersion,
HDFS_Fsync,
HDFS_GetFileSize
.name = "HDFS",
.create = HDFS_Create,
.open = HDFS_Open,
.xfer = HDFS_Xfer,
.close = HDFS_Close,
.delete = HDFS_Delete,
.set_version = HDFS_SetVersion,
.fsync = HDFS_Fsync,
.get_file_size = HDFS_GetFileSize,
};
/***************************** F U N C T I O N S ******************************/

View File

@ -60,15 +60,15 @@ static IOR_offset_t NCMPI_GetFileSize(IOR_param_t *, MPI_Comm, char *);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t ncmpi_aiori = {
"NCMPI",
NCMPI_Create,
NCMPI_Open,
NCMPI_Xfer,
NCMPI_Close,
NCMPI_Delete,
NCMPI_SetVersion,
NCMPI_Fsync,
NCMPI_GetFileSize
.name = "NCMPI",
.create = NCMPI_Create,
.open = NCMPI_Open,
.xfer = NCMPI_Xfer,
.close = NCMPI_Close,
.delete = NCMPI_Delete,
.set_version = NCMPI_SetVersion,
.fsync = NCMPI_Fsync,
.get_file_size = NCMPI_GetFileSize,
};
/***************************** F U N C T I O N S ******************************/

View File

@ -1,473 +0,0 @@
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
/*
* Copyright (c) 2009, Los Alamos National Security, LLC All rights reserved.
* Copyright 2009. Los Alamos National Security, LLC. This software was produced
* under U.S. Government contract DE-AC52-06NA25396 for Los Alamos National
* Laboratory (LANL), which is operated by Los Alamos National Security, LLC for
* the U.S. Department of Energy. The U.S. Government has rights to use,
* reproduce, and distribute this software. NEITHER THE GOVERNMENT NOR LOS
* ALAMOS NATIONAL SECURITY, LLC MAKES ANY WARRANTY, EXPRESS OR IMPLIED, OR
* ASSUMES ANY LIABILITY FOR THE USE OF THIS SOFTWARE. If software is
* modified to produce derivative works, such modified software should be
* clearly marked, so as not to confuse it with the version available from
* LANL.
*
* Additionally, redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of Los Alamos National Security, LLC, Los Alamos National
* Laboratory, LANL, the U.S. Government, nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY LOS ALAMOS NATIONAL SECURITY, LLC AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL LOS ALAMOS NATIONAL SECURITY, LLC OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*/
/******************************************************************************\
*
* Implement of abstract I/O interface for PLFS.
*
\******************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#ifdef __linux__
#include <sys/ioctl.h> /* necessary for: */
#define __USE_GNU /* O_DIRECT and */
#include <fcntl.h> /* IO operations */
#undef __USE_GNU
#endif /* __linux__ */
#include <errno.h>
#include <fcntl.h> /* IO operations */
#include <sys/stat.h>
#include <assert.h>
/*
#ifdef HAVE_LUSTRE_LUSTRE_USER_H
#include <lustre/lustre_user.h>
#endif
*/
#include "ior.h"
#include "aiori.h"
#include "iordef.h"
#ifndef open64 /* necessary for TRU64 -- */
# define open64 open /* unlikely, but may pose */
#endif /* not open64 */ /* conflicting prototypes */
#ifndef lseek64 /* necessary for TRU64 -- */
# define lseek64 lseek /* unlikely, but may pose */
#endif /* not lseek64 */ /* conflicting prototypes */
#ifndef O_BINARY /* Required on Windows */
# define O_BINARY 0
#endif
#include "plfs.h"
#include "utilities.h"
/**************************** P R O T O T Y P E S *****************************/
static void *PLFS_Create(char *, IOR_param_t *);
static void *PLFS_Open(char *, IOR_param_t *);
static IOR_offset_t PLFS_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void PLFS_Close(void *, IOR_param_t *);
static void PLFS_Delete(char *, IOR_param_t *);
static void PLFS_SetVersion(IOR_param_t *);
static void PLFS_Fsync(void *, IOR_param_t *);
static IOR_offset_t PLFS_GetFileSize(IOR_param_t *, MPI_Comm, char *);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t plfs_aiori = {
"PLFS",
PLFS_Create,
PLFS_Open,
PLFS_Xfer,
PLFS_Close,
PLFS_Delete,
PLFS_SetVersion,
PLFS_Fsync,
PLFS_GetFileSize
};
/***************************** F U N C T I O N S ******************************/
/*
* Create or open the file. Pass TRUE if creating and FALSE if opening an existing file.
*/
static void *PLFS_Create_Or_Open( char *testFileName, IOR_param_t *param, unsigned char createFile ) {
Plfs_fd *plfs_fd = NULL;
int fd_oflags = 0, plfs_return;
/*
* Check for unsupported flags.
*
* If they want RDWR, we don't know if they're going to try to do both, so we
* can't default to either O_RDONLY or O_WRONLY. Thus, we error and exit.
*
* The other two, we just note that they are not supported and don't do them.
*/
if ( param->openFlags & IOR_RDWR ) {
ERR( "Opening or creating a file in RDWR is not implemented in PLFS" );
}
if ( param->openFlags & IOR_EXCL ) {
fprintf( stdout, "Opening or creating a file in Exclusive mode is not implemented in PLFS\n" );
}
if ( param->openFlags & IOR_APPEND ) {
fprintf( stdout, "Opening or creating a file for appending is not implemented in PLFS\n" );
}
/*
* Setup the flags to be used.
*/
if ( createFile == TRUE ) {
fd_oflags = O_CREAT;
}
if ( param->openFlags & IOR_WRONLY ) {
if ( !param->filePerProc ) {
// in N-1 mode, only rank 0 truncates the file
if ( rank != 0 ) {
fd_oflags |= O_WRONLY;
} else {
fd_oflags |= O_TRUNC;
fd_oflags |= O_WRONLY;
}
} else {
// in N-N mode, everyone does truncate
fd_oflags |= O_TRUNC;
fd_oflags |= O_WRONLY;
}
} else {
fd_oflags |= O_RDONLY;
}
/*
* Now see if O_DIRECT is needed.
*/
if ( param->useO_DIRECT == TRUE ) {
set_o_direct_flag( &fd_oflags );
}
/*
* For N-1 write, All other ranks wait for Rank 0 to open the file.
* this is bec 0 does truncate and rest don't
* it would be dangerous for all to do truncate as they might
* truncate each other's writes
*/
if (( param->openFlags & IOR_WRONLY ) &&
( !param->filePerProc ) &&
( rank != 0 )) {
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
}
/*
* Now rank zero can open and truncate, if necessary.
*/
plfs_return = plfs_open( &( plfs_fd ), testFileName, fd_oflags, rank, 0666, NULL );
if ( plfs_return != 0 ) {
ERR( "Failed to open the file" );
}
/*
* For N-1 write, Rank 0 waits for the other ranks to open the file after it has.
*/
if (( param->openFlags & IOR_WRONLY ) &&
( !param->filePerProc ) &&
( rank == 0 )) {
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
}
return ((void *) plfs_fd );
}
/*
* Create and open a file through the PLFS interface.
*/
static void *PLFS_Create( char *testFileName, IOR_param_t * param ) {
return PLFS_Create_Or_Open( testFileName, param, TRUE );
}
/*
* Open a file through the PLFS interface.
*/
static void *PLFS_Open( char *testFileName, IOR_param_t * param ) {
if ( param->openFlags & IOR_CREAT ) {
return PLFS_Create_Or_Open( testFileName, param, TRUE );
} else {
return PLFS_Create_Or_Open( testFileName, param, FALSE );
}
}
/*
* Write or read access to file using the PLFS interface.
*/
static IOR_offset_t PLFS_Xfer(int access, void *file, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param) {
int xferRetries = 0;
long long remaining = (long long)length;
char * ptr = (char *)buffer;
long long rc;
off_t offset = param->offset;
Plfs_fd * plfs_fd = (Plfs_fd *)file;
while ( remaining > 0 ) {
/* write/read file */
if (access == WRITE) { /* WRITE */
if (verbose >= VERBOSE_4) {
fprintf( stdout, "task %d writing to offset %lld\n",
rank,
param->offset + length - remaining);
}
#if 0
rc = plfs_write( plfs_fd, ptr, remaining, offset, rank ); /* PLFS 2.4 */
#else
ssize_t bytes_written = 0;
rc = plfs_write( plfs_fd, ptr, remaining, offset, rank, &bytes_written ); /* PLFS 2.5 */
#endif
if ( rc < 0 ) {
ERR( "plfs_write() failed" );
}
offset += rc;
if ( param->fsyncPerWrite == TRUE ) {
PLFS_Fsync( plfs_fd, param );
}
} else { /* READ or CHECK */
if (verbose >= VERBOSE_4) {
fprintf( stdout, "task %d reading from offset %lld\n",
rank,
param->offset + length - remaining );
}
#if 0
rc = plfs_read( plfs_fd, ptr, remaining, param->offset ); /* PLFS 2.4 */
#else
ssize_t bytes_read = 0;
rc = plfs_read( plfs_fd, ptr, remaining, param->offset, &bytes_read ); /* PLFS 2.5 */
#endif
if ( rc == 0 ) {
ERR( "plfs_read() returned EOF prematurely" );
}
if ( rc < 0 ) {
ERR( "plfs_read() failed" );
}
offset += rc;
}
if ( rc < remaining ) {
fprintf(stdout, "WARNING: Task %d, partial %s, %lld of %lld bytes at offset %lld\n",
rank,
access == WRITE ? "plfs_write()" : "plfs_read()",
rc, remaining,
param->offset + length - remaining );
if ( param->singleXferAttempt == TRUE ) {
MPI_CHECK( MPI_Abort( MPI_COMM_WORLD, -1 ), "barrier error" );
}
if ( xferRetries > MAX_RETRY ) {
ERR( "too many retries -- aborting" );
}
}
assert( rc >= 0 );
assert( rc <= remaining );
remaining -= rc;
ptr += rc;
xferRetries++;
}
return ( length );
}
/*
* Perform plfs_sync().
*/
static void PLFS_Fsync( void *fd, IOR_param_t * param ) {
Plfs_fd *plfs_fd = (Plfs_fd *)fd;
if ( plfs_sync( plfs_fd ) != 0 ) {
EWARN( "plfs_sync() failed" );
}
}
/*
* Close a file through the PLFS interface.
*/
static void PLFS_Close( void *fd, IOR_param_t * param ) {
Plfs_fd * plfs_fd = (Plfs_fd *)fd;
int open_flags;
long long rc;
if ( param->openFlags & IOR_WRONLY ) {
open_flags = O_CREAT | O_WRONLY;
} else {
open_flags = O_RDONLY;
}
#if 0
rc = plfs_close( plfs_fd, rank, param->id, open_flags, NULL ); /* PLFS 2.4 */
#else
int ref_count = 0;
rc = plfs_close( plfs_fd, rank, param->id, open_flags, NULL, &ref_count ); /* PLFS 2.5 */
#endif
if ( rc != 0 ) {
ERR( "plfs_close() failed" );
}
free( fd );
}
/*
* Delete a file through the POSIX interface.
*/
static void PLFS_Delete( char *testFileName, IOR_param_t * param ) {
char errmsg[256];
if ( plfs_unlink( testFileName ) != 0 ) {
sprintf(
errmsg,
"[RANK %03d]: plfs_unlink() of file \"%s\" failed\n",
rank, testFileName);
EWARN( errmsg );
}
}
/*
* Determine api version.
*/
static void PLFS_SetVersion( IOR_param_t * test ) {
strcpy( test->apiVersion, test->api );
}
/*
* Use plfs_getattr to return aggregate file size.
*/
static IOR_offset_t PLFS_GetFileSize(
IOR_param_t * test, MPI_Comm testComm, char *testFileName) {
int plfs_return;
Plfs_fd * plfs_fd = NULL;
struct stat stat_buf;
IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum;
long long rc;
plfs_return = plfs_open( &( plfs_fd ), testFileName, O_RDONLY, rank, 0666, NULL );
if ( plfs_return != 0 ) {
ERR( "plfs_open() failed before reading the file size attribute" );
}
if ( plfs_getattr( plfs_fd, testFileName, &stat_buf, 1 ) != 0 ) {
ERR( "plfs_getattr() failed" );
}
#if 0
rc = plfs_close( plfs_fd, rank, test->id, O_RDONLY, NULL ); /* PLFS 2.4 */
#else
int ref_count = 0;
rc = plfs_close( plfs_fd, rank, test->id, O_RDONLY, NULL, &ref_count ); /* PLFS 2.5 */
#endif
if ( rc != 0 ) {
ERR( "plfs_close() failed after reading the file size attribute" );
}
aggFileSizeFromStat = stat_buf.st_size;
if ( test->filePerProc == TRUE ) {
MPI_CHECK(
MPI_Allreduce(
&aggFileSizeFromStat, &tmpSum, 1, MPI_LONG_LONG_INT, MPI_SUM, testComm ),
"cannot total data moved" );
aggFileSizeFromStat = tmpSum;
} else {
MPI_CHECK(
MPI_Allreduce(
&aggFileSizeFromStat, &tmpMin, 1, MPI_LONG_LONG_INT, MPI_MIN, testComm ),
"cannot total data moved" );
MPI_CHECK(
MPI_Allreduce(
&aggFileSizeFromStat, &tmpMax, 1, MPI_LONG_LONG_INT, MPI_MAX, testComm ),
"cannot total data moved" );
if ( tmpMin != tmpMax ) {
if ( rank == 0 ) {
WARN( "inconsistent file size by different tasks" );
}
/* incorrect, but now consistent across tasks */
aggFileSizeFromStat = tmpMin;
}
}
return ( aggFileSizeFromStat );
}

View File

@ -78,15 +78,15 @@ static IOR_offset_t POSIX_GetFileSize(IOR_param_t *, MPI_Comm, char *);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t posix_aiori = {
"POSIX",
POSIX_Create,
POSIX_Open,
POSIX_Xfer,
POSIX_Close,
POSIX_Delete,
POSIX_SetVersion,
POSIX_Fsync,
POSIX_GetFileSize
.name = "POSIX",
.create = POSIX_Create,
.open = POSIX_Open,
.xfer = POSIX_Xfer,
.close = POSIX_Close,
.delete = POSIX_Delete,
.set_version = POSIX_SetVersion,
.fsync = POSIX_Fsync,
.get_file_size = POSIX_GetFileSize,
};
/***************************** F U N C T I O N S ******************************/

View File

@ -132,45 +132,45 @@ static IOR_offset_t S3_GetFileSize(IOR_param_t*, MPI_Comm, char*);
// N:1 writes use multi-part upload
// N:N fails if "transfer-size" != "block-size" (because that requires "append")
ior_aiori_t s3_aiori = {
"S3",
S3_Create,
S3_Open,
S3_Xfer,
S3_Close,
S3_Delete,
S3_SetVersion,
S3_Fsync,
S3_GetFileSize
.name = "S3",
.create = S3_Create,
.open = S3_Open,
.xfer = S3_Xfer,
.close = S3_Close,
.delete = S3_Delete,
.set_version = S3_SetVersion,
.fsync = S3_Fsync,
.get_file_size = S3_GetFileSize,
};
// "S3", plus EMC-extensions enabled
// N:1 writes use multi-part upload
// N:N succeeds (because EMC-extensions support "append")
ior_aiori_t s3_plus_aiori = {
"S3_plus",
S3_Create,
S3_Open,
S3_Xfer,
S3_Close,
S3_Delete,
S3_SetVersion,
S3_Fsync,
S3_GetFileSize
.name = "S3_plus",
.create = S3_Create,
.open = S3_Open,
.xfer = S3_Xfer,
.close = S3_Close,
.delete = S3_Delete,
.set_version = S3_SetVersion,
.fsync = S3_Fsync,
.get_file_size = S3_GetFileSize,
};
// Use EMC-extensions for N:1 write, as well
// N:1 writes use EMC byte-range
// N:N succeeds because EMC-extensions support "append"
ior_aiori_t s3_emc_aiori = {
"S3_EMC",
EMC_Create,
EMC_Open,
EMC_Xfer,
EMC_Close,
S3_Delete,
S3_SetVersion,
S3_Fsync,
S3_GetFileSize
.name = "S3_EMC",
.create = EMC_Create,
.open = EMC_Open,
.xfer = EMC_Xfer,
.close = EMC_Close,
.delete = S3_Delete,
.set_version = S3_SetVersion,
.fsync = S3_Fsync,
.get_file_size = S3_GetFileSize,
};

147
src/aiori.c Normal file
View File

@ -0,0 +1,147 @@
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* Definitions and prototypes of abstract I/O interface
*
\******************************************************************************/
#include "aiori.h"
#if defined(HAVE_SYS_STATVFS_H)
#include <sys/statvfs.h>
#endif
#if defined(HAVE_SYS_STATFS_H)
#include <sys/statfs.h>
#endif
/*
* Bind the global "backend" pointer to the requested backend AIORI's
* function table.
*/
ior_aiori_t *available_aiori[] = {
#ifdef USE_HDF5_AIORI
&hdf5_aiori,
#endif
#ifdef USE_HDFS_AIORI
&hdfs_aiori,
#endif
#ifdef USE_MPIIO_AIORI
&mpiio_aiori,
#endif
#ifdef USE_NCMPI_AIORI
&ncmpi_aiori,
#endif
#ifdef USE_POSIX_AIORI
&posix_aiori,
#endif
#ifdef USE_S3_AIORI
&s3_aiori,
&s3_plus_aiori,
&s3_emc_aiori,
#endif
NULL
};
/**
* Default statfs implementation.
*
* @param[in] path Path to run statfs on
* @param[out] statfs_buf AIORI statfs buffer
*
* This function provides a AIORI statfs for POSIX-compliant filesystems. It
* uses statvfs is available and falls back on statfs.
*/
static int aiori_statfs (const char *path, ior_aiori_statfs_t *stat_buf, IOR_param_t * param)
{
int ret;
#if defined(HAVE_STATVFS)
struct statvfs statfs_buf;
ret = statvfs (path, &statfs_buf);
#else
struct statfs statfs_buf;
ret = statfs (path, &statfs_buf);
#endif
if (-1 == ret) {
return -1;
}
stat_buf->f_bsize = statfs_buf.f_bsize;
stat_buf->f_blocks = statfs_buf.f_blocks;
stat_buf->f_bfree = statfs_buf.f_bfree;
stat_buf->f_files = statfs_buf.f_files;
stat_buf->f_ffree = statfs_buf.f_ffree;
return 0;
}
static int aiori_mkdir (const char *path, mode_t mode, IOR_param_t * param)
{
return mkdir (path, mode);
}
static int aiori_rmdir (const char *path, IOR_param_t * param)
{
return rmdir (path);
}
static int aiori_access (const char *path, int mode, IOR_param_t * param)
{
return access (path, mode);
}
static int aiori_stat (const char *path, struct stat *buf, IOR_param_t * param)
{
return stat (path, buf);
}
const ior_aiori_t *aiori_select (const char *api)
{
for (ior_aiori_t **tmp = available_aiori ; *tmp != NULL; ++tmp) {
if (NULL == api || strcasecmp(api, (*tmp)->name) == 0) {
if (NULL == (*tmp)->statfs) {
(*tmp)->statfs = aiori_statfs;
}
if (NULL == (*tmp)->mkdir) {
(*tmp)->mkdir = aiori_mkdir;
}
if (NULL == (*tmp)->rmdir) {
(*tmp)->rmdir = aiori_rmdir;
}
if (NULL == (*tmp)->access) {
(*tmp)->access = aiori_access;
}
if (NULL == (*tmp)->stat) {
(*tmp)->stat = aiori_stat;
}
return *tmp;
}
}
return NULL;
}
int aiori_count (void)
{
return sizeof (available_aiori)/sizeof(available_aiori[0]) - 1;
}
const char *aiori_default (void)
{
if (aiori_count () > 0) {
return available_aiori[0]->name;
}
return NULL;
}

View File

@ -21,6 +21,8 @@
# include <mpio.h>
#endif /* not MPI_FILE_NULL */
#include <sys/stat.h>
#include "ior.h"
#include "iordef.h" /* IOR Definitions */
@ -50,6 +52,15 @@
#define IOR_IWOTH 0x0400 /* write permission: other */
#define IOR_IXOTH 0x0800 /* execute permission: other */
typedef struct ior_aiori_statfs {
uint64_t f_bsize;
uint64_t f_blocks;
uint64_t f_bfree;
uint64_t f_bavail;
uint64_t f_files;
uint64_t f_ffree;
} ior_aiori_statfs_t;
typedef struct ior_aiori {
char *name;
void *(*create)(char *, IOR_param_t *);
@ -61,6 +72,11 @@ typedef struct ior_aiori {
void (*set_version)(IOR_param_t *);
void (*fsync)(void *, IOR_param_t *);
IOR_offset_t (*get_file_size)(IOR_param_t *, MPI_Comm, char *);
int (*statfs) (const char *, ior_aiori_statfs_t *, IOR_param_t * param);
int (*mkdir) (const char *path, mode_t mode, IOR_param_t * param);
int (*rmdir) (const char *path, IOR_param_t * param);
int (*access) (const char *path, int mode, IOR_param_t * param);
int (*stat) (const char *path, struct stat *buf, IOR_param_t * param);
} ior_aiori_t;
extern ior_aiori_t hdf5_aiori;
@ -68,11 +84,13 @@ extern ior_aiori_t hdfs_aiori;
extern ior_aiori_t mpiio_aiori;
extern ior_aiori_t ncmpi_aiori;
extern ior_aiori_t posix_aiori;
extern ior_aiori_t plfs_aiori;
extern ior_aiori_t s3_aiori;
extern ior_aiori_t s3_plus_aiori;
extern ior_aiori_t s3_emc_aiori;
const ior_aiori_t *aiori_select (const char *api);
int aiori_count (void);
const char *aiori_default (void);
IOR_offset_t MPIIO_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
char *testFileName);

View File

@ -50,34 +50,7 @@ int totalErrorCount = 0;
double wall_clock_delta = 0;
double wall_clock_deviation;
ior_aiori_t *backend;
ior_aiori_t *available_aiori[] = {
#ifdef USE_HDF5_AIORI
&hdf5_aiori,
#endif
#ifdef USE_HDFS_AIORI
&hdfs_aiori,
#endif
#ifdef USE_MPIIO_AIORI
&mpiio_aiori,
#endif
#ifdef USE_NCMPI_AIORI
&ncmpi_aiori,
#endif
#ifdef USE_POSIX_AIORI
&posix_aiori,
#endif
#ifdef USE_PLFS_AIORI
&plfs_aiori,
#endif
#ifdef USE_S3_AIORI
&s3_aiori,
&s3_plus_aiori,
&s3_emc_aiori,
#endif
NULL
};
const ior_aiori_t *backend;
static void DestroyTests(IOR_test_t *tests_head);
static void DisplayUsage(char **);
@ -135,7 +108,7 @@ int main(int argc, char **argv)
"cannot set errhandler"); */
/* Sanity check, we were compiled with SOME backend, right? */
if (available_aiori[0] == NULL) {
if (0 == aiori_count ()) {
ERR("No IO backends compiled into ior. "
"Run 'configure --with-<backend>', and recompile.");
}
@ -204,13 +177,16 @@ int main(int argc, char **argv)
*/
void init_IOR_Param_t(IOR_param_t * p)
{
assert(available_aiori[0] != NULL);
const char *default_aiori = aiori_default ();
assert (NULL != default_aiori);
memset(p, 0, sizeof(IOR_param_t));
p->mode = IOR_IRUSR | IOR_IWUSR | IOR_IRGRP | IOR_IWGRP;
p->openFlags = IOR_RDWR | IOR_CREAT;
strncpy(p->api, available_aiori[0]->name, MAX_STR);
strncpy(p->api, default_aiori, MAX_STR);
strncpy(p->platform, "HOST(OSTYPE)", MAX_STR);
strncpy(p->testFileName, "testFile", MAXPATHLEN);
@ -247,32 +223,20 @@ void init_IOR_Param_t(IOR_param_t * p)
p->beegfs_chunkSize = -1;
}
/*
* Bind the global "backend" pointer to the requested backend AIORI's
* function table.
*/
static void AioriBind(char* api, IOR_param_t* param)
{
ior_aiori_t **tmp;
backend = NULL;
for (tmp = available_aiori; *tmp != NULL; tmp++) {
if (strcmp(api, (*tmp)->name) == 0) {
backend = *tmp;
break;
backend = aiori_select (api);
if (NULL != backend) {
if (! strncmp(api, "S3", 2)) {
if (! strcmp(api, "S3_EMC")) {
param->curl_flags |= IOR_CURL_S3_EMC_EXT;
} else {
param->curl_flags &= ~(IOR_CURL_S3_EMC_EXT);
}
}
}
if (backend == NULL) {
} else {
ERR("unrecognized IO API");
}
else if (! strncmp(api, "S3", 2)) {
if (! strcmp(api, "S3_EMC"))
param->curl_flags |= IOR_CURL_S3_EMC_EXT;
else
param->curl_flags &= ~(IOR_CURL_S3_EMC_EXT);
}
}
static void

2406
src/mdtest.c Normal file

File diff suppressed because it is too large Load Diff