Started to move IOR specific knowledge out of AIORI.

For now, and compatibility, IOR options can still be set/internally accessed using the backends init_xfer_options.
This should be removed in the long run to strip away this dependency.
master
Julian M. Kunkel 2020-05-30 18:19:48 +01:00
parent 2de4210311
commit 1890aaaeb0
12 changed files with 371 additions and 438 deletions

View File

@ -46,12 +46,17 @@ static option_help * DUMMY_options(void ** init_backend_options, void * init_val
return help;
}
static void *DUMMY_Create(char *testFileName, IOR_param_t * param)
static int count_init = 0;
static void *DUMMY_Create(char *testFileName, int iorflags, void * param)
{
if(count_init <= 0){
ERR("DUMMY missing initialization in create\n");
}
if(verbose > 4){
fprintf(out_logfile, "DUMMY create: %s = %p\n", testFileName, current);
}
dummy_options_t * o = (dummy_options_t*) param->backend_options;
dummy_options_t * o = (dummy_options_t*) param;
if (o->delay_creates){
if (! o->delay_rank_0_only || (o->delay_rank_0_only && rank == 0)){
struct timespec wait = { o->delay_creates / 1000 / 1000, 1000l * (o->delay_creates % 1000000)};
@ -61,15 +66,18 @@ static void *DUMMY_Create(char *testFileName, IOR_param_t * param)
return current++;
}
static void *DUMMY_Open(char *testFileName, IOR_param_t * param)
static void *DUMMY_Open(char *testFileName, int flags, void * param)
{
if(count_init <= 0){
ERR("DUMMY missing initialization in open\n");
}
if(verbose > 4){
fprintf(out_logfile, "DUMMY open: %s = %p\n", testFileName, current);
}
return current++;
}
static void DUMMY_Fsync(void *fd, IOR_param_t * param)
static void DUMMY_Fsync(void *fd, void * param)
{
if(verbose > 4){
fprintf(out_logfile, "DUMMY fsync %p\n", fd);
@ -77,18 +85,18 @@ static void DUMMY_Fsync(void *fd, IOR_param_t * param)
}
static void DUMMY_Sync(IOR_param_t * param)
static void DUMMY_Sync(void * param)
{
}
static void DUMMY_Close(void *fd, IOR_param_t * param)
static void DUMMY_Close(void *fd, void * param)
{
if(verbose > 4){
fprintf(out_logfile, "DUMMY close %p\n", fd);
}
}
static void DUMMY_Delete(char *testFileName, IOR_param_t * param)
static void DUMMY_Delete(char *testFileName, void * param)
{
if(verbose > 4){
fprintf(out_logfile, "DUMMY delete: %s\n", testFileName);
@ -100,7 +108,7 @@ static char * DUMMY_getVersion()
return "0.5";
}
static IOR_offset_t DUMMY_GetFileSize(IOR_param_t * test, MPI_Comm testComm, char *testFileName)
static IOR_offset_t DUMMY_GetFileSize(void * test, MPI_Comm testComm, char *testFileName)
{
if(verbose > 4){
fprintf(out_logfile, "DUMMY getFileSize: %s\n", testFileName);
@ -108,11 +116,11 @@ static IOR_offset_t DUMMY_GetFileSize(IOR_param_t * test, MPI_Comm testComm, cha
return 0;
}
static IOR_offset_t DUMMY_Xfer(int access, void *file, IOR_size_t * buffer, IOR_offset_t length, IOR_param_t * param){
static IOR_offset_t DUMMY_Xfer(int access, void *file, IOR_size_t * buffer, IOR_offset_t length, void * param){
if(verbose > 4){
fprintf(out_logfile, "DUMMY xfer: %p\n", file);
}
dummy_options_t * o = (dummy_options_t*) param->backend_options;
dummy_options_t * o = (dummy_options_t*) param;
if (o->delay_xfer){
if (! o->delay_rank_0_only || (o->delay_rank_0_only && rank == 0)){
struct timespec wait = {o->delay_xfer / 1000 / 1000, 1000l * (o->delay_xfer % 1000000)};
@ -122,7 +130,7 @@ static IOR_offset_t DUMMY_Xfer(int access, void *file, IOR_size_t * buffer, IOR_
return length;
}
static int DUMMY_statfs (const char * path, ior_aiori_statfs_t * stat, IOR_param_t * param){
static int DUMMY_statfs (const char * path, ior_aiori_statfs_t * stat, void * param){
stat->f_bsize = 1;
stat->f_blocks = 1;
stat->f_bfree = 1;
@ -132,26 +140,40 @@ static int DUMMY_statfs (const char * path, ior_aiori_statfs_t * stat, IOR_param
return 0;
}
static int DUMMY_mkdir (const char *path, mode_t mode, IOR_param_t * param){
static int DUMMY_mkdir (const char *path, mode_t mode, void * param){
return 0;
}
static int DUMMY_rmdir (const char *path, IOR_param_t * param){
static int DUMMY_rmdir (const char *path, void * param){
return 0;
}
static int DUMMY_access (const char *path, int mode, IOR_param_t * param){
static int DUMMY_access (const char *path, int mode, void * param){
return 0;
}
static int DUMMY_stat (const char *path, struct stat *buf, IOR_param_t * param){
static int DUMMY_stat (const char *path, struct stat *buf, void * param){
return 0;
}
static int DUMMY_check_params(IOR_param_t * test){
return 1;
static int DUMMY_check_params(void * test){
return 0;
}
static void DUMMY_init(void * options){
WARN("DUMMY initialized");
count_init++;
}
static void DUMMY_final(void * options){
WARN("DUMMY finalized");
if(count_init <= 0){
ERR("DUMMY invalid finalization\n");
}
count_init--;
}
ior_aiori_t dummy_aiori = {
.name = "DUMMY",
.name_legacy = NULL,
@ -168,11 +190,10 @@ ior_aiori_t dummy_aiori = {
.rmdir = DUMMY_rmdir,
.access = DUMMY_access,
.stat = DUMMY_stat,
.initialize = NULL,
.finalize = NULL,
.initialize = DUMMY_init,
.finalize = DUMMY_final,
.get_options = DUMMY_options,
.enable_mdtest = true,
.check_params = DUMMY_check_params,
.sync = DUMMY_Sync,
.enable_mdtest = true
.enable_mdtest = true
};

View File

@ -26,14 +26,15 @@
#include "utilities.h"
/**************************** P R O T O T Y P E S *****************************/
static void *MMAP_Create(char *, IOR_param_t *);
static void *MMAP_Open(char *, IOR_param_t *);
static void *MMAP_Create(char *, int flags, void *);
static void *MMAP_Open(char *, int flags, void *);
static IOR_offset_t MMAP_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void MMAP_Close(void *, IOR_param_t *);
static void MMAP_Fsync(void *, IOR_param_t *);
IOR_offset_t, void *);
static void MMAP_Close(void *, void *);
static void MMAP_Fsync(void *, void *);
static option_help * MMAP_options(void ** init_backend_options, void * init_values);
static void MMAP_init_xfer_options(IOR_param_t * params);
static int MMAP_check_params(void * options);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t mmap_aiori = {
@ -43,10 +44,12 @@ ior_aiori_t mmap_aiori = {
.xfer = MMAP_Xfer,
.close = MMAP_Close,
.delete = POSIX_Delete,
.init_xfer_options = MMAP_init_xfer_options,
.get_version = aiori_get_version,
.fsync = MMAP_Fsync,
.get_file_size = POSIX_GetFileSize,
.get_options = MMAP_options,
.check_params = MMAP_check_params
};
/***************************** F U N C T I O N S ******************************/
@ -79,25 +82,37 @@ static option_help * MMAP_options(void ** init_backend_options, void * init_valu
return help;
}
static void ior_mmap_file(int *file, IOR_param_t *param)
static IOR_param_t * ior_param = NULL;
static void MMAP_init_xfer_options(IOR_param_t * params){
ior_param = params;
}
static int MMAP_check_params(void * options){
if (ior_param->fsyncPerWrite && (ior_param->transferSize & (sysconf(_SC_PAGESIZE) - 1)))
ERR("transfer size must be aligned with PAGESIZE for MMAP with fsyncPerWrite");
return 0;
}
static void ior_mmap_file(int *file, int mflags, void *param)
{
int flags = PROT_READ;
IOR_offset_t size = param->expectedAggFileSize;
IOR_offset_t size = ior_param->expectedAggFileSize;
if (param->open == WRITE)
if (mflags & IOR_WRONLY || mflags & IOR_RDWR)
flags |= PROT_WRITE;
mmap_options_t *o = (mmap_options_t*) param->backend_options;
mmap_options_t *o = (mmap_options_t*) param;
o->mmap_ptr = mmap(NULL, size, flags, MAP_SHARED,
*file, 0);
if (o->mmap_ptr == MAP_FAILED)
ERR("mmap() failed");
if (param->randomOffset)
if (ior_param->randomOffset)
flags = POSIX_MADV_RANDOM;
else
flags = POSIX_MADV_SEQUENTIAL;
if(o->madv_pattern){
if (posix_madvise(o->mmap_ptr, size, flags) != 0)
ERR("madvise() failed");
@ -114,26 +129,25 @@ static void ior_mmap_file(int *file, IOR_param_t *param)
/*
* Creat and open a file through the POSIX interface, then setup mmap.
*/
static void *MMAP_Create(char *testFileName, IOR_param_t * param)
static void *MMAP_Create(char *testFileName, int flags, void * param)
{
int *fd;
fd = POSIX_Create(testFileName, param);
if (ftruncate(*fd, param->expectedAggFileSize) != 0)
fd = POSIX_Create(testFileName, flags, param);
if (ftruncate(*fd, ior_param->expectedAggFileSize) != 0)
ERR("ftruncate() failed");
ior_mmap_file(fd, param);
ior_mmap_file(fd, flags, param);
return ((void *)fd);
}
/*
* Open a file through the POSIX interface and setup mmap.
*/
static void *MMAP_Open(char *testFileName, IOR_param_t * param)
static void *MMAP_Open(char *testFileName, int flags, void * param)
{
int *fd;
fd = POSIX_Open(testFileName, param);
ior_mmap_file(fd, param);
fd = POSIX_Open(testFileName, flags, param);
ior_mmap_file(fd, flags, param);
return ((void *)fd);
}
@ -141,19 +155,19 @@ static void *MMAP_Open(char *testFileName, IOR_param_t * param)
* Write or read access to file using mmap
*/
static IOR_offset_t MMAP_Xfer(int access, void *file, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param)
IOR_offset_t length, void * param)
{
mmap_options_t *o = (mmap_options_t*) param->backend_options;
mmap_options_t *o = (mmap_options_t*) param;
if (access == WRITE) {
memcpy(o->mmap_ptr + param->offset, buffer, length);
memcpy(o->mmap_ptr + ior_param->offset, buffer, length);
} else {
memcpy(buffer, o->mmap_ptr + param->offset, length);
memcpy(buffer, o->mmap_ptr + ior_param->offset, length);
}
if (param->fsyncPerWrite == TRUE) {
if (msync(o->mmap_ptr + param->offset, length, MS_SYNC) != 0)
if (ior_param->fsyncPerWrite == TRUE) {
if (msync(o->mmap_ptr + ior_param->offset, length, MS_SYNC) != 0)
ERR("msync() failed");
if (posix_madvise(o->mmap_ptr + param->offset, length,
if (posix_madvise(o->mmap_ptr + ior_param->offset, length,
POSIX_MADV_DONTNEED) != 0)
ERR("madvise() failed");
}
@ -163,20 +177,20 @@ static IOR_offset_t MMAP_Xfer(int access, void *file, IOR_size_t * buffer,
/*
* Perform msync().
*/
static void MMAP_Fsync(void *fd, IOR_param_t * param)
static void MMAP_Fsync(void *fd, void * param)
{
mmap_options_t *o = (mmap_options_t*) param->backend_options;
if (msync(o->mmap_ptr, param->expectedAggFileSize, MS_SYNC) != 0)
mmap_options_t *o = (mmap_options_t*) param;
if (msync(o->mmap_ptr, ior_param->expectedAggFileSize, MS_SYNC) != 0)
EWARN("msync() failed");
}
/*
* Close a file through the POSIX interface, after tear down the mmap.
*/
static void MMAP_Close(void *fd, IOR_param_t * param)
static void MMAP_Close(void *fd, void * param)
{
mmap_options_t *o = (mmap_options_t*) param->backend_options;
if (munmap(o->mmap_ptr, param->expectedAggFileSize) != 0)
mmap_options_t *o = (mmap_options_t*) param;
if (munmap(o->mmap_ptr, ior_param->expectedAggFileSize) != 0)
ERR("munmap failed");
o->mmap_ptr = NULL;
POSIX_Close(fd, param);

View File

@ -31,23 +31,61 @@
/**************************** P R O T O T Y P E S *****************************/
static IOR_offset_t SeekOffset(MPI_File, IOR_offset_t, IOR_param_t *);
static IOR_offset_t SeekOffset(MPI_File, IOR_offset_t, void *);
static void *MPIIO_Create(char *, IOR_param_t *);
static void *MPIIO_Open(char *, IOR_param_t *);
static void *MPIIO_Create(char *, int iorflags, void *);
static void *MPIIO_Open(char *, int flags, void *);
static IOR_offset_t MPIIO_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void MPIIO_Close(void *, IOR_param_t *);
IOR_offset_t, void *);
static void MPIIO_Close(void *, void *);
static char* MPIIO_GetVersion();
static void MPIIO_Fsync(void *, IOR_param_t *);
static void MPIIO_Fsync(void *, void *);
static void MPIIO_init_xfer_options(IOR_param_t * params);
static int MPIIO_check_params(void * options);
/************************** D E C L A R A T I O N S ***************************/
typedef struct {
int dry_run;
int showHints; /* show hints */
int useFileView; /* use MPI_File_set_view */
int preallocate; /* preallocate file size */
int useSharedFilePointer; /* use shared file pointer */
int useStridedDatatype; /* put strided access into datatype */
char * hintsFileName; /* full name for hints file */
} mpiio_options_t;
static option_help * MPIIO_options(void ** init_backend_options, void * init_values){
mpiio_options_t * o = malloc(sizeof(mpiio_options_t));
if (init_values != NULL){
memcpy(o, init_values, sizeof(mpiio_options_t));
}else{
memset(o, 0, sizeof(mpiio_options_t));
}
*init_backend_options = o;
option_help h [] = {
{0, "mpiio.dryRun", "Dry run, disable actual IO", OPTION_FLAG, 'd', & o->dry_run},
{0, "mpiio.hintsFileName","Full name for hints file", OPTION_OPTIONAL_ARGUMENT, 's', & o->hintsFileName},
{0, "mpiio.showHints", "Show MPI hints", OPTION_FLAG, 'd', & o->showHints},
{0, "mpiio.preallocate", "Preallocate file size", OPTION_FLAG, 'd', & o->preallocate},
{0, "mpiio.useStridedDatatype", "put strided access into datatype [not working]", OPTION_FLAG, 'd', & o->useStridedDatatype},
//{'P', NULL, "useSharedFilePointer -- use shared file pointer [not working]", OPTION_FLAG, 'd', & params->useSharedFilePointer},
{0, "mpiio.useFileView", "Use MPI_File_set_view", OPTION_FLAG, 'd', & o->useFileView},
LAST_OPTION
};
option_help * help = malloc(sizeof(h));
memcpy(help, h, sizeof(h));
return help;
}
ior_aiori_t mpiio_aiori = {
.name = "MPIIO",
.name_legacy = NULL,
.create = MPIIO_Create,
.get_options = MPIIO_options,
.init_xfer_options = MPIIO_init_xfer_options,
.open = MPIIO_Open,
.xfer = MPIIO_Xfer,
.close = MPIIO_Close,
@ -60,16 +98,46 @@ ior_aiori_t mpiio_aiori = {
.rmdir = aiori_posix_rmdir,
.access = MPIIO_Access,
.stat = aiori_posix_stat,
.check_params = MPIIO_check_params
};
/***************************** F U N C T I O N S ******************************/
static IOR_param_t * ior_param = NULL;
static void MPIIO_init_xfer_options(IOR_param_t * params){
ior_param = params;
}
static int MPIIO_check_params(void * module_options){
mpiio_options_t * param = (mpiio_options_t*) module_options;
if ((param->useFileView == TRUE)
&& (sizeof(MPI_Aint) < 8) /* used for 64-bit datatypes */
&&((ior_param->numTasks * ior_param->blockSize) >
(2 * (IOR_offset_t) GIBIBYTE)))
ERR("segment size must be < 2GiB");
if (param->useSharedFilePointer)
ERR("shared file pointer not implemented");
if (param->useStridedDatatype)
ERR("strided datatype not implemented");
if (param->useStridedDatatype && (ior_param->blockSize < sizeof(IOR_size_t)
|| ior_param->transferSize <
sizeof(IOR_size_t)))
ERR("need larger file size for strided datatype in MPIIO");
if (ior_param->randomOffset && ior_param->collective)
ERR("random offset not available with collective MPIIO");
if (ior_param->randomOffset && param->useFileView)
ERR("random offset not available with MPIIO fileviews");
return 0;
}
/*
* Try to access a file through the MPIIO interface.
*/
int MPIIO_Access(const char *path, int mode, IOR_param_t *param)
int MPIIO_Access(const char *path, int mode, void *module_options)
{
if(param->dryRun){
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(param->dry_run){
return MPI_SUCCESS;
}
MPI_File fd;
@ -98,23 +166,21 @@ int MPIIO_Access(const char *path, int mode, IOR_param_t *param)
/*
* Create and open a file through the MPIIO interface.
*/
static void *MPIIO_Create(char *testFileName, IOR_param_t * param)
static void *MPIIO_Create(char *testFileName, int iorflags, void * module_options)
{
if(param->dryRun){
return 0;
}
return MPIIO_Open(testFileName, param);
return MPIIO_Open(testFileName, iorflags, module_options);
}
/*
* Open a file through the MPIIO interface. Setup file view.
*/
static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
static void *MPIIO_Open(char *testFileName, int flags, void * module_options)
{
mpiio_options_t * param = (mpiio_options_t*) module_options;
int fd_mode = (int)0,
offsetFactor,
tasksPerFile,
transfersPerBlock = param->blockSize / param->transferSize;
transfersPerBlock = ior_param->blockSize / ior_param->transferSize;
struct fileTypeStruct {
int globalSizes[2], localSizes[2], startIndices[2];
} fileTypeStruct;
@ -130,28 +196,28 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
/* set IOR file flags to MPIIO flags */
/* -- file open flags -- */
if (param->openFlags & IOR_RDONLY) {
if (flags & IOR_RDONLY) {
fd_mode |= MPI_MODE_RDONLY;
}
if (param->openFlags & IOR_WRONLY) {
if (flags & IOR_WRONLY) {
fd_mode |= MPI_MODE_WRONLY;
}
if (param->openFlags & IOR_RDWR) {
if (flags & IOR_RDWR) {
fd_mode |= MPI_MODE_RDWR;
}
if (param->openFlags & IOR_APPEND) {
if (flags & IOR_APPEND) {
fd_mode |= MPI_MODE_APPEND;
}
if (param->openFlags & IOR_CREAT) {
if (flags & IOR_CREAT) {
fd_mode |= MPI_MODE_CREATE;
}
if (param->openFlags & IOR_EXCL) {
if (flags & IOR_EXCL) {
fd_mode |= MPI_MODE_EXCL;
}
if (param->openFlags & IOR_TRUNC) {
if (flags & IOR_TRUNC) {
fprintf(stdout, "File truncation not implemented in MPIIO\n");
}
if (param->openFlags & IOR_DIRECT) {
if (flags & IOR_DIRECT) {
fprintf(stdout, "O_DIRECT not implemented in MPIIO\n");
}
@ -162,7 +228,7 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
*/
fd_mode |= MPI_MODE_UNIQUE_OPEN;
if (param->filePerProc) {
if (ior_param->filePerProc) {
comm = MPI_COMM_SELF;
} else {
comm = testComm;
@ -181,13 +247,13 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
if(! param->dryRun){
if(! param->dry_run){
MPI_CHECKF(MPI_File_open(comm, testFileName, fd_mode, mpiHints, fd),
"cannot open file: %s", testFileName);
}
/* show hints actually attached to file handle */
if (rank == 0 && param->showHints && ! param->dryRun) {
if (rank == 0 && param->showHints && ! param->dry_run) {
if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "MPI_Info_free failed");
MPI_CHECK(MPI_File_get_info(*fd, &mpiHints),
@ -198,29 +264,29 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
}
/* preallocate space for file */
if (param->preallocate && param->open == WRITE && ! param->dryRun) {
if (param->preallocate && ior_param->open == WRITE && ! param->dry_run) {
MPI_CHECK(MPI_File_preallocate(*fd,
(MPI_Offset) (param->segmentCount
(MPI_Offset) (ior_param->segmentCount
*
param->blockSize *
param->numTasks)),
ior_param->blockSize *
ior_param->numTasks)),
"cannot preallocate file");
}
/* create file view */
if (param->useFileView) {
/* create contiguous transfer datatype */
MPI_CHECK(MPI_Type_contiguous
(param->transferSize / sizeof(IOR_size_t),
MPI_LONG_LONG_INT, &param->transferType),
(ior_param->transferSize / sizeof(IOR_size_t),
MPI_LONG_LONG_INT, &ior_param->transferType),
"cannot create contiguous datatype");
MPI_CHECK(MPI_Type_commit(&param->transferType),
MPI_CHECK(MPI_Type_commit(&ior_param->transferType),
"cannot commit datatype");
if (param->filePerProc) {
if (ior_param->filePerProc) {
offsetFactor = 0;
tasksPerFile = 1;
} else {
offsetFactor = (rank + rankOffset) % param->numTasks;
tasksPerFile = param->numTasks;
offsetFactor = (rank + rankOffset) % ior_param->numTasks;
tasksPerFile = ior_param->numTasks;
}
/*
@ -239,15 +305,15 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
(2, fileTypeStruct.globalSizes,
fileTypeStruct.localSizes,
fileTypeStruct.startIndices, MPI_ORDER_C,
param->transferType, &param->fileType),
ior_param->transferType, &ior_param->fileType),
"cannot create subarray");
MPI_CHECK(MPI_Type_commit(&param->fileType),
MPI_CHECK(MPI_Type_commit(&ior_param->fileType),
"cannot commit datatype");
if(! param->dryRun){
if(! param->dry_run){
MPI_CHECK(MPI_File_set_view(*fd, (MPI_Offset) 0,
param->transferType,
param->fileType, "native",
ior_param->transferType,
ior_param->fileType, "native",
(MPI_Info) MPI_INFO_NULL),
"cannot set file view");
}
@ -261,14 +327,14 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
* Write or read access to file using the MPIIO interface.
*/
static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param)
IOR_offset_t length, void * module_options)
{
/* NOTE: The second arg is (void *) for reads, and (const void *)
for writes. Therefore, one of the two sets of assignments below
will get "assignment from incompatible pointer-type" warnings,
if we only use this one set of signatures. */
if(param->dryRun)
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(param->dry_run)
return length;
int (MPIAPI * Access) (MPI_File, void *, int,
@ -319,7 +385,7 @@ static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer,
*/
if (param->useFileView) {
/* find offset in file */
if (SeekOffset(*(MPI_File *) fd, param->offset, param) <
if (SeekOffset(*(MPI_File *) fd, ior_param->offset, param) <
0) {
/* if unsuccessful */
length = -1;
@ -331,24 +397,24 @@ static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer,
* e.g., 'IOR -s 2 -b 32K -t 32K -a MPIIO -S'
*/
if (param->useStridedDatatype) {
length = param->segmentCount;
length = ior_param->segmentCount;
} else {
length = 1;
}
if (param->collective) {
if (ior_param->collective) {
/* individual, collective call */
MPI_CHECK(Access_all
(*(MPI_File *) fd, buffer, length,
param->transferType, &status),
ior_param->transferType, &status),
"cannot access collective");
} else {
/* individual, noncollective call */
MPI_CHECK(Access
(*(MPI_File *) fd, buffer, length,
param->transferType, &status),
ior_param->transferType, &status),
"cannot access noncollective");
}
length *= param->transferSize; /* for return value in bytes */
length *= ior_param->transferSize; /* for return value in bytes */
}
} else {
/*
@ -358,7 +424,7 @@ static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer,
if (param->useSharedFilePointer) {
/* find offset in file */
if (SeekOffset
(*(MPI_File *) fd, param->offset, param) < 0) {
(*(MPI_File *) fd, ior_param->offset, param) < 0) {
/* if unsuccessful */
length = -1;
} else {
@ -374,32 +440,31 @@ static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer,
"useSharedFilePointer not implemented\n");
}
} else {
if (param->collective) {
if (ior_param->collective) {
/* explicit, collective call */
MPI_CHECK(Access_at_all
(*(MPI_File *) fd, param->offset,
(*(MPI_File *) fd, ior_param->offset,
buffer, length, MPI_BYTE, &status),
"cannot access explicit, collective");
} else {
/* explicit, noncollective call */
MPI_CHECK(Access_at
(*(MPI_File *) fd, param->offset,
(*(MPI_File *) fd, ior_param->offset,
buffer, length, MPI_BYTE, &status),
"cannot access explicit, noncollective");
}
}
}
if((access == WRITE) && (param->fsyncPerWrite == TRUE))
MPIIO_Fsync(fd, param);
return (length);
}
/*
* Perform fsync().
*/
static void MPIIO_Fsync(void *fdp, IOR_param_t * param)
static void MPIIO_Fsync(void *fdp, void * module_options)
{
if(param->dryRun)
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(param->dry_run)
return;
if (MPI_File_sync(*(MPI_File *)fdp) != MPI_SUCCESS)
EWARN("fsync() failed");
@ -408,29 +473,31 @@ static void MPIIO_Fsync(void *fdp, IOR_param_t * param)
/*
* Close a file through the MPIIO interface.
*/
static void MPIIO_Close(void *fd, IOR_param_t * param)
static void MPIIO_Close(void *fd, void * module_options)
{
if(! param->dryRun){
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(! param->dry_run){
MPI_CHECK(MPI_File_close((MPI_File *) fd), "cannot close file");
}
if ((param->useFileView == TRUE) && (param->fd_fppReadCheck == NULL)) {
/*
* need to free the datatype, so done in the close process
*/
MPI_CHECK(MPI_Type_free(&param->fileType),
"cannot free MPI file datatype");
MPI_CHECK(MPI_Type_free(&param->transferType),
"cannot free MPI transfer datatype");
}
//if ((param->useFileView == TRUE) && (param->fd_fppReadCheck == NULL)) {
// /*
// * need to free the datatype, so done in the close process
// */
// MPI_CHECK(MPI_Type_free(&param->fileType),
// "cannot free MPI file datatype");
// MPI_CHECK(MPI_Type_free(&param->transferType),
// "cannot free MPI transfer datatype");
//}
free(fd);
}
/*
* Delete a file through the MPIIO interface.
*/
void MPIIO_Delete(char *testFileName, IOR_param_t * param)
void MPIIO_Delete(char *testFileName, void * module_options)
{
if(param->dryRun)
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(param->dry_run)
return;
MPI_CHECKF(MPI_File_delete(testFileName, (MPI_Info) MPI_INFO_NULL),
"cannot delete file: %s", testFileName);
@ -452,36 +519,37 @@ static char* MPIIO_GetVersion()
* Seek to offset in file using the MPIIO interface.
*/
static IOR_offset_t SeekOffset(MPI_File fd, IOR_offset_t offset,
IOR_param_t * param)
void * module_options)
{
mpiio_options_t * param = (mpiio_options_t*) module_options;
int offsetFactor, tasksPerFile;
IOR_offset_t tempOffset;
tempOffset = offset;
if (param->filePerProc) {
if (ior_param->filePerProc) {
offsetFactor = 0;
tasksPerFile = 1;
} else {
offsetFactor = (rank + rankOffset) % param->numTasks;
tasksPerFile = param->numTasks;
offsetFactor = (rank + rankOffset) % ior_param->numTasks;
tasksPerFile = ior_param->numTasks;
}
if (param->useFileView) {
/* recall that offsets in a file view are
counted in units of transfer size */
if (param->filePerProc) {
tempOffset = tempOffset / param->transferSize;
if (ior_param->filePerProc) {
tempOffset = tempOffset / ior_param->transferSize;
} else {
/*
* this formula finds a file view offset for a task
* from an absolute offset
*/
tempOffset = ((param->blockSize / param->transferSize)
tempOffset = ((ior_param->blockSize / ior_param->transferSize)
* (tempOffset /
(param->blockSize * tasksPerFile)))
+ (((tempOffset % (param->blockSize * tasksPerFile))
- (offsetFactor * param->blockSize))
/ param->transferSize);
(ior_param->blockSize * tasksPerFile)))
+ (((tempOffset % (ior_param->blockSize * tasksPerFile))
- (offsetFactor * ior_param->blockSize))
/ ior_param->transferSize);
}
}
MPI_CHECK(MPI_File_seek(fd, tempOffset, MPI_SEEK_SET),
@ -493,17 +561,18 @@ static IOR_offset_t SeekOffset(MPI_File fd, IOR_offset_t offset,
* Use MPI_File_get_size() to return aggregate file size.
* NOTE: This function is used by the HDF5 and NCMPI backends.
*/
IOR_offset_t MPIIO_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
IOR_offset_t MPIIO_GetFileSize(void * module_options, MPI_Comm testComm,
char *testFileName)
{
if(test->dryRun)
mpiio_options_t * test = (mpiio_options_t*) module_options;
if(test->dry_run)
return 0;
IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum;
MPI_File fd;
MPI_Comm comm;
MPI_Info mpiHints = MPI_INFO_NULL;
if (test->filePerProc == TRUE) {
if (ior_param->filePerProc == TRUE) {
comm = MPI_COMM_SELF;
} else {
comm = testComm;
@ -519,7 +588,7 @@ IOR_offset_t MPIIO_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "MPI_Info_free failed");
if (test->filePerProc == TRUE) {
if (ior_param->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved");

View File

@ -69,9 +69,11 @@
/**************************** P R O T O T Y P E S *****************************/
static IOR_offset_t POSIX_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void POSIX_Fsync(void *, IOR_param_t *);
static void POSIX_Sync(IOR_param_t * );
IOR_offset_t, void *);
static void POSIX_Fsync(void *, void *);
static void POSIX_Sync(void * );
static void POSIX_init_xfer_options(IOR_param_t * params);
/************************** O P T I O N S *****************************/
typedef struct{
@ -113,6 +115,7 @@ ior_aiori_t posix_aiori = {
.xfer = POSIX_Xfer,
.close = POSIX_Close,
.delete = POSIX_Delete,
.init_xfer_options = POSIX_init_xfer_options,
.get_version = aiori_get_version,
.fsync = POSIX_Fsync,
.get_file_size = POSIX_GetFileSize,
@ -128,6 +131,11 @@ ior_aiori_t posix_aiori = {
/***************************** F U N C T I O N S ******************************/
static IOR_param_t * ior_param = NULL;
static void POSIX_init_xfer_options(IOR_param_t * params){
ior_param = params;
}
#ifdef HAVE_GPFS_FCNTL_H
void gpfs_free_all_locks(int fd)
@ -151,7 +159,7 @@ void gpfs_free_all_locks(int fd)
EWARNF("gpfs_fcntl(%d, ...) release all locks hint failed.", fd);
}
}
void gpfs_access_start(int fd, IOR_offset_t length, IOR_param_t *param, int access)
void gpfs_access_start(int fd, IOR_offset_t length, void *param, int access)
{
int rc;
struct {
@ -175,7 +183,7 @@ void gpfs_access_start(int fd, IOR_offset_t length, IOR_param_t *param, int acce
}
}
void gpfs_access_end(int fd, IOR_offset_t length, IOR_param_t *param, int access)
void gpfs_access_end(int fd, IOR_offset_t length, void *param, int access)
{
int rc;
struct {
@ -318,7 +326,7 @@ bool beegfs_createFilePath(char* filepath, mode_t mode, int numTargets, int chun
/*
* Creat and open a file through the POSIX interface.
*/
void *POSIX_Create(char *testFileName, IOR_param_t * param)
void *POSIX_Create(char *testFileName, int flags, void * param)
{
int fd_oflag = O_BINARY;
int mode = 0664;
@ -327,12 +335,12 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
fd = (int *)malloc(sizeof(int));
if (fd == NULL)
ERR("Unable to malloc file descriptor");
posix_options_t * o = (posix_options_t*) param->backend_options;
posix_options_t * o = (posix_options_t*) param;
if (o->direct_io == TRUE){
set_o_direct_flag(&fd_oflag);
}
if(param->dryRun)
if(ior_param->dryRun)
return 0;
#ifdef HAVE_LUSTRE_LUSTRE_USER_H
@ -450,7 +458,7 @@ int POSIX_Mknod(char *testFileName)
/*
* Open a file through the POSIX interface.
*/
void *POSIX_Open(char *testFileName, IOR_param_t * param)
void *POSIX_Open(char *testFileName, int flags, void * param)
{
int fd_oflag = O_BINARY;
int *fd;
@ -459,13 +467,13 @@ void *POSIX_Open(char *testFileName, IOR_param_t * param)
if (fd == NULL)
ERR("Unable to malloc file descriptor");
posix_options_t * o = (posix_options_t*) param->backend_options;
posix_options_t * o = (posix_options_t*) param;
if (o->direct_io == TRUE)
set_o_direct_flag(&fd_oflag);
fd_oflag |= O_RDWR;
if(param->dryRun)
if(ior_param->dryRun)
return 0;
*fd = open64(testFileName, fd_oflag);
@ -496,7 +504,7 @@ void *POSIX_Open(char *testFileName, IOR_param_t * param)
* Write or read access to file using the POSIX interface.
*/
static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param)
IOR_offset_t length, void * param)
{
int xferRetries = 0;
long long remaining = (long long)length;
@ -504,7 +512,7 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
long long rc;
int fd;
if(param->dryRun)
if(ior_param->dryRun)
return length;
fd = *(int *)file;
@ -517,8 +525,8 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
/* seek to offset */
if (lseek64(fd, param->offset, SEEK_SET) == -1)
ERRF("lseek64(%d, %lld, SEEK_SET) failed", fd, param->offset);
if (lseek64(fd, ior_param->offset, SEEK_SET) == -1)
ERRF("lseek64(%d, %lld, SEEK_SET) failed", fd, ior_param->offset);
while (remaining > 0) {
/* write/read file */
@ -527,20 +535,20 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
fprintf(stdout,
"task %d writing to offset %lld\n",
rank,
param->offset + length - remaining);
ior_param->offset + length - remaining);
}
rc = write(fd, ptr, remaining);
if (rc == -1)
ERRF("write(%d, %p, %lld) failed",
fd, (void*)ptr, remaining);
if (param->fsyncPerWrite == TRUE)
if (ior_param->fsyncPerWrite == TRUE)
POSIX_Fsync(&fd, param);
} else { /* READ or CHECK */
if (verbose >= VERBOSE_4) {
fprintf(stdout,
"task %d reading from offset %lld\n",
rank,
param->offset + length - remaining);
ior_param->offset + length - remaining);
}
rc = read(fd, ptr, remaining);
if (rc == 0)
@ -556,8 +564,8 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
rank,
access == WRITE ? "write()" : "read()",
rc, remaining,
param->offset + length - remaining);
if (param->singleXferAttempt == TRUE)
ior_param->offset + length - remaining);
if (ior_param->singleXferAttempt == TRUE)
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1),
"barrier error");
if (xferRetries > MAX_RETRY)
@ -580,14 +588,14 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
/*
* Perform fsync().
*/
static void POSIX_Fsync(void *fd, IOR_param_t * param)
static void POSIX_Fsync(void *fd, void * param)
{
if (fsync(*(int *)fd) != 0)
EWARNF("fsync(%d) failed", *(int *)fd);
}
static void POSIX_Sync(IOR_param_t * param)
static void POSIX_Sync(void * param)
{
int ret = system("sync");
if (ret != 0){
@ -599,9 +607,9 @@ static void POSIX_Sync(IOR_param_t * param)
/*
* Close a file through the POSIX interface.
*/
void POSIX_Close(void *fd, IOR_param_t * param)
void POSIX_Close(void *fd, void * param)
{
if(param->dryRun)
if(ior_param->dryRun)
return;
if (close(*(int *)fd) != 0)
ERRF("close(%d) failed", *(int *)fd);
@ -611,9 +619,9 @@ void POSIX_Close(void *fd, IOR_param_t * param)
/*
* Delete a file through the POSIX interface.
*/
void POSIX_Delete(char *testFileName, IOR_param_t * param)
void POSIX_Delete(char *testFileName, void * param)
{
if(param->dryRun)
if(ior_param->dryRun)
return;
if (unlink(testFileName) != 0){
EWARNF("[RANK %03d]: unlink() of file \"%s\" failed\n",
@ -624,10 +632,10 @@ void POSIX_Delete(char *testFileName, IOR_param_t * param)
/*
* Use POSIX stat() to return aggregate file size.
*/
IOR_offset_t POSIX_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
IOR_offset_t POSIX_GetFileSize(void * test, MPI_Comm testComm,
char *testFileName)
{
if(test->dryRun)
if(ior_param->dryRun)
return 0;
struct stat stat_buf;
IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum;
@ -637,7 +645,7 @@ IOR_offset_t POSIX_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
}
aggFileSizeFromStat = stat_buf.st_size;
if (test->filePerProc == TRUE) {
if (ior_param->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved");

View File

@ -157,8 +157,8 @@ static void EMC_Close(void*, IOR_param_t*);
static void S3_Delete(char*, IOR_param_t*);
static void S3_Fsync(void*, IOR_param_t*);
static IOR_offset_t S3_GetFileSize(IOR_param_t*, MPI_Comm, char*);
static void S3_init();
static void S3_finalize();
static void S3_init(void * options);
static void S3_finalize(void * options);
static int S3_check_params(IOR_param_t *);
@ -218,14 +218,14 @@ ior_aiori_t s3_emc_aiori = {
};
static void S3_init(){
static void S3_init(void * options){
/* This is supposed to be done before *any* threads are created.
* Could MPI_Init() create threads (or call multi-threaded
* libraries)? We'll assume so. */
AWS4C_CHECK( aws_init() );
}
static void S3_finalize(){
static void S3_finalize(void * options){
/* done once per program, after exiting all threads.
* NOTE: This fn doesn't return a value that can be checked for success. */
aws_cleanup();
@ -241,10 +241,10 @@ static int S3_check_params(IOR_param_t * test){
if (Nto1 && (s != 1) && (b != t)) {
ERR("N:1 (strided) requires xfer-size == block-size");
return 0;
return 1;
}
return 1;
return 0;
}
/* modelled on similar macros in iordef.h */

View File

@ -152,7 +152,7 @@ void aiori_supported_apis(char * APIs, char * APIs_legacy, enum bench_type type)
* This function provides a AIORI statfs for POSIX-compliant filesystems. It
* uses statvfs is available and falls back on statfs.
*/
int aiori_posix_statfs (const char *path, ior_aiori_statfs_t *stat_buf, IOR_param_t * param)
int aiori_posix_statfs (const char *path, ior_aiori_statfs_t *stat_buf, void * module_options)
{
int ret;
#if defined(HAVE_STATVFS)
@ -177,22 +177,22 @@ int aiori_posix_statfs (const char *path, ior_aiori_statfs_t *stat_buf, IOR_para
return 0;
}
int aiori_posix_mkdir (const char *path, mode_t mode, IOR_param_t * param)
int aiori_posix_mkdir (const char *path, mode_t mode, void * module_options)
{
return mkdir (path, mode);
}
int aiori_posix_rmdir (const char *path, IOR_param_t * param)
int aiori_posix_rmdir (const char *path, void * module_options)
{
return rmdir (path);
}
int aiori_posix_access (const char *path, int mode, IOR_param_t * param)
int aiori_posix_access (const char *path, int mode, void * module_options)
{
return access (path, mode);
}
int aiori_posix_stat (const char *path, struct stat *buf, IOR_param_t * param)
int aiori_posix_stat (const char *path, struct stat *buf, void * module_options)
{
return stat (path, buf);
}
@ -202,92 +202,6 @@ char* aiori_get_version()
return "";
}
static bool is_initialized = false;
static void init_or_fini_internal(const ior_aiori_t *test_backend,
const bool init)
{
if (init)
{
if (test_backend->initialize)
test_backend->initialize();
}
else
{
if (test_backend->finalize)
test_backend->finalize();
}
}
static void init_or_fini(IOR_test_t *tests, const bool init)
{
/* Sanity check, we were compiled with SOME backend, right? */
if (0 == aiori_count ()) {
ERR("No IO backends compiled into aiori. "
"Run 'configure --with-<backend>', and recompile.");
}
/* Pointer to the initialize of finalize function */
/* if tests is NULL, initialize or finalize all available backends */
if (tests == NULL)
{
for (ior_aiori_t **tmp = available_aiori ; *tmp != NULL; ++tmp)
init_or_fini_internal(*tmp, init);
return;
}
for (IOR_test_t *t = tests; t != NULL; t = t->next)
{
IOR_param_t *params = &t->params;
assert(params != NULL);
const ior_aiori_t *test_backend = params->backend;
assert(test_backend != NULL);
init_or_fini_internal(test_backend, init);
}
}
/**
* Initialize IO backends.
*
* @param[in] tests Pointers to the first test
*
* This function initializes all backends which will be used. If tests is NULL
* all available backends are initialized.
*/
void aiori_initialize(IOR_test_t *tests)
{
if (is_initialized)
return;
init_or_fini(tests, true);
is_initialized = true;
}
/**
* Finalize IO backends.
*
* @param[in] tests Pointers to the first test
*
* This function finalizes all backends which were used. If tests is NULL
* all available backends are finialized.
*/
void aiori_finalize(IOR_test_t *tests)
{
if (!is_initialized)
return;
is_initialized = false;
init_or_fini(tests, false);
}
const ior_aiori_t *aiori_select (const char *api)
{
char warn_str[256] = {0};

View File

@ -67,27 +67,31 @@ typedef struct ior_aiori_statfs {
typedef struct ior_aiori {
char *name;
char *name_legacy;
void *(*create)(char *, IOR_param_t *);
void *(*create)(char *, int iorflags, void *);
int (*mknod)(char *);
void *(*open)(char *, IOR_param_t *);
void *(*open)(char *, int iorflags, void *);
/*
Allow to set generic transfer options that shall be applied to any subsequent IO call.
*/
void (*init_xfer_options)(IOR_param_t * params);
IOR_offset_t (*xfer)(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
void (*close)(void *, IOR_param_t *);
void (*delete)(char *, IOR_param_t *);
IOR_offset_t, void *);
void (*close)(void *, void *);
void (*delete)(char *, void *);
char* (*get_version)(void);
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);
void (*initialize)(void); /* called once per program before MPI is started */
void (*finalize)(void); /* called once per program after MPI is shutdown */
void (*fsync)(void *, void *);
IOR_offset_t (*get_file_size)(void * module_options, MPI_Comm, char *);
int (*statfs) (const char *, ior_aiori_statfs_t *, void * module_options);
int (*mkdir) (const char *path, mode_t mode, void * module_options);
int (*rmdir) (const char *path, void * module_options);
int (*access) (const char *path, int mode, void * module_options);
int (*stat) (const char *path, struct stat *buf, void * module_options);
void (*initialize)(void * options); /* called once per program before MPI is started */
void (*finalize)(void * options); /* called once per program after MPI is shutdown */
option_help * (*get_options)(void ** init_backend_options, void* init_values); /* initializes the backend options as well and returns the pointer to the option help structure */
bool enable_mdtest;
int (*check_params)(IOR_param_t *); /* check if the provided parameters for the given test and the module options are correct, if they aren't print a message and exit(1) or return 1*/
void (*sync)(IOR_param_t * ); /* synchronize every pending operation for this storage */
int (*check_params)(void *); /* check if the provided module_optionseters for the given test and the module options are correct, if they aren't print a message and exit(1) or return 1*/
void (*sync)(void * ); /* synchronize every pending operation for this storage */
} ior_aiori_t;
enum bench_type {
@ -112,8 +116,6 @@ extern ior_aiori_t rados_aiori;
extern ior_aiori_t cephfs_aiori;
extern ior_aiori_t gfarm_aiori;
void aiori_initialize(IOR_test_t * tests);
void aiori_finalize(IOR_test_t * tests);
const ior_aiori_t *aiori_select (const char *api);
int aiori_count (void);
void aiori_supported_apis(char * APIs, char * APIs_legacy, enum bench_type type);
@ -125,25 +127,25 @@ const char *aiori_default (void);
/* some generic POSIX-based backend calls */
char * aiori_get_version (void);
int aiori_posix_statfs (const char *path, ior_aiori_statfs_t *stat_buf, IOR_param_t * param);
int aiori_posix_mkdir (const char *path, mode_t mode, IOR_param_t * param);
int aiori_posix_rmdir (const char *path, IOR_param_t * param);
int aiori_posix_access (const char *path, int mode, IOR_param_t * param);
int aiori_posix_stat (const char *path, struct stat *buf, IOR_param_t * param);
int aiori_posix_statfs (const char *path, ior_aiori_statfs_t *stat_buf, void * module_options);
int aiori_posix_mkdir (const char *path, mode_t mode, void * module_options);
int aiori_posix_rmdir (const char *path, void * module_options);
int aiori_posix_access (const char *path, int mode, void * module_options);
int aiori_posix_stat (const char *path, struct stat *buf, void * module_options);
void *POSIX_Create(char *testFileName, IOR_param_t * param);
void *POSIX_Create(char *testFileName, int flags, void * module_options);
int POSIX_Mknod(char *testFileName);
void *POSIX_Open(char *testFileName, IOR_param_t * param);
IOR_offset_t POSIX_GetFileSize(IOR_param_t * test, MPI_Comm testComm, char *testFileName);
void POSIX_Delete(char *testFileName, IOR_param_t * param);
void POSIX_Close(void *fd, IOR_param_t * param);
void *POSIX_Open(char *testFileName, int flags, void * module_options);
IOR_offset_t POSIX_GetFileSize(void * test, MPI_Comm testComm, char *testFileName);
void POSIX_Delete(char *testFileName, void * module_options);
void POSIX_Close(void *fd, void * module_options);
option_help * POSIX_options(void ** init_backend_options, void * init_values);
/* NOTE: these 3 MPI-IO functions are exported for reuse by HDF5/PNetCDF */
void MPIIO_Delete(char *testFileName, IOR_param_t * param);
IOR_offset_t MPIIO_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
void MPIIO_Delete(char *testFileName, void * module_options);
IOR_offset_t MPIIO_GetFileSize(void * test, MPI_Comm testComm,
char *testFileName);
int MPIIO_Access(const char *, int, IOR_param_t *);
int MPIIO_Access(const char *, int, void *);
#endif /* not _AIORI_H */

View File

@ -337,7 +337,6 @@ void ShowTestStart(IOR_param_t *test)
PrintKeyVal("api", test->api);
PrintKeyVal("platform", test->platform);
PrintKeyVal("testFileName", test->testFileName);
PrintKeyVal("hintsFileName", test->hintsFileName);
PrintKeyValInt("deadlineForStonewall", test->deadlineForStonewalling);
PrintKeyValInt("stoneWallingWearOut", test->stoneWallingWearOut);
PrintKeyValInt("maxTimeDuration", test->maxTimeDuration);
@ -355,7 +354,6 @@ void ShowTestStart(IOR_param_t *test)
PrintKeyValInt("fsync", test->fsync);
PrintKeyValInt("fsyncperwrite", test->fsyncPerWrite);
PrintKeyValInt("useExistingTestFile", test->useExistingTestFile);
PrintKeyValInt("showHints", test->showHints);
PrintKeyValInt("uniqueDir", test->uniqueDir);
PrintKeyValInt("individualDataSets", test->individualDataSets);
PrintKeyValInt("singleXferAttempt", test->singleXferAttempt);
@ -368,12 +366,8 @@ void ShowTestStart(IOR_param_t *test)
PrintKeyValInt("randomOffset", test->randomOffset);
PrintKeyValInt("checkWrite", test->checkWrite);
PrintKeyValInt("checkRead", test->checkRead);
PrintKeyValInt("preallocate", test->preallocate);
PrintKeyValInt("useFileView", test->useFileView);
PrintKeyValInt("setAlignment", test->setAlignment);
PrintKeyValInt("storeFileOffset", test->storeFileOffset);
PrintKeyValInt("useSharedFilePointer", test->useSharedFilePointer);
PrintKeyValInt("useStridedDatatype", test->useStridedDatatype);
PrintKeyValInt("keepFile", test->keepFile);
PrintKeyValInt("keepFileWithError", test->keepFileWithError);
PrintKeyValInt("quitOnError", test->quitOnError);

108
src/ior.c
View File

@ -58,6 +58,28 @@ static IOR_offset_t WriteOrRead(IOR_param_t *test, IOR_results_t *results,
void *fd, const int access,
IOR_io_buffers *ioBuffers);
static void test_initialize(IOR_test_t * test){
verbose = test->params.verbose;
backend = test->params.backend;
if (rank == 0 && verbose >= VERBOSE_0) {
ShowTestStart(& test->params);
}
if(backend->initialize){
backend->initialize(test->params.backend_options);
}
if(backend->init_xfer_options){
backend->init_xfer_options(test);
}
}
static void test_finalize(IOR_test_t * test){
backend = test->params.backend;
if(backend->finalize){
backend->finalize(test->params.backend_options);
}
}
IOR_test_t * ior_run(int argc, char **argv, MPI_Comm world_com, FILE * world_out){
IOR_test_t *tests_head;
IOR_test_t *tptr;
@ -76,17 +98,12 @@ IOR_test_t * ior_run(int argc, char **argv, MPI_Comm world_com, FILE * world_out
/* perform each test */
for (tptr = tests_head; tptr != NULL; tptr = tptr->next) {
aiori_initialize(tptr);
test_initialize(tptr);
totalErrorCount = 0;
verbose = tptr->params.verbose;
backend = tptr->params.backend;
if (rank == 0 && verbose >= VERBOSE_0) {
ShowTestStart(&tptr->params);
}
TestIoSys(tptr);
tptr->results->errors = totalErrorCount;
ShowTestEnd(tptr);
aiori_finalize(tptr);
test_finalize(tptr);
}
PrintLongSummaryAllTests(tests_head);
@ -125,18 +142,11 @@ int ior_main(int argc, char **argv)
InitTests(tests_head, mpi_comm_world);
verbose = tests_head->params.verbose;
aiori_initialize(tests_head); // this is quite suspicious, likely an error when multiple tests need to be executed with different backends and options
PrintHeader(argc, argv);
/* perform each test */
for (tptr = tests_head; tptr != NULL; tptr = tptr->next) {
verbose = tptr->params.verbose;
backend = tptr->params.backend;
if (rank == 0 && verbose >= VERBOSE_0) {
backend = tptr->params.backend;
ShowTestStart(&tptr->params);
}
test_initialize(tptr);
// This is useful for trapping a running MPI process. While
// this is sleeping, run the script 'testing/hdfs/gdb.attach'
@ -148,6 +158,7 @@ int ior_main(int argc, char **argv)
TestIoSys(tptr);
ShowTestEnd(tptr);
test_finalize(tptr);
}
if (verbose < 0)
@ -158,8 +169,6 @@ int ior_main(int argc, char **argv)
/* display finish time */
PrintTestEnds();
aiori_finalize(tests_head);
MPI_CHECK(MPI_Finalize(), "cannot finalize MPI");
DestroyTests(tests_head);
@ -180,10 +189,6 @@ void init_IOR_Param_t(IOR_param_t * p)
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;
p->api = strdup(default_aiori);
p->platform = strdup("HOST(OSTYPE)");
p->testFileName = strdup("testFile");
@ -1338,7 +1343,7 @@ static void TestIoSys(IOR_test_t *test)
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
params->open = WRITE;
timer[0] = GetTimeStamp();
fd = backend->create(testFileName, params);
fd = backend->create(testFileName, IOR_WRONLY | IOR_CREAT, params->backend_options);
timer[1] = GetTimeStamp();
if (params->intraTestBarriers)
MPI_CHECK(MPI_Barrier(testComm),
@ -1412,7 +1417,7 @@ static void TestIoSys(IOR_test_t *test)
GetTestFileName(testFileName, params);
params->open = WRITECHECK;
fd = backend->open(testFileName, params);
fd = backend->open(testFileName, IOR_RDONLY, params);
dataMoved = WriteOrRead(params, &results[rep], fd, WRITECHECK, &ioBuffers);
backend->close(fd, params);
rankOffset = 0;
@ -1484,7 +1489,7 @@ static void TestIoSys(IOR_test_t *test)
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
params->open = READ;
timer[0] = GetTimeStamp();
fd = backend->open(testFileName, params);
fd = backend->open(testFileName, IOR_RDONLY, params);
timer[1] = GetTimeStamp();
if (params->intraTestBarriers)
MPI_CHECK(MPI_Barrier(testComm),
@ -1613,11 +1618,6 @@ static void ValidateTests(IOR_param_t * test)
&& (test->blockSize < sizeof(IOR_size_t)
|| test->transferSize < sizeof(IOR_size_t)))
ERR("block/transfer size may not be smaller than IOR_size_t for NCMPI");
if ((test->useFileView == TRUE)
&& (sizeof(MPI_Aint) < 8) /* used for 64-bit datatypes */
&&((test->numTasks * test->blockSize) >
(2 * (IOR_offset_t) GIBIBYTE)))
ERR("segment size must be < 2GiB");
if ((strcasecmp(test->api, "POSIX") != 0) && test->singleXferAttempt)
WARN_RESET("retry only available in POSIX",
test, &defaults, singleXferAttempt);
@ -1630,39 +1630,6 @@ static void ValidateTests(IOR_param_t * test)
&& (strcasecmp(test->api, "CEPHFS") != 0)) && test->fsync)
WARN_RESET("fsync() not supported in selected backend",
test, &defaults, fsync);
if ((strcasecmp(test->api, "MPIIO") != 0) && test->preallocate)
WARN_RESET("preallocation only available in MPIIO",
test, &defaults, preallocate);
if ((strcasecmp(test->api, "MPIIO") != 0) && test->useFileView)
WARN_RESET("file view only available in MPIIO",
test, &defaults, useFileView);
if ((strcasecmp(test->api, "MPIIO") != 0) && test->useSharedFilePointer)
WARN_RESET("shared file pointer only available in MPIIO",
test, &defaults, useSharedFilePointer);
if ((strcasecmp(test->api, "MPIIO") == 0) && test->useSharedFilePointer)
WARN_RESET("shared file pointer not implemented",
test, &defaults, useSharedFilePointer);
if ((strcasecmp(test->api, "MPIIO") != 0) && test->useStridedDatatype)
WARN_RESET("strided datatype only available in MPIIO",
test, &defaults, useStridedDatatype);
if ((strcasecmp(test->api, "MPIIO") == 0) && test->useStridedDatatype)
WARN_RESET("strided datatype not implemented",
test, &defaults, useStridedDatatype);
if ((strcasecmp(test->api, "MPIIO") == 0)
&& test->useStridedDatatype && (test->blockSize < sizeof(IOR_size_t)
|| test->transferSize <
sizeof(IOR_size_t)))
ERR("need larger file size for strided datatype in MPIIO");
if ((strcasecmp(test->api, "POSIX") == 0) && test->showHints)
WARN_RESET("hints not available in POSIX",
test, &defaults, showHints);
if ((strcasecmp(test->api, "POSIX") == 0) && test->collective)
WARN_RESET("collective not available in POSIX",
test, &defaults, collective);
if ((strcasecmp(test->api, "MMAP") == 0) && test->fsyncPerWrite
&& (test->transferSize & (sysconf(_SC_PAGESIZE) - 1)))
ERR("transfer size must be aligned with PAGESIZE for MMAP with fsyncPerWrite");
/* parameter consitency */
if (test->reorderTasks == TRUE && test->reorderTasksRandom == TRUE)
ERR("Both Constant and Random task re-ordering specified. Choose one and resubmit");
@ -1676,14 +1643,6 @@ static void ValidateTests(IOR_param_t * test)
ERR("random offset not available with read check option (use write check)");
if (test->randomOffset && test->storeFileOffset)
ERR("random offset not available with store file offset option)");
if ((strcasecmp(test->api, "MPIIO") == 0) && test->randomOffset
&& test->collective)
ERR("random offset not available with collective MPIIO");
if ((strcasecmp(test->api, "MPIIO") == 0) && test->randomOffset
&& test->useFileView)
ERR("random offset not available with MPIIO fileviews");
if ((strcasecmp(test->api, "HDF5") == 0) && test->randomOffset)
ERR("random offset not available with HDF5");
if ((strcasecmp(test->api, "NCMPI") == 0) && test->randomOffset)
@ -1719,8 +1678,11 @@ static void ValidateTests(IOR_param_t * test)
/* allow the backend to validate the options */
if(test->backend->check_params){
if(test->backend->init_xfer_options){
test->backend->init_xfer_options(test);
}
int check = test->backend->check_params(test);
if (check == 0){
if (check){
ERR("The backend returned that the test parameters are invalid.");
}
}
@ -1870,9 +1832,11 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
FillBuffer(buffer, test, test->offset, pretendRank);
}
amtXferred =
backend->xfer(access, fd, buffer, transfer, test);
backend->xfer(access, fd, buffer, transfer, test->backend_options);
if (amtXferred != transfer)
ERR("cannot write to file");
if (test->fsyncPerWrite)
backend->fsync(fd, test->backend_options);
if (test->interIODelay > 0){
struct timespec wait = {test->interIODelay / 1000 / 1000, 1000l * (test->interIODelay % 1000000)};
nanosleep( & wait, NULL);

View File

@ -84,17 +84,15 @@ typedef struct
{
const struct ior_aiori * backend;
char * debug; /* debug info string */
unsigned int mode; /* file permissions */
unsigned int openFlags; /* open flags (see also <open>) */
int referenceNumber; /* user supplied reference number */
char * api; /* API for I/O */
char * apiVersion; /* API version */
char * platform; /* platform type */
char * testFileName; /* full name for test */
char * testFileName_fppReadCheck;/* filename for fpp read check */
char * hintsFileName; /* full name for hints file */
char * options; /* options string */
// intermediate options
int collective; /* collective I/O */
int dryRun; /* do not perform any I/Os just run evtl. inputs print dummy output */
int numTasks; /* number of tasks for test */
int numNodes; /* number of nodes for test */
@ -119,17 +117,12 @@ typedef struct
int keepFileWithError; /* don't delete the testfile with errors */
int errorFound; /* error found in data check */
int quitOnError; /* quit code when error in check */
int collective; /* collective I/O */
IOR_offset_t segmentCount; /* number of segments (or HDF5 datasets) */
IOR_offset_t blockSize; /* contiguous bytes to write per task */
IOR_offset_t transferSize; /* size of transfer in bytes */
IOR_offset_t offset; /* offset for read/write */
IOR_offset_t expectedAggFileSize; /* calculated aggregate file size */
int preallocate; /* preallocate file size */
int useFileView; /* use MPI_File_set_view */
int useSharedFilePointer; /* use shared file pointer */
int useStridedDatatype; /* put strided access into datatype */
int showHints; /* show hints */
int summary_every_test; /* flag to print summary every test, not just at end */
int uniqueDir; /* use unique directory for each fpp */
int useExistingTestFile; /* do not delete test file before access */
@ -144,7 +137,6 @@ typedef struct
int verbose; /* verbosity */
int setTimeStampSignature; /* set time stamp signature */
unsigned int timeStampSignatureValue; /* value for time stamp signature */
void * fd_fppReadCheck; /* additional fd for fpp read check */
int randomSeed; /* random seed for write/read check */
unsigned int incompressibleSeed; /* random seed for incompressible file creation */
int randomOffset; /* access is to random offsets */

View File

@ -355,8 +355,6 @@ static void create_file (const char *path, uint64_t itemNum) {
sprintf(curr_item, "%s/file.%s"LLU"", path, mk_name, itemNum);
VERBOSE(3,5,"create_remove_items_helper (non-dirs create): curr_item is '%s'", curr_item);
param.openFlags = IOR_WRONLY;
if (make_node) {
int ret;
VERBOSE(3,5,"create_remove_items_helper : mknod..." );
@ -369,7 +367,7 @@ static void create_file (const char *path, uint64_t itemNum) {
} else if (collective_creates) {
VERBOSE(3,5,"create_remove_items_helper (collective): open..." );
aiori_fh = backend->open (curr_item, &param);
aiori_fh = backend->open (curr_item, IOR_WRONLY | IOR_CREAT, &param);
if (NULL == aiori_fh)
FAIL("unable to open file %s", curr_item);
@ -377,12 +375,10 @@ static void create_file (const char *path, uint64_t itemNum) {
* !collective_creates
*/
} else {
param.openFlags |= IOR_CREAT;
param.filePerProc = !shared_file;
param.mode = FILEMODE;
VERBOSE(3,5,"create_remove_items_helper (non-collective, shared): open..." );
aiori_fh = backend->create (curr_item, &param);
aiori_fh = backend->create (curr_item, IOR_WRONLY | IOR_CREAT, &param.backend_options);
if (NULL == aiori_fh)
FAIL("unable to create file %s", curr_item);
}
@ -449,9 +445,7 @@ void collective_helper(const int dirs, const int create, const char* path, uint6
void *aiori_fh;
//create files
param.openFlags = IOR_WRONLY | IOR_CREAT;
param.mode = FILEMODE;
aiori_fh = backend->create (curr_item, &param);
aiori_fh = backend->create (curr_item, IOR_WRONLY | IOR_CREAT, &param);
if (NULL == aiori_fh) {
FAIL("unable to create file %s", curr_item);
}
@ -713,8 +707,7 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) {
VERBOSE(3,5,"mdtest_read file: %s", item);
/* open file for reading */
param.openFlags = O_RDONLY;
aiori_fh = backend->open (item, &param);
aiori_fh = backend->open (item, O_RDONLY, &param);
if (NULL == aiori_fh) {
FAIL("unable to open file %s", item);
}
@ -1972,7 +1965,7 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
MPI_Comm_size(testComm, &size);
if (backend->initialize)
backend->initialize();
backend->initialize(param.backend_options);
pid = getpid();
uid = getuid();
@ -2264,7 +2257,7 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
}
if (backend->finalize)
backend->finalize();
backend->finalize(param.backend_options);
return summary_table;
}

View File

@ -62,24 +62,6 @@ static void CheckRunSettings(IOR_test_t *tests)
params->readFile = TRUE;
params->writeFile = TRUE;
}
/* If only read or write is requested, then fix the default
* openFlags to not be open RDWR. It matters in the case
* of HDFS, which doesn't support opening RDWR.
* (We assume int-valued params are exclusively 0 or 1.)
*/
if ((params->openFlags & IOR_RDWR)
&& ((params->readFile | params->checkRead | params->checkWrite)
^ params->writeFile)) {
params->openFlags &= ~(IOR_RDWR);
if (params->readFile | params->checkRead) {
params->openFlags |= IOR_RDONLY;
params->openFlags &= ~(IOR_CREAT|IOR_EXCL);
}
else
params->openFlags |= IOR_WRONLY;
}
}
}
@ -137,8 +119,6 @@ void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_opt
params->platform = strdup(value);
} else if (strcasecmp(option, "testfile") == 0) {
params->testFileName = strdup(value);
} else if (strcasecmp(option, "hintsfilename") == 0) {
params->hintsFileName = strdup(value);
} else if (strcasecmp(option, "deadlineforstonewalling") == 0) {
params->deadlineForStonewalling = atoi(value);
} else if (strcasecmp(option, "stoneWallingWearOut") == 0) {
@ -213,20 +193,8 @@ void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_opt
params->verbose = atoi(value);
} else if (strcasecmp(option, "settimestampsignature") == 0) {
params->setTimeStampSignature = atoi(value);
} else if (strcasecmp(option, "collective") == 0) {
params->collective = atoi(value);
} else if (strcasecmp(option, "preallocate") == 0) {
params->preallocate = atoi(value);
} else if (strcasecmp(option, "storefileoffset") == 0) {
params->storeFileOffset = atoi(value);
} else if (strcasecmp(option, "usefileview") == 0) {
params->useFileView = atoi(value);
} else if (strcasecmp(option, "usesharedfilepointer") == 0) {
params->useSharedFilePointer = atoi(value);
} else if (strcasecmp(option, "usestrideddatatype") == 0) {
params->useStridedDatatype = atoi(value);
} else if (strcasecmp(option, "showhints") == 0) {
params->showHints = atoi(value);
} else if (strcasecmp(option, "uniqueDir") == 0) {
params->uniqueDir = atoi(value);
} else if (strcasecmp(option, "useexistingtestfile") == 0) {
@ -472,7 +440,7 @@ option_help * createGlobalOptions(IOR_param_t * params){
{'a', NULL, apiStr, OPTION_OPTIONAL_ARGUMENT, 's', & params->api},
{'A', NULL, "refNum -- user supplied reference number to include in the summary", OPTION_OPTIONAL_ARGUMENT, 'd', & params->referenceNumber},
{'b', NULL, "blockSize -- contiguous bytes to write per task (e.g.: 8, 4k, 2m, 1g)", OPTION_OPTIONAL_ARGUMENT, 'l', & params->blockSize},
{'c', NULL, "collective -- collective I/O", OPTION_FLAG, 'd', & params->collective},
{'c', "collective", "Use collective I/O", OPTION_FLAG, 'd', & params->collective},
{'C', NULL, "reorderTasks -- changes task ordering for readback (useful to avoid client cache)", OPTION_FLAG, 'd', & params->reorderTasks},
{'d', NULL, "interTestDelay -- delay between reps in seconds", OPTION_OPTIONAL_ARGUMENT, 'd', & params->interTestDelay},
{'D', NULL, "deadlineForStonewalling -- seconds before stopping write or read phase", OPTION_OPTIONAL_ARGUMENT, 'd', & params->deadlineForStonewalling},
@ -489,7 +457,6 @@ option_help * createGlobalOptions(IOR_param_t * params){
* after all the arguments are in and we know which it keep.
*/
{'G', NULL, "setTimeStampSignature -- set value for time stamp signature/random seed", OPTION_OPTIONAL_ARGUMENT, 'd', & params->setTimeStampSignature},
{'H', NULL, "showHints -- show hints", OPTION_FLAG, 'd', & params->showHints},
{'i', NULL, "repetitions -- number of repetitions of test", OPTION_OPTIONAL_ARGUMENT, 'd', & params->repetitions},
{'I', NULL, "individualDataSets -- datasets not shared by all procs [not working]", OPTION_FLAG, 'd', & params->individualDataSets},
{'j', NULL, "outlierThreshold -- warn on outlier N seconds from mean", OPTION_OPTIONAL_ARGUMENT, 'd', & params->outlierThreshold},
@ -503,20 +470,15 @@ option_help * createGlobalOptions(IOR_param_t * params){
{'N', NULL, "numTasks -- number of tasks that are participating in the test (overrides MPI)", OPTION_OPTIONAL_ARGUMENT, 'd', & params->numTasks},
{'o', NULL, "testFile -- full name for test", OPTION_OPTIONAL_ARGUMENT, 's', & params->testFileName},
{'O', NULL, "string of IOR directives (e.g. -O checkRead=1,lustreStripeCount=32)", OPTION_OPTIONAL_ARGUMENT, 'p', & decodeDirectiveWrapper},
{'p', NULL, "preallocate -- preallocate file size", OPTION_FLAG, 'd', & params->preallocate},
{'P', NULL, "useSharedFilePointer -- use shared file pointer [not working]", OPTION_FLAG, 'd', & params->useSharedFilePointer},
{'q', NULL, "quitOnError -- during file error-checking, abort on error", OPTION_FLAG, 'd', & params->quitOnError},
{'Q', NULL, "taskPerNodeOffset for read tests use with -C & -Z options (-C constant N, -Z at least N)", OPTION_OPTIONAL_ARGUMENT, 'd', & params->taskPerNodeOffset},
{'r', NULL, "readFile -- read existing file", OPTION_FLAG, 'd', & params->readFile},
{'R', NULL, "checkRead -- verify that the output of read matches the expected signature (used with -G)", OPTION_FLAG, 'd', & params->checkRead},
{'s', NULL, "segmentCount -- number of segments", OPTION_OPTIONAL_ARGUMENT, 'd', & params->segmentCount},
{'S', NULL, "useStridedDatatype -- put strided access into datatype [not working]", OPTION_FLAG, 'd', & params->useStridedDatatype},
{'t', NULL, "transferSize -- size of transfer in bytes (e.g.: 8, 4k, 2m, 1g)", OPTION_OPTIONAL_ARGUMENT, 'l', & params->transferSize},
{'T', NULL, "maxTimeDuration -- max time in minutes executing repeated test; it aborts only between iterations and not within a test!", OPTION_OPTIONAL_ARGUMENT, 'd', & params->maxTimeDuration},
{'u', NULL, "uniqueDir -- use unique directory name for each file-per-process", OPTION_FLAG, 'd', & params->uniqueDir},
{'U', NULL, "hintsFileName -- full name for hints file", OPTION_OPTIONAL_ARGUMENT, 's', & params->hintsFileName},
{'v', NULL, "verbose -- output information (repeating flag increases level)", OPTION_FLAG, 'd', & params->verbose},
{'V', NULL, "useFileView -- use MPI_File_set_view", OPTION_FLAG, 'd', & params->useFileView},
{'w', NULL, "writeFile -- write file", OPTION_FLAG, 'd', & params->writeFile},
{'W', NULL, "checkWrite -- check read after write", OPTION_FLAG, 'd', & params->checkWrite},
{'x', NULL, "singleXferAttempt -- do not retry transfer if incomplete", OPTION_FLAG, 'd', & params->singleXferAttempt},