Merge branch 'master' into master

master
Julian Kunkel 2020-06-24 09:50:03 +01:00 committed by GitHub
commit d5de9bcc77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 1883 additions and 1365 deletions

2
META
View File

@ -1,3 +1,3 @@
Package: ior
Version: 3.3.0+dev
Version: 3.4.0+dev
Release: 0

View File

@ -212,6 +212,20 @@ AM_COND_IF([USE_RADOS_AIORI],[
AC_DEFINE([USE_RADOS_AIORI], [], [Build RADOS backend AIORI])
])
# CEPHFS support
AC_ARG_WITH([cephfs],
[AS_HELP_STRING([--with-cephfs],
[support IO with libcephfs backend @<:@default=no@:>@])],
[],
[with_cephfs=no])
AS_IF([test "x$with_cephfs" != xno], [
CPPFLAGS="$CPPFLAGS -D_FILE_OFFSET_BITS=64 -std=gnu11"
])
AM_CONDITIONAL([USE_CEPHFS_AIORI], [test x$with_cephfs = xyes])
AM_COND_IF([USE_CEPHFS_AIORI],[
AC_DEFINE([USE_CEPHFS_AIORI], [], [Build CEPHFS backend AIORI])
])
# DAOS Backends (DAOS and DFS) IO support require DAOS and CART/GURT
AC_ARG_WITH([cart],
[AS_HELP_STRING([--with-cart],
@ -220,7 +234,8 @@ AC_ARG_WITH([cart],
AS_IF([test "x$with_cart" != xno], [
CART="yes"
LDFLAGS="$LDFLAGS -L$with_cart/lib"
LDFLAGS="$LDFLAGS -L$with_cart/lib64 -Wl,--enable-new-dtags -Wl,-rpath=$with_cart/lib64"
LDFLAGS="$LDFLAGS -L$with_cart/lib -Wl,--enable-new-dtags -Wl,-rpath=$with_cart/lib"
CPPFLAGS="$CPPFLAGS -I$with_cart/include/"
AC_CHECK_HEADERS(gurt/common.h,, [unset CART])
AC_CHECK_LIB([gurt], [d_hash_murmur64],, [unset CART])
@ -233,7 +248,7 @@ AC_ARG_WITH([daos],
AS_IF([test "x$with_daos" != xno], [
DAOS="yes"
LDFLAGS="$LDFLAGS -L$with_daos/lib"
LDFLAGS="$LDFLAGS -L$with_daos/lib64 -Wl,--enable-new-dtags -Wl,-rpath=$with_daos/lib64"
CPPFLAGS="$CPPFLAGS -I$with_daos/include"
AC_CHECK_HEADERS(daos_types.h,, [unset DAOS])
AC_CHECK_LIB([uuid], [uuid_generate],, [unset DAOS])
@ -348,6 +363,7 @@ AM_CONDITIONAL([USE_CAPS], [test x$enable_caps = xyes])
AC_CONFIG_FILES([Makefile
src/Makefile
src/test/Makefile
contrib/Makefile
doc/Makefile])
AC_OUTPUT

View File

@ -65,7 +65,6 @@ These options are to be used on the command line. E.g., 'IOR -a POSIX -b 4K'.
-a S api -- API for I/O, e.g., POSIX
-A N refNum -- user reference number to include in long summary
-b N blockSize -- contiguous bytes to write per task (e.g.: 8, 4k, 2m, 1g)
-B useO_DIRECT -- uses O_DIRECT for POSIX, bypassing I/O buffers
-c collective -- collective I/O
-C reorderTasksConstant -- changes task ordering to n+1 ordering for readback
-d N interTestDelay -- delay between reps in seconds
@ -118,6 +117,8 @@ NOTES: * S is a string, N is an integer number.
* For transfer and block sizes, the case-insensitive K, M, and G
suffices are recognized. I.e., '4k' or '4K' is accepted as 4096.
Various options are only valid for specific modules, you can see details when running $ ./ior -h
These options are typically prefixed with the module name, an example is: --posix.odirect
*********************
* 4. OPTION DETAILS *

View File

@ -22,7 +22,6 @@ These options are to be used on the command line (e.g., ``./ior -a POSIX -b 4K``
-a S api -- API for I/O [POSIX|MPIIO|HDF5|HDFS|S3|S3_EMC|NCMPI|RADOS]
-A N refNum -- user reference number to include in long summary
-b N blockSize -- contiguous bytes to write per task (e.g.: 8, 4k, 2m, 1g)
-B useO_DIRECT -- uses O_DIRECT for POSIX, bypassing I/O buffers
-c collective -- collective I/O
-C reorderTasksConstant -- changes task ordering to n+1 ordering for readback
-d N interTestDelay -- delay between reps in seconds
@ -76,6 +75,9 @@ These options are to be used on the command line (e.g., ``./ior -a POSIX -b 4K``
* For transfer and block sizes, the case-insensitive K, M, and G
suffices are recognized. I.e., '4k' or '4K' is accepted as 4096.
Various options are only valid for specific modules, you can see details when running $ ./ior -h
These options are typically prefixed with the module name, an example is: --posix.odirect
Directive Options
------------------

View File

@ -1,4 +1,4 @@
SUBDIRS = .
SUBDIRS = . test
bin_PROGRAMS = ior mdtest
if USE_CAPS
@ -75,6 +75,12 @@ extraSOURCES += aiori-RADOS.c
extraLDADD += -lrados
endif
if USE_CEPHFS_AIORI
extraSOURCES += aiori-CEPHFS.c
extraLDADD += -lcephfs
endif
if USE_DAOS_AIORI
extraSOURCES += aiori-DAOS.c aiori-DFS.c
endif
@ -122,11 +128,3 @@ MDTEST_CPPFLAGS = $(mdtest_CPPFLAGS)
libaiori_a_SOURCES += $(extraSOURCES)
libaiori_a_CPPFLAGS = $(extraCPPFLAGS)
TESTS = testlib
bin_PROGRAMS += testlib
testlib_SOURCES = ./test/lib.c
testlib_LDFLAGS = $(extraLDFLAGS)
testlib_LDADD = libaiori.a $(extraLDADD)

385
src/aiori-CEPHFS.c Executable file
View File

@ -0,0 +1,385 @@
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
/******************************************************************************\
* *
* (C) 2015 The University of Chicago *
* (C) 2020 Red Hat, Inc. *
* *
* See COPYRIGHT in top-level directory. *
* *
********************************************************************************
*
* Implement abstract I/O interface for CEPHFS.
*
\******************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <cephfs/libcephfs.h>
#include "ior.h"
#include "iordef.h"
#include "aiori.h"
#include "utilities.h"
#define CEPH_O_RDONLY 00000000
#define CEPH_O_WRONLY 00000001
#define CEPH_O_RDWR 00000002
#define CEPH_O_CREAT 00000100
#define CEPH_O_EXCL 00000200
#define CEPH_O_TRUNC 00001000
#define CEPH_O_LAZY 00020000
#define CEPH_O_DIRECTORY 00200000
#define CEPH_O_NOFOLLOW 00400000
/************************** O P T I O N S *****************************/
struct cephfs_options{
char * user;
char * conf;
char * prefix;
};
static struct cephfs_options o = {
.user = NULL,
.conf = NULL,
.prefix = NULL,
};
static option_help options [] = {
{0, "cephfs.user", "Username for the ceph cluster", OPTION_REQUIRED_ARGUMENT, 's', & o.user},
{0, "cephfs.conf", "Config file for the ceph cluster", OPTION_REQUIRED_ARGUMENT, 's', & o.conf},
{0, "cephfs.prefix", "mount prefix", OPTION_OPTIONAL_ARGUMENT, 's', & o.prefix},
LAST_OPTION
};
static struct ceph_mount_info *cmount;
/**************************** P R O T O T Y P E S *****************************/
static void CEPHFS_Init();
static void CEPHFS_Final();
static void *CEPHFS_Create(char *, IOR_param_t *);
static void *CEPHFS_Open(char *, IOR_param_t *);
static IOR_offset_t CEPHFS_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void CEPHFS_Close(void *, IOR_param_t *);
static void CEPHFS_Delete(char *, IOR_param_t *);
static void CEPHFS_Fsync(void *, IOR_param_t *);
static IOR_offset_t CEPHFS_GetFileSize(IOR_param_t *, MPI_Comm, char *);
static int CEPHFS_StatFS(const char *, ior_aiori_statfs_t *, IOR_param_t *);
static int CEPHFS_MkDir(const char *, mode_t, IOR_param_t *);
static int CEPHFS_RmDir(const char *, IOR_param_t *);
static int CEPHFS_Access(const char *, int, IOR_param_t *);
static int CEPHFS_Stat(const char *, struct stat *, IOR_param_t *);
static void CEPHFS_Sync(IOR_param_t *);
static option_help * CEPHFS_options();
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t cephfs_aiori = {
.name = "CEPHFS",
.name_legacy = NULL,
.initialize = CEPHFS_Init,
.finalize = CEPHFS_Final,
.create = CEPHFS_Create,
.open = CEPHFS_Open,
.xfer = CEPHFS_Xfer,
.close = CEPHFS_Close,
.delete = CEPHFS_Delete,
.get_version = aiori_get_version,
.fsync = CEPHFS_Fsync,
.get_file_size = CEPHFS_GetFileSize,
.statfs = CEPHFS_StatFS,
.mkdir = CEPHFS_MkDir,
.rmdir = CEPHFS_RmDir,
.access = CEPHFS_Access,
.stat = CEPHFS_Stat,
.sync = CEPHFS_Sync,
.get_options = CEPHFS_options,
};
#define CEPHFS_ERR(__err_str, __ret) do { \
errno = -__ret; \
ERR(__err_str); \
} while(0)
/***************************** F U N C T I O N S ******************************/
static const char* pfix(const char* path) {
const char* npath = path;
const char* prefix = o.prefix;
while (*prefix) {
if(*prefix++ != *npath++) {
return path;
}
}
return npath;
}
static option_help * CEPHFS_options(){
return options;
}
static void CEPHFS_Init()
{
/* Short circuit if the options haven't been filled yet. */
if (!o.user || !o.conf || !o.prefix) {
WARN("CEPHFS_Init() called before options have been populated!");
return;
}
/* Short circuit if the mount handle already exists */
if (cmount) {
return;
}
int ret;
/* create CEPHFS mount handle */
ret = ceph_create(&cmount, o.user);
if (ret) {
CEPHFS_ERR("unable to create CEPHFS mount handle", ret);
}
/* set the handle using the Ceph config */
ret = ceph_conf_read_file(cmount, o.conf);
if (ret) {
CEPHFS_ERR("unable to read ceph config file", ret);
}
/* mount the handle */
ret = ceph_mount(cmount, "/");
if (ret) {
CEPHFS_ERR("unable to mount cephfs", ret);
ceph_shutdown(cmount);
}
Inode *root;
/* try retrieving the root cephfs inode */
ret = ceph_ll_lookup_root(cmount, &root);
if (ret) {
CEPHFS_ERR("uanble to retrieve root cephfs inode", ret);
ceph_shutdown(cmount);
}
return;
}
static void CEPHFS_Final()
{
/* shutdown */
int ret = ceph_unmount(cmount);
if (ret < 0) {
CEPHFS_ERR("ceph_umount failed", ret);
}
ret = ceph_release(cmount);
if (ret < 0) {
CEPHFS_ERR("ceph_release failed", ret);
}
cmount = NULL;
}
static void *CEPHFS_Create(char *testFileName, IOR_param_t * param)
{
return CEPHFS_Open(testFileName, param);
}
static void *CEPHFS_Open(char *testFileName, IOR_param_t * param)
{
const char *file = pfix(testFileName);
int* fd;
fd = (int *)malloc(sizeof(int));
mode_t mode = 0664;
int flags = (int) 0;
/* set IOR file flags to CephFS flags */
/* -- file open flags -- */
if (param->openFlags & IOR_RDONLY) {
flags |= CEPH_O_RDONLY;
}
if (param->openFlags & IOR_WRONLY) {
flags |= CEPH_O_WRONLY;
}
if (param->openFlags & IOR_RDWR) {
flags |= CEPH_O_RDWR;
}
if (param->openFlags & IOR_APPEND) {
fprintf(stdout, "File append not implemented in CephFS\n");
}
if (param->openFlags & IOR_CREAT) {
flags |= CEPH_O_CREAT;
}
if (param->openFlags & IOR_EXCL) {
flags |= CEPH_O_EXCL;
}
if (param->openFlags & IOR_TRUNC) {
flags |= CEPH_O_TRUNC;
}
if (param->openFlags & IOR_DIRECT) {
fprintf(stdout, "O_DIRECT not implemented in CephFS\n");
}
*fd = ceph_open(cmount, file, flags, mode);
if (*fd < 0) {
CEPHFS_ERR("ceph_open failed", *fd);
}
return (void *) fd;
}
static IOR_offset_t CEPHFS_Xfer(int access, void *file, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param)
{
uint64_t size = (uint64_t) length;
char *buf = (char *) buffer;
int fd = *(int *) file;
int ret;
if (access == WRITE)
{
ret = ceph_write(cmount, fd, buf, size, param->offset);
if (ret < 0) {
CEPHFS_ERR("unable to write file to CephFS", ret);
} else if (ret < size) {
CEPHFS_ERR("short write to CephFS", ret);
}
if (param->fsyncPerWrite == TRUE) {
CEPHFS_Fsync(&fd, param);
}
}
else /* READ */
{
ret = ceph_read(cmount, fd, buf, size, param->offset);
if (ret < 0) {
CEPHFS_ERR("unable to read file from CephFS", ret);
} else if (ret < size) {
CEPHFS_ERR("short read from CephFS", ret);
}
}
return length;
}
static void CEPHFS_Fsync(void *file, IOR_param_t * param)
{
int fd = *(int *) file;
int ret = ceph_fsync(cmount, fd, 0);
if (ret < 0) {
CEPHFS_ERR("ceph_fsync failed", ret);
}
}
static void CEPHFS_Close(void *file, IOR_param_t * param)
{
int fd = *(int *) file;
int ret = ceph_close(cmount, fd);
if (ret < 0) {
CEPHFS_ERR("ceph_close failed", ret);
}
free(file);
return;
}
static void CEPHFS_Delete(char *testFileName, IOR_param_t * param)
{
int ret = ceph_unlink(cmount, pfix(testFileName));
if (ret < 0) {
CEPHFS_ERR("ceph_unlink failed", ret);
}
return;
}
static IOR_offset_t CEPHFS_GetFileSize(IOR_param_t * param, MPI_Comm testComm,
char *testFileName)
{
struct stat stat_buf;
IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum;
int ret = ceph_stat(cmount, pfix(testFileName), &stat_buf);
if (ret < 0) {
CEPHFS_ERR("ceph_stat failed", ret);
}
aggFileSizeFromStat = stat_buf.st_size;
if (param->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);
}
static int CEPHFS_StatFS(const char *path, ior_aiori_statfs_t *stat_buf,
IOR_param_t *param)
{
#if defined(HAVE_STATVFS)
struct statvfs statfs_buf;
int ret = ceph_statfs(cmount, pfix(path), &statfs_buf);
if (ret < 0) {
CEPHFS_ERR("ceph_statfs failed", 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;
#else
WARN("ceph_statfs requires statvfs!");
return -1;
#endif
}
static int CEPHFS_MkDir(const char *path, mode_t mode, IOR_param_t *param)
{
return ceph_mkdir(cmount, pfix(path), mode);
}
static int CEPHFS_RmDir(const char *path, IOR_param_t *param)
{
return ceph_rmdir(cmount, pfix(path));
}
static int CEPHFS_Access(const char *testFileName, int mode, IOR_param_t *param)
{
struct stat buf;
return ceph_stat(cmount, pfix(testFileName), &buf);
}
static int CEPHFS_Stat(const char *testFileName, struct stat *buf, IOR_param_t *param)
{
return ceph_stat(cmount, pfix(testFileName), buf);
}
static void CEPHFS_Sync(IOR_param_t *param)
{
int ret = ceph_sync_fs(cmount);
if (ret < 0) {
CEPHFS_ERR("ceph_sync_fs failed", ret);
}
}

View File

@ -1,16 +1,9 @@
/*
* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
/*
* Copyright (C) 2018-2019 Intel Corporation
*
* GOVERNMENT LICENSE RIGHTS-OPEN SOURCE SOFTWARE
* The Government's rights to use, modify, reproduce, release, perform, display,
* or disclose this software are subject to the terms of the Apache License as
* provided in Contract No. 8F-30005.
* Any reproduction of computer software, computer software documentation, or
* portions thereof marked with this legend must also reproduce the markings.
* Copyright (C) 2018-2020 Intel Corporation
* See the file COPYRIGHT for a complete copyright notice and license.
*/
/*
@ -31,15 +24,16 @@
#include <libgen.h>
#include <stdbool.h>
#include <mpi.h>
#include <gurt/common.h>
#include <daos.h>
#include "ior.h"
#include "aiori.h"
#include "utilities.h"
#include "iordef.h"
/************************** O P T I O N S *****************************/
struct daos_options{
typedef struct {
char *pool;
char *svcl;
char *group;
@ -47,49 +41,62 @@ struct daos_options{
int chunk_size;
int destroy;
char *oclass;
};
} DAOS_options_t;
static struct daos_options o = {
.pool = NULL,
.svcl = NULL,
.group = NULL,
.cont = NULL,
.chunk_size = 1048576,
.destroy = 0,
.oclass = NULL,
};
static option_help * DAOS_options(aiori_mod_opt_t ** init_backend_options,
aiori_mod_opt_t * init_values){
DAOS_options_t * o = malloc(sizeof(DAOS_options_t));
static option_help options [] = {
{0, "daos.pool", "pool uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o.pool},
{0, "daos.svcl", "pool SVCL", OPTION_OPTIONAL_ARGUMENT, 's', &o.svcl},
{0, "daos.group", "server group", OPTION_OPTIONAL_ARGUMENT, 's', &o.group},
{0, "daos.cont", "container uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o.cont},
{0, "daos.chunk_size", "chunk size", OPTION_OPTIONAL_ARGUMENT, 'd', &o.chunk_size},
{0, "daos.destroy", "Destroy Container", OPTION_FLAG, 'd', &o.destroy},
{0, "daos.oclass", "object class", OPTION_OPTIONAL_ARGUMENT, 's', &o.oclass},
LAST_OPTION
};
if (init_values != NULL) {
memcpy(o, init_values, sizeof(DAOS_options_t));
} else {
memset(o, 0, sizeof(DAOS_options_t));
/* initialize the options properly */
o->chunk_size = 1048576;
}
*init_backend_options = (aiori_mod_opt_t *) o;
option_help h [] = {
{0, "daos.pool", "pool uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o->pool},
{0, "daos.svcl", "pool SVCL", OPTION_OPTIONAL_ARGUMENT, 's', &o->svcl},
{0, "daos.group", "server group", OPTION_OPTIONAL_ARGUMENT, 's', &o->group},
{0, "daos.cont", "container uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o->cont},
{0, "daos.chunk_size", "chunk size", OPTION_OPTIONAL_ARGUMENT, 'd', &o->chunk_size},
{0, "daos.destroy", "Destroy Container", OPTION_FLAG, 'd', &o->destroy},
{0, "daos.oclass", "object class", OPTION_OPTIONAL_ARGUMENT, 's', &o->oclass},
LAST_OPTION
};
option_help * help = malloc(sizeof(h));
memcpy(help, h, sizeof(h));
return help;
}
/**************************** P R O T O T Y P E S *****************************/
static void DAOS_Init();
static void DAOS_Fini();
static void *DAOS_Create(char *, IOR_param_t *);
static void *DAOS_Open(char *, IOR_param_t *);
static int DAOS_Access(const char *, int, IOR_param_t *);
static IOR_offset_t DAOS_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void DAOS_Close(void *, IOR_param_t *);
static void DAOS_Delete(char *, IOR_param_t *);
static void DAOS_Init(aiori_mod_opt_t *);
static void DAOS_Fini(aiori_mod_opt_t *);
static aiori_fd_t *DAOS_Create(char *, int, aiori_mod_opt_t *);
static aiori_fd_t *DAOS_Open(char *, int, aiori_mod_opt_t *);
static int DAOS_Access(const char *, int, aiori_mod_opt_t *);
static IOR_offset_t DAOS_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t,
IOR_offset_t, aiori_mod_opt_t *);
static void DAOS_Close(aiori_fd_t *, aiori_mod_opt_t *);
static void DAOS_Delete(char *, aiori_mod_opt_t *);
static char* DAOS_GetVersion();
static void DAOS_Fsync(void *, IOR_param_t *);
static IOR_offset_t DAOS_GetFileSize(IOR_param_t *, MPI_Comm, char *);
static void DAOS_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static IOR_offset_t DAOS_GetFileSize(aiori_mod_opt_t *, MPI_Comm, char *);
static option_help * DAOS_options();
static void DAOS_init_xfer_options(aiori_xfer_hint_t *);
static int DAOS_check_params(aiori_mod_opt_t *);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t daos_aiori = {
.name = "DAOS",
.initialize = DAOS_Init,
.finalize = DAOS_Fini,
.create = DAOS_Create,
.open = DAOS_Open,
.access = DAOS_Access,
@ -97,15 +104,17 @@ ior_aiori_t daos_aiori = {
.close = DAOS_Close,
.delete = DAOS_Delete,
.get_version = DAOS_GetVersion,
.xfer_hints = DAOS_init_xfer_options,
.fsync = DAOS_Fsync,
.get_file_size = DAOS_GetFileSize,
.initialize = DAOS_Init,
.finalize = DAOS_Fini,
.get_options = DAOS_options,
.statfs = aiori_posix_statfs,
.mkdir = aiori_posix_mkdir,
.rmdir = aiori_posix_rmdir,
.stat = aiori_posix_stat,
.get_options = DAOS_options,
.xfer_hints = DAOS_init_xfer_options,
.check_params = DAOS_check_params,
.enable_mdtest = false,
};
#define IOR_DAOS_MUR_SEED 0xDEAD10CC
@ -151,6 +160,22 @@ do { \
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error"); \
} while (0)
static aiori_xfer_hint_t * hints = NULL;
void DAOS_init_xfer_options(aiori_xfer_hint_t * params)
{
hints = params;
}
static int DAOS_check_params(aiori_mod_opt_t * options){
DAOS_options_t *o = (DAOS_options_t *) options;
if (o->pool == NULL || o->svcl == NULL || o->cont == NULL)
ERR("Invalid pool or container options\n");
return 0;
}
/* Distribute process 0's pool or container handle to others. */
static void
HandleDistribute(daos_handle_t *handle, enum handleType type)
@ -209,29 +234,22 @@ HandleDistribute(daos_handle_t *handle, enum handleType type)
free(global.iov_buf);
}
static option_help *
DAOS_options()
{
return options;
}
static void
DAOS_Init()
DAOS_Init(aiori_mod_opt_t * options)
{
DAOS_options_t *o = (DAOS_options_t *)options;
int rc;
if (daos_initialized)
return;
if (o.pool == NULL || o.svcl == NULL || o.cont == NULL) {
GERR("Invalid DAOS pool/cont\n");
if (o->pool == NULL || o->svcl == NULL || o->cont == NULL)
return;
}
if (o.oclass) {
objectClass = daos_oclass_name2id(o.oclass);
if (o->oclass) {
objectClass = daos_oclass_name2id(o->oclass);
if (objectClass == OC_UNKNOWN)
GERR("Invalid DAOS Object class %s\n", o.oclass);
GERR("Invalid DAOS Object class %s\n", o->oclass);
}
rc = daos_init();
@ -244,25 +262,25 @@ DAOS_Init()
static daos_pool_info_t po_info;
static daos_cont_info_t co_info;
INFO(VERBOSE_1, "Connecting to pool %s", o.pool);
INFO(VERBOSE_1, "Connecting to pool %s", o->pool);
rc = uuid_parse(o.pool, uuid);
DCHECK(rc, "Failed to parse 'pool': %s", o.pool);
rc = uuid_parse(o->pool, uuid);
DCHECK(rc, "Failed to parse 'pool': %s", o->pool);
svcl = daos_rank_list_parse(o.svcl, ":");
svcl = daos_rank_list_parse(o->svcl, ":");
if (svcl == NULL)
ERR("Failed to allocate svcl");
rc = daos_pool_connect(uuid, o.group, svcl, DAOS_PC_RW,
rc = daos_pool_connect(uuid, o->group, svcl, DAOS_PC_RW,
&poh, &po_info, NULL);
d_rank_list_free(svcl);
DCHECK(rc, "Failed to connect to pool %s", o.pool);
DCHECK(rc, "Failed to connect to pool %s", o->pool);
INFO(VERBOSE_1, "Create/Open Container %s", o.cont);
INFO(VERBOSE_1, "Create/Open Container %s", o->cont);
uuid_clear(uuid);
rc = uuid_parse(o.cont, uuid);
DCHECK(rc, "Failed to parse 'cont': %s", o.cont);
rc = uuid_parse(o->cont, uuid);
DCHECK(rc, "Failed to parse 'cont': %s", o->cont);
rc = daos_cont_open(poh, uuid, DAOS_COO_RW, &coh, &co_info,
NULL);
@ -285,8 +303,9 @@ DAOS_Init()
}
static void
DAOS_Fini()
DAOS_Fini(aiori_mod_opt_t *options)
{
DAOS_options_t *o = (DAOS_options_t *)options;
int rc;
if (!daos_initialized)
@ -295,18 +314,18 @@ DAOS_Fini()
MPI_Barrier(MPI_COMM_WORLD);
rc = daos_cont_close(coh, NULL);
if (rc) {
DCHECK(rc, "Failed to close container %s (%d)", o.cont, rc);
DCHECK(rc, "Failed to close container %s (%d)", o->cont, rc);
MPI_Abort(MPI_COMM_WORLD, -1);
}
MPI_Barrier(MPI_COMM_WORLD);
if (o.destroy) {
if (o->destroy) {
if (rank == 0) {
uuid_t uuid;
double t1, t2;
INFO(VERBOSE_1, "Destroying DAOS Container %s", o.cont);
uuid_parse(o.cont, uuid);
INFO(VERBOSE_1, "Destroying DAOS Container %s", o->cont);
uuid_parse(o->cont, uuid);
t1 = MPI_Wtime();
rc = daos_cont_destroy(poh, uuid, 1, NULL);
t2 = MPI_Wtime();
@ -317,7 +336,7 @@ DAOS_Fini()
MPI_Bcast(&rc, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (rc) {
if (rank == 0)
DCHECK(rc, "Failed to destroy container %s (%d)", o.cont, rc);
DCHECK(rc, "Failed to destroy container %s (%d)", o->cont, rc);
MPI_Abort(MPI_COMM_WORLD, -1);
}
}
@ -326,7 +345,7 @@ DAOS_Fini()
INFO(VERBOSE_1, "Disconnecting from DAOS POOL..");
rc = daos_pool_disconnect(poh, NULL);
DCHECK(rc, "Failed to disconnect from pool %s", o.pool);
DCHECK(rc, "Failed to disconnect from pool %s", o->pool);
MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD), "barrier error");
if (rank == 0)
@ -341,38 +360,38 @@ DAOS_Fini()
static void
gen_oid(const char *name, daos_obj_id_t *oid)
{
oid->lo = d_hash_murmur64(name, strlen(name), IOR_DAOS_MUR_SEED);
oid->hi = 0;
daos_array_generate_id(oid, objectClass, true, 0);
}
static void *
DAOS_Create(char *testFileName, IOR_param_t *param)
static aiori_fd_t *
DAOS_Create(char *testFileName, int flags, aiori_mod_opt_t *param)
{
DAOS_options_t *o = (DAOS_options_t*) param;
daos_obj_id_t oid;
int rc;
/** Convert file name into object ID */
gen_oid(testFileName, &oid);
/** Create the array */
if (param->filePerProc || rank == 0) {
rc = daos_array_create(coh, oid, DAOS_TX_NONE, 1, o.chunk_size,
if (hints->filePerProc || rank == 0) {
rc = daos_array_create(coh, oid, DAOS_TX_NONE, 1, o->chunk_size,
&aoh, NULL);
DCHECK(rc, "Failed to create array object\n");
}
/** Distribute the array handle if not FPP */
if (!param->filePerProc)
if (!hints->filePerProc)
HandleDistribute(&aoh, ARRAY_HANDLE);
return &aoh;
return (aiori_fd_t*)(&aoh);
}
static int
DAOS_Access(const char *testFileName, int mode, IOR_param_t * param)
DAOS_Access(const char *testFileName, int mode, aiori_mod_opt_t * param)
{
daos_obj_id_t oid;
daos_size_t cell_size, chunk_size;
@ -394,8 +413,8 @@ DAOS_Access(const char *testFileName, int mode, IOR_param_t * param)
return rc;
}
static void *
DAOS_Open(char *testFileName, IOR_param_t *param)
static aiori_fd_t *
DAOS_Open(char *testFileName, int flags, aiori_mod_opt_t *param)
{
daos_obj_id_t oid;
@ -403,7 +422,7 @@ DAOS_Open(char *testFileName, IOR_param_t *param)
gen_oid(testFileName, &oid);
/** Open the array */
if (param->filePerProc || rank == 0) {
if (hints->filePerProc || rank == 0) {
daos_size_t cell_size, chunk_size;
int rc;
@ -416,15 +435,15 @@ DAOS_Open(char *testFileName, IOR_param_t *param)
}
/** Distribute the array handle if not FPP */
if (!param->filePerProc)
if (!hints->filePerProc)
HandleDistribute(&aoh, ARRAY_HANDLE);
return &aoh;
return (aiori_fd_t*)(&aoh);
}
static IOR_offset_t
DAOS_Xfer(int access, void *file, IOR_size_t *buffer,
IOR_offset_t length, IOR_param_t *param)
DAOS_Xfer(int access, aiori_fd_t *file, IOR_size_t *buffer, IOR_offset_t length,
IOR_offset_t off, aiori_mod_opt_t *param)
{
daos_array_iod_t iod;
daos_range_t rg;
@ -435,7 +454,7 @@ DAOS_Xfer(int access, void *file, IOR_size_t *buffer,
/** set array location */
iod.arr_nr = 1;
rg.rg_len = length;
rg.rg_idx = param->offset;
rg.rg_idx = off;
iod.arr_rgs = &rg;
/** set memory location */
@ -444,10 +463,10 @@ DAOS_Xfer(int access, void *file, IOR_size_t *buffer,
sgl.sg_iovs = &iov;
if (access == WRITE) {
rc = daos_array_write(aoh, DAOS_TX_NONE, &iod, &sgl, NULL, NULL);
rc = daos_array_write(aoh, DAOS_TX_NONE, &iod, &sgl, NULL);
DCHECK(rc, "daos_array_write() failed (%d).", rc);
} else {
rc = daos_array_read(aoh, DAOS_TX_NONE, &iod, &sgl, NULL, NULL);
rc = daos_array_read(aoh, DAOS_TX_NONE, &iod, &sgl, NULL);
DCHECK(rc, "daos_array_read() failed (%d).", rc);
}
@ -455,7 +474,7 @@ DAOS_Xfer(int access, void *file, IOR_size_t *buffer,
}
static void
DAOS_Close(void *file, IOR_param_t *param)
DAOS_Close(aiori_fd_t *file, aiori_mod_opt_t *param)
{
int rc;
@ -469,7 +488,7 @@ DAOS_Close(void *file, IOR_param_t *param)
}
static void
DAOS_Delete(char *testFileName, IOR_param_t *param)
DAOS_Delete(char *testFileName, aiori_mod_opt_t *param)
{
daos_obj_id_t oid;
daos_size_t cell_size, chunk_size;
@ -507,13 +526,13 @@ DAOS_GetVersion()
}
static void
DAOS_Fsync(void *file, IOR_param_t *param)
DAOS_Fsync(aiori_fd_t *file, aiori_mod_opt_t *param)
{
return;
}
static IOR_offset_t
DAOS_GetFileSize(IOR_param_t *param, MPI_Comm testComm, char *testFileName)
DAOS_GetFileSize(aiori_mod_opt_t *param, MPI_Comm comm, char *testFileName)
{
daos_obj_id_t oid;
daos_size_t size;
@ -526,7 +545,7 @@ DAOS_GetFileSize(IOR_param_t *param, MPI_Comm testComm, char *testFileName)
gen_oid(testFileName, &oid);
/** open the array to verify it exists */
if (param->filePerProc || rank == 0) {
if (hints->filePerProc || rank == 0) {
daos_size_t cell_size, chunk_size;
rc = daos_array_open(coh, oid, DAOS_TX_NONE, DAOS_OO_RO,
@ -544,7 +563,7 @@ DAOS_GetFileSize(IOR_param_t *param, MPI_Comm testComm, char *testFileName)
aoh.cookie = 0;
}
if (!param->filePerProc)
if (!hints->filePerProc)
MPI_Bcast(&size, 1, MPI_LONG, 0, MPI_COMM_WORLD);
return size;

View File

@ -2,14 +2,8 @@
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
/*
* Copyright (C) 2018-2019 Intel Corporation
*
* GOVERNMENT LICENSE RIGHTS-OPEN SOURCE SOFTWARE
* The Government's rights to use, modify, reproduce, release, perform, display,
* or disclose this software are subject to the terms of the Apache License as
* provided in Contract No. 8F-30005.
* Any reproduction of computer software, computer software documentation, or
* portions thereof marked with this legend must also reproduce the markings.
* Copyright (C) 2018-2020 Intel Corporation
* See the file COPYRIGHT for a complete copyright notice and license.
*/
/*
@ -33,20 +27,22 @@
#include <fcntl.h>
#include <libgen.h>
#include <mpi.h>
#include <gurt/common.h>
#include <gurt/hash.h>
#include <daos.h>
#include <daos_fs.h>
#include "ior.h"
#include "iordef.h"
#include "aiori.h"
#include "utilities.h"
#include "iordef.h"
dfs_t *dfs;
static daos_handle_t poh, coh;
static daos_oclass_id_t objectClass = OC_SX;
static daos_oclass_id_t dir_oclass = OC_SX;
static struct d_hash_table *dir_hash;
static bool dfs_init;
struct aiori_dir_hdl {
d_list_t entry;
@ -57,64 +53,83 @@ struct aiori_dir_hdl {
enum handleType {
POOL_HANDLE,
CONT_HANDLE,
ARRAY_HANDLE
DFS_HANDLE
};
/************************** O P T I O N S *****************************/
struct dfs_options{
typedef struct {
char *pool;
char *svcl;
char *group;
char *cont;
int chunk_size;
char *oclass;
char *dir_oclass;
char *prefix;
int destroy;
};
} DFS_options_t;
static struct dfs_options o = {
.pool = NULL,
.svcl = NULL,
.group = NULL,
.cont = NULL,
.chunk_size = 1048576,
.oclass = NULL,
.destroy = 0,
};
static option_help * DFS_options(aiori_mod_opt_t ** init_backend_options,
aiori_mod_opt_t * init_values){
DFS_options_t * o = malloc(sizeof(DFS_options_t));
static option_help options [] = {
{0, "dfs.pool", "pool uuid", OPTION_OPTIONAL_ARGUMENT, 's', & o.pool},
{0, "dfs.svcl", "pool SVCL", OPTION_OPTIONAL_ARGUMENT, 's', & o.svcl},
{0, "dfs.group", "server group", OPTION_OPTIONAL_ARGUMENT, 's', & o.group},
{0, "dfs.cont", "DFS container uuid", OPTION_OPTIONAL_ARGUMENT, 's', & o.cont},
{0, "dfs.chunk_size", "chunk size", OPTION_OPTIONAL_ARGUMENT, 'd', &o.chunk_size},
{0, "dfs.oclass", "object class", OPTION_OPTIONAL_ARGUMENT, 's', &o.oclass},
{0, "dfs.destroy", "Destroy DFS Container", OPTION_FLAG, 'd', &o.destroy},
LAST_OPTION
};
if (init_values != NULL) {
memcpy(o, init_values, sizeof(DFS_options_t));
} else {
memset(o, 0, sizeof(DFS_options_t));
/* initialize the options properly */
o->chunk_size = 1048576;
}
*init_backend_options = (aiori_mod_opt_t *) o;
option_help h [] = {
{0, "dfs.pool", "pool uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o->pool},
{0, "dfs.svcl", "pool SVCL", OPTION_OPTIONAL_ARGUMENT, 's', &o->svcl},
{0, "dfs.group", "server group", OPTION_OPTIONAL_ARGUMENT, 's', &o->group},
{0, "dfs.cont", "DFS container uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o->cont},
{0, "dfs.chunk_size", "chunk size", OPTION_OPTIONAL_ARGUMENT, 'd', &o->chunk_size},
{0, "dfs.oclass", "object class", OPTION_OPTIONAL_ARGUMENT, 's', &o->oclass},
{0, "dfs.dir_oclass", "directory object class", OPTION_OPTIONAL_ARGUMENT, 's',
&o->dir_oclass},
{0, "dfs.prefix", "mount prefix", OPTION_OPTIONAL_ARGUMENT, 's', &o->prefix},
{0, "dfs.destroy", "Destroy DFS Container", OPTION_FLAG, 'd', &o->destroy},
LAST_OPTION
};
option_help * help = malloc(sizeof(h));
memcpy(help, h, sizeof(h));
return help;
}
/**************************** P R O T O T Y P E S *****************************/
static void *DFS_Create(char *, IOR_param_t *);
static void *DFS_Open(char *, IOR_param_t *);
static IOR_offset_t DFS_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void DFS_Close(void *, IOR_param_t *);
static void DFS_Delete(char *, IOR_param_t *);
static void DFS_Init(aiori_mod_opt_t *);
static void DFS_Finalize(aiori_mod_opt_t *);
static aiori_fd_t *DFS_Create(char *, int, aiori_mod_opt_t *);
static aiori_fd_t *DFS_Open(char *, int, aiori_mod_opt_t *);
static IOR_offset_t DFS_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t,
IOR_offset_t, aiori_mod_opt_t *);
static void DFS_Close(aiori_fd_t *, aiori_mod_opt_t *);
static void DFS_Delete(char *, aiori_mod_opt_t *);
static char* DFS_GetVersion();
static void DFS_Fsync(void *, IOR_param_t *);
static IOR_offset_t DFS_GetFileSize(IOR_param_t *, MPI_Comm, char *);
static int DFS_Statfs (const char *, ior_aiori_statfs_t *, IOR_param_t *);
static int DFS_Stat (const char *, struct stat *, IOR_param_t *);
static int DFS_Mkdir (const char *, mode_t, IOR_param_t *);
static int DFS_Rmdir (const char *, IOR_param_t *);
static int DFS_Access (const char *, int, IOR_param_t *);
static void DFS_Init();
static void DFS_Finalize();
static void DFS_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static void DFS_Sync(aiori_mod_opt_t *);
static IOR_offset_t DFS_GetFileSize(aiori_mod_opt_t *, MPI_Comm, char *);
static int DFS_Statfs (const char *, ior_aiori_statfs_t *, aiori_mod_opt_t *);
static int DFS_Stat (const char *, struct stat *, aiori_mod_opt_t *);
static int DFS_Mkdir (const char *, mode_t, aiori_mod_opt_t *);
static int DFS_Rmdir (const char *, aiori_mod_opt_t *);
static int DFS_Access (const char *, int, aiori_mod_opt_t *);
static option_help * DFS_options();
static void DFS_init_xfer_options(aiori_xfer_hint_t *);
static int DFS_check_params(aiori_mod_opt_t *);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t dfs_aiori = {
.name = "DFS",
.initialize = DFS_Init,
.finalize = DFS_Finalize,
.create = DFS_Create,
.open = DFS_Open,
.xfer = DFS_Xfer,
@ -122,15 +137,17 @@ ior_aiori_t dfs_aiori = {
.delete = DFS_Delete,
.get_version = DFS_GetVersion,
.fsync = DFS_Fsync,
.sync = DFS_Sync,
.get_file_size = DFS_GetFileSize,
.xfer_hints = DFS_init_xfer_options,
.statfs = DFS_Statfs,
.mkdir = DFS_Mkdir,
.rmdir = DFS_Rmdir,
.access = DFS_Access,
.stat = DFS_Stat,
.initialize = DFS_Init,
.finalize = DFS_Finalize,
.get_options = DFS_options,
.check_params = DFS_check_params,
.enable_mdtest = true,
};
/***************************** F U N C T I O N S ******************************/
@ -161,6 +178,22 @@ do { \
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error"); \
} while (0)
static aiori_xfer_hint_t * hints = NULL;
void DFS_init_xfer_options(aiori_xfer_hint_t * params)
{
hints = params;
}
static int DFS_check_params(aiori_mod_opt_t * options){
DFS_options_t *o = (DFS_options_t *) options;
if (o->pool == NULL || o->svcl == NULL || o->cont == NULL)
ERR("Invalid pool or container options\n");
return 0;
}
static inline struct aiori_dir_hdl *
hdl_obj(d_list_t *rlink)
{
@ -193,7 +226,7 @@ static d_hash_table_ops_t hdl_hash_ops = {
/* Distribute process 0's pool or container handle to others. */
static void
HandleDistribute(daos_handle_t *handle, enum handleType type)
HandleDistribute(enum handleType type)
{
d_iov_t global;
int rc;
@ -202,13 +235,15 @@ HandleDistribute(daos_handle_t *handle, enum handleType type)
global.iov_buf_len = 0;
global.iov_len = 0;
assert(type == POOL_HANDLE || type == CONT_HANDLE);
assert(type == POOL_HANDLE || type == CONT_HANDLE || type == DFS_HANDLE);
if (rank == 0) {
/* Get the global handle size. */
if (type == POOL_HANDLE)
rc = daos_pool_local2global(*handle, &global);
rc = daos_pool_local2global(poh, &global);
else if (type == CONT_HANDLE)
rc = daos_cont_local2global(coh, &global);
else
rc = daos_cont_local2global(*handle, &global);
rc = dfs_local2global(dfs, &global);
DCHECK(rc, "Failed to get global handle size");
}
@ -223,9 +258,11 @@ HandleDistribute(daos_handle_t *handle, enum handleType type)
if (rank == 0) {
if (type == POOL_HANDLE)
rc = daos_pool_local2global(*handle, &global);
rc = daos_pool_local2global(poh, &global);
else if (type == CONT_HANDLE)
rc = daos_cont_local2global(coh, &global);
else
rc = daos_cont_local2global(*handle, &global);
rc = dfs_local2global(dfs, &global);
DCHECK(rc, "Failed to create global handle");
}
@ -235,9 +272,11 @@ HandleDistribute(daos_handle_t *handle, enum handleType type)
if (rank != 0) {
if (type == POOL_HANDLE)
rc = daos_pool_global2local(global, handle);
rc = daos_pool_global2local(global, &poh);
else if (type == CONT_HANDLE)
rc = daos_cont_global2local(poh, global, &coh);
else
rc = daos_cont_global2local(poh, global, handle);
rc = dfs_global2local(poh, coh, 0, global, &dfs);
DCHECK(rc, "Failed to get local handle");
}
@ -336,7 +375,7 @@ out:
}
static dfs_obj_t *
lookup_insert_dir(const char *name)
lookup_insert_dir(const char *name, mode_t *mode)
{
struct aiori_dir_hdl *hdl;
d_list_t *rlink;
@ -355,8 +394,11 @@ lookup_insert_dir(const char *name)
strncpy(hdl->name, name, PATH_MAX-1);
hdl->name[PATH_MAX-1] = '\0';
rc = dfs_lookup(dfs, name, O_RDWR, &hdl->oh, NULL, NULL);
DCHECK(rc, "dfs_lookup() of %s Failed", name);
rc = dfs_lookup(dfs, name, O_RDWR, &hdl->oh, mode, NULL);
if (rc)
return NULL;
if (mode && S_ISREG(*mode))
return hdl->oh;
rc = d_hash_rec_insert(dir_hash, hdl->name, strlen(hdl->name),
&hdl->entry, true);
@ -365,26 +407,35 @@ lookup_insert_dir(const char *name)
return hdl->oh;
}
static option_help * DFS_options(){
return options;
}
static void
DFS_Init() {
DFS_Init(aiori_mod_opt_t * options)
{
DFS_options_t *o = (DFS_options_t *)options;
int rc;
if (o.pool == NULL || o.svcl == NULL || o.cont == NULL)
ERR("Invalid pool or container options\n");
/** in case we are already initialized, return */
if (dfs_init)
return;
if (o.oclass) {
objectClass = daos_oclass_name2id(o.oclass);
if (objectClass == OC_UNKNOWN)
GERR("Invalid DAOS Object class %s\n", o.oclass);
}
/** shouldn't be fatal since it can be called with POSIX backend selection */
if (o->pool == NULL || o->svcl == NULL || o->cont == NULL)
return;
rc = daos_init();
DCHECK(rc, "Failed to initialize daos");
if (o->oclass) {
objectClass = daos_oclass_name2id(o->oclass);
if (objectClass == OC_UNKNOWN)
GERR("Invalid DAOS object class %s\n", o->oclass);
}
if (o->dir_oclass) {
dir_oclass = daos_oclass_name2id(o->dir_oclass);
if (dir_oclass == OC_UNKNOWN)
GERR("Invalid DAOS directory object class %s\n", o->dir_oclass);
}
rc = d_hash_table_create(0, 16, NULL, &hdl_hash_ops, &dir_hash);
DCHECK(rc, "Failed to initialize dir hashtable");
@ -394,21 +445,21 @@ DFS_Init() {
daos_pool_info_t pool_info;
daos_cont_info_t co_info;
rc = uuid_parse(o.pool, pool_uuid);
DCHECK(rc, "Failed to parse 'Pool uuid': %s", o.pool);
rc = uuid_parse(o->pool, pool_uuid);
DCHECK(rc, "Failed to parse 'Pool uuid': %s", o->pool);
rc = uuid_parse(o.cont, co_uuid);
DCHECK(rc, "Failed to parse 'Cont uuid': %s", o.cont);
rc = uuid_parse(o->cont, co_uuid);
DCHECK(rc, "Failed to parse 'Cont uuid': %s", o->cont);
svcl = daos_rank_list_parse(o.svcl, ":");
svcl = daos_rank_list_parse(o->svcl, ":");
if (svcl == NULL)
ERR("Failed to allocate svcl");
INFO(VERBOSE_1, "Pool uuid = %s, SVCL = %s\n", o.pool, o.svcl);
INFO(VERBOSE_1, "DFS Container namespace uuid = %s\n", o.cont);
INFO(VERBOSE_1, "Pool uuid = %s, SVCL = %s\n", o->pool, o->svcl);
INFO(VERBOSE_1, "DFS Container namespace uuid = %s\n", o->cont);
/** Connect to DAOS pool */
rc = daos_pool_connect(pool_uuid, o.group, svcl, DAOS_PC_RW,
rc = daos_pool_connect(pool_uuid, o->group, svcl, DAOS_PC_RW,
&poh, &pool_info, NULL);
d_rank_list_free(svcl);
DCHECK(rc, "Failed to connect to pool");
@ -425,18 +476,26 @@ DFS_Init() {
} else if (rc) {
DCHECK(rc, "Failed to create container");
}
rc = dfs_mount(poh, coh, O_RDWR, &dfs);
DCHECK(rc, "Failed to mount DFS namespace");
}
HandleDistribute(&poh, POOL_HANDLE);
HandleDistribute(&coh, CONT_HANDLE);
HandleDistribute(POOL_HANDLE);
HandleDistribute(CONT_HANDLE);
HandleDistribute(DFS_HANDLE);
rc = dfs_mount(poh, coh, O_RDWR, &dfs);
DCHECK(rc, "Failed to mount DFS namespace");
if (o->prefix) {
rc = dfs_set_prefix(dfs, o->prefix);
DCHECK(rc, "Failed to set DFS Prefix");
}
dfs_init = true;
}
static void
DFS_Finalize()
DFS_Finalize(aiori_mod_opt_t *options)
{
DFS_options_t *o = (DFS_options_t *)options;
int rc;
MPI_Barrier(MPI_COMM_WORLD);
@ -447,16 +506,16 @@ DFS_Finalize()
MPI_Barrier(MPI_COMM_WORLD);
rc = daos_cont_close(coh, NULL);
DCHECK(rc, "Failed to close container %s (%d)", o.cont, rc);
DCHECK(rc, "Failed to close container %s (%d)", o->cont, rc);
MPI_Barrier(MPI_COMM_WORLD);
if (o.destroy) {
if (o->destroy) {
if (rank == 0) {
uuid_t uuid;
double t1, t2;
INFO(VERBOSE_1, "Destorying DFS Container: %s\n", o.cont);
uuid_parse(o.cont, uuid);
INFO(VERBOSE_1, "Destorying DFS Container: %s\n", o->cont);
uuid_parse(o->cont, uuid);
t1 = MPI_Wtime();
rc = daos_cont_destroy(poh, uuid, 1, NULL);
t2 = MPI_Wtime();
@ -467,7 +526,7 @@ DFS_Finalize()
MPI_Bcast(&rc, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (rc) {
if (rank == 0)
DCHECK(rc, "Failed to destroy container %s (%d)", o.cont, rc);
DCHECK(rc, "Failed to destroy container %s (%d)", o->cont, rc);
MPI_Abort(MPI_COMM_WORLD, -1);
}
}
@ -485,45 +544,58 @@ DFS_Finalize()
rc = daos_fini();
DCHECK(rc, "Failed to finalize DAOS");
/** reset tunables */
o->pool = NULL;
o->svcl = NULL;
o->group = NULL;
o->cont = NULL;
o->chunk_size = 1048576;
o->oclass = NULL;
o->dir_oclass = NULL;
o->prefix = NULL;
o->destroy = 0;
objectClass = OC_SX;
dir_oclass = OC_SX;
dfs_init = false;
}
/*
* Creat and open a file through the DFS interface.
*/
static void *
DFS_Create(char *testFileName, IOR_param_t *param)
static aiori_fd_t *
DFS_Create(char *testFileName, int flags, aiori_mod_opt_t *param)
{
DFS_options_t *o = (DFS_options_t*) param;
char *name = NULL, *dir_name = NULL;
dfs_obj_t *obj = NULL, *parent = NULL;
mode_t mode;
mode_t mode = 0664;
int fd_oflag = 0;
int rc;
assert(param);
rc = parse_filename(testFileName, &name, &dir_name);
DCHECK(rc, "Failed to parse path %s", testFileName);
assert(dir_name);
assert(name);
parent = lookup_insert_dir(dir_name);
parent = lookup_insert_dir(dir_name, NULL);
if (parent == NULL)
GERR("Failed to lookup parent dir");
mode = S_IFREG | param->mode;
if (param->filePerProc || rank == 0) {
mode = S_IFREG | mode;
if (hints->filePerProc || rank == 0) {
fd_oflag |= O_CREAT | O_RDWR | O_EXCL;
rc = dfs_open(dfs, parent, name, mode, fd_oflag,
objectClass, o.chunk_size, NULL, &obj);
objectClass, o->chunk_size, NULL, &obj);
DCHECK(rc, "dfs_open() of %s Failed", name);
}
if (!param->filePerProc) {
if (!hints->filePerProc) {
MPI_Barrier(MPI_COMM_WORLD);
if (rank != 0) {
fd_oflag |= O_RDWR;
rc = dfs_open(dfs, parent, name, mode, fd_oflag,
objectClass, o.chunk_size, NULL, &obj);
objectClass, o->chunk_size, NULL, &obj);
DCHECK(rc, "dfs_open() of %s Failed", name);
}
}
@ -533,36 +605,36 @@ DFS_Create(char *testFileName, IOR_param_t *param)
if (dir_name)
free(dir_name);
return ((void *)obj);
return (aiori_fd_t *)(obj);
}
/*
* Open a file through the DFS interface.
*/
static void *
DFS_Open(char *testFileName, IOR_param_t *param)
static aiori_fd_t *
DFS_Open(char *testFileName, int flags, aiori_mod_opt_t *param)
{
DFS_options_t *o = (DFS_options_t*) param;
char *name = NULL, *dir_name = NULL;
dfs_obj_t *obj = NULL, *parent = NULL;
mode_t mode;
int rc;
mode_t mode = 0664;
int fd_oflag = 0;
int rc;
fd_oflag |= O_RDWR;
mode = S_IFREG | param->mode;
mode = S_IFREG | flags;
rc = parse_filename(testFileName, &name, &dir_name);
DCHECK(rc, "Failed to parse path %s", testFileName);
assert(dir_name);
assert(name);
parent = lookup_insert_dir(dir_name);
parent = lookup_insert_dir(dir_name, NULL);
if (parent == NULL)
GERR("Failed to lookup parent dir");
rc = dfs_open(dfs, parent, name, mode, fd_oflag, objectClass,
o.chunk_size, NULL, &obj);
o->chunk_size, NULL, &obj);
DCHECK(rc, "dfs_open() of %s Failed", name);
if (name)
@ -570,15 +642,15 @@ DFS_Open(char *testFileName, IOR_param_t *param)
if (dir_name)
free(dir_name);
return ((void *)obj);
return (aiori_fd_t *)(obj);
}
/*
* Write or read access to file using the DFS interface.
*/
static IOR_offset_t
DFS_Xfer(int access, void *file, IOR_size_t *buffer, IOR_offset_t length,
IOR_param_t *param)
DFS_Xfer(int access, aiori_fd_t *file, IOR_size_t *buffer, IOR_offset_t length,
IOR_offset_t off, aiori_mod_opt_t *param)
{
int xferRetries = 0;
long long remaining = (long long)length;
@ -601,20 +673,20 @@ DFS_Xfer(int access, void *file, IOR_size_t *buffer, IOR_offset_t length,
/* write/read file */
if (access == WRITE) {
rc = dfs_write(dfs, obj, &sgl, param->offset, NULL);
rc = dfs_write(dfs, obj, &sgl, off, NULL);
if (rc) {
fprintf(stderr, "dfs_write() failed (%d)", rc);
return -1;
}
ret = remaining;
} else {
rc = dfs_read(dfs, obj, &sgl, param->offset, &ret, NULL);
rc = dfs_read(dfs, obj, &sgl, off, &ret, NULL);
if (rc || ret == 0)
fprintf(stderr, "dfs_read() failed(%d)", rc);
}
if (ret < remaining) {
if (param->singleXferAttempt == TRUE)
if (hints->singleXferAttempt == TRUE)
exit(-1);
if (xferRetries > MAX_RETRY)
ERR("too many retries -- aborting");
@ -634,8 +706,20 @@ DFS_Xfer(int access, void *file, IOR_size_t *buffer, IOR_offset_t length,
* Perform fsync().
*/
static void
DFS_Fsync(void *fd, IOR_param_t * param)
DFS_Fsync(aiori_fd_t *fd, aiori_mod_opt_t * param)
{
/* no cache in DFS, so this is a no-op currently */
dfs_sync(dfs);
return;
}
/*
* Perform sync() on the dfs mount.
*/
static void
DFS_Sync(aiori_mod_opt_t * param)
{
/* no cache in DFS, so this is a no-op currently */
dfs_sync(dfs);
return;
}
@ -644,7 +728,7 @@ DFS_Fsync(void *fd, IOR_param_t * param)
* Close a file through the DFS interface.
*/
static void
DFS_Close(void *fd, IOR_param_t * param)
DFS_Close(aiori_fd_t *fd, aiori_mod_opt_t * param)
{
dfs_release((dfs_obj_t *)fd);
}
@ -653,7 +737,7 @@ DFS_Close(void *fd, IOR_param_t * param)
* Delete a file through the DFS interface.
*/
static void
DFS_Delete(char *testFileName, IOR_param_t * param)
DFS_Delete(char *testFileName, aiori_mod_opt_t * param)
{
char *name = NULL, *dir_name = NULL;
dfs_obj_t *parent = NULL;
@ -665,7 +749,7 @@ DFS_Delete(char *testFileName, IOR_param_t * param)
assert(dir_name);
assert(name);
parent = lookup_insert_dir(dir_name);
parent = lookup_insert_dir(dir_name, NULL);
if (parent == NULL)
GERR("Failed to lookup parent dir");
@ -690,7 +774,7 @@ static char* DFS_GetVersion()
* Use DFS stat() to return aggregate file size.
*/
static IOR_offset_t
DFS_GetFileSize(IOR_param_t * test, MPI_Comm comm, char *testFileName)
DFS_GetFileSize(aiori_mod_opt_t * test, MPI_Comm comm, char *testFileName)
{
dfs_obj_t *obj;
daos_size_t fsize, tmpMin, tmpMax, tmpSum;
@ -708,7 +792,7 @@ DFS_GetFileSize(IOR_param_t * test, MPI_Comm comm, char *testFileName)
dfs_release(obj);
if (test->filePerProc == TRUE) {
if (hints->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&fsize, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, comm),
"cannot total data moved");
@ -733,13 +817,13 @@ DFS_GetFileSize(IOR_param_t * test, MPI_Comm comm, char *testFileName)
}
static int
DFS_Statfs(const char *path, ior_aiori_statfs_t *sfs, IOR_param_t * param)
DFS_Statfs(const char *path, ior_aiori_statfs_t *sfs, aiori_mod_opt_t * param)
{
return 0;
}
static int
DFS_Mkdir(const char *path, mode_t mode, IOR_param_t * param)
DFS_Mkdir(const char *path, mode_t mode, aiori_mod_opt_t * param)
{
dfs_obj_t *parent = NULL;
char *name = NULL, *dir_name = NULL;
@ -752,24 +836,22 @@ DFS_Mkdir(const char *path, mode_t mode, IOR_param_t * param)
if (!name)
return 0;
parent = lookup_insert_dir(dir_name);
parent = lookup_insert_dir(dir_name, NULL);
if (parent == NULL)
GERR("Failed to lookup parent dir");
rc = dfs_mkdir(dfs, parent, name, mode);
rc = dfs_mkdir(dfs, parent, name, mode, dir_oclass);
DCHECK(rc, "dfs_mkdir() of %s Failed", name);
if (name)
free(name);
if (dir_name)
free(dir_name);
if (rc)
return -1;
return rc;
}
static int
DFS_Rmdir(const char *path, IOR_param_t * param)
DFS_Rmdir(const char *path, aiori_mod_opt_t * param)
{
dfs_obj_t *parent = NULL;
char *name = NULL, *dir_name = NULL;
@ -781,7 +863,7 @@ DFS_Rmdir(const char *path, IOR_param_t * param)
assert(dir_name);
assert(name);
parent = lookup_insert_dir(dir_name);
parent = lookup_insert_dir(dir_name, NULL);
if (parent == NULL)
GERR("Failed to lookup parent dir");
@ -798,39 +880,24 @@ DFS_Rmdir(const char *path, IOR_param_t * param)
}
static int
DFS_Access(const char *path, int mode, IOR_param_t * param)
DFS_Access(const char *path, int mode, aiori_mod_opt_t * param)
{
dfs_obj_t *parent = NULL;
char *name = NULL, *dir_name = NULL;
struct stat stbuf;
int rc;
dfs_obj_t *obj = NULL;
mode_t fmode;
rc = parse_filename(path, &name, &dir_name);
DCHECK(rc, "Failed to parse path %s", path);
assert(dir_name);
parent = lookup_insert_dir(dir_name);
if (parent == NULL)
GERR("Failed to lookup parent dir");
if (name && strcmp(name, ".") == 0) {
free(name);
name = NULL;
}
rc = dfs_stat(dfs, parent, name, &stbuf);
if (name)
free(name);
if (dir_name)
free(dir_name);
if (rc)
obj = lookup_insert_dir(path, &fmode);
if (obj == NULL)
return -1;
return rc;
/** just close if it's a file */
if (S_ISREG(fmode))
dfs_release(obj);
return 0;
}
static int
DFS_Stat(const char *path, struct stat *buf, IOR_param_t * param)
DFS_Stat(const char *path, struct stat *buf, aiori_mod_opt_t * param)
{
dfs_obj_t *parent = NULL;
char *name = NULL, *dir_name = NULL;
@ -842,7 +909,7 @@ DFS_Stat(const char *path, struct stat *buf, IOR_param_t * param)
assert(dir_name);
assert(name);
parent = lookup_insert_dir(dir_name);
parent = lookup_insert_dir(dir_name, NULL);
if (parent == NULL)
GERR("Failed to lookup parent dir");

View File

@ -25,7 +25,7 @@ typedef struct {
static char * current = (char*) 1;
static option_help * DUMMY_options(void ** init_backend_options, void * init_values){
static option_help * DUMMY_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * init_values){
dummy_options_t * o = malloc(sizeof(dummy_options_t));
if (init_values != NULL){
memcpy(o, init_values, sizeof(dummy_options_t));
@ -33,7 +33,7 @@ static option_help * DUMMY_options(void ** init_backend_options, void * init_val
memset(o, 0, sizeof(dummy_options_t));
}
*init_backend_options = o;
*init_backend_options = (aiori_mod_opt_t*) o;
option_help h [] = {
{0, "dummy.delay-create", "Delay per create in usec", OPTION_OPTIONAL_ARGUMENT, 'l', & o->delay_creates},
@ -46,44 +46,57 @@ 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 aiori_fd_t *DUMMY_Create(char *testFileName, int iorflags, aiori_mod_opt_t * options)
{
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*) options;
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)};
nanosleep( & wait, NULL);
}
}
return current++;
return (aiori_fd_t*) current++;
}
static void *DUMMY_Open(char *testFileName, IOR_param_t * param)
static aiori_fd_t *DUMMY_Open(char *testFileName, int flags, aiori_mod_opt_t * options)
{
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++;
return (aiori_fd_t*) current++;
}
static void DUMMY_Fsync(void *fd, IOR_param_t * param)
static void DUMMY_Fsync(aiori_fd_t *fd, aiori_mod_opt_t * options)
{
if(verbose > 4){
fprintf(out_logfile, "DUMMY fsync %p\n", fd);
}
}
static void DUMMY_Close(void *fd, IOR_param_t * param)
static void DUMMY_Sync(aiori_mod_opt_t * options)
{
}
static void DUMMY_Close(aiori_fd_t *fd, aiori_mod_opt_t * options)
{
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, aiori_mod_opt_t * options)
{
if(verbose > 4){
fprintf(out_logfile, "DUMMY delete: %s\n", testFileName);
@ -95,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(aiori_mod_opt_t * options, MPI_Comm testComm, char *testFileName)
{
if(verbose > 4){
fprintf(out_logfile, "DUMMY getFileSize: %s\n", testFileName);
@ -103,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, aiori_fd_t *file, IOR_size_t * buffer, IOR_offset_t length, IOR_offset_t offset, aiori_mod_opt_t * options){
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*) options;
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)};
@ -117,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, aiori_mod_opt_t * options){
stat->f_bsize = 1;
stat->f_blocks = 1;
stat->f_bfree = 1;
@ -127,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, aiori_mod_opt_t * options){
return 0;
}
static int DUMMY_rmdir (const char *path, IOR_param_t * param){
static int DUMMY_rmdir (const char *path, aiori_mod_opt_t * options){
return 0;
}
static int DUMMY_access (const char *path, int mode, IOR_param_t * param){
static int DUMMY_access (const char *path, int mode, aiori_mod_opt_t * options){
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, aiori_mod_opt_t * options){
return 0;
}
static int DUMMY_check_params(IOR_param_t * test){
return 1;
static int DUMMY_check_params(aiori_mod_opt_t * options){
return 0;
}
static void DUMMY_init(aiori_mod_opt_t * options){
WARN("DUMMY initialized");
count_init++;
}
static void DUMMY_final(aiori_mod_opt_t * 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,
@ -163,9 +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
.check_params = DUMMY_check_params,
.sync = DUMMY_Sync,
.enable_mdtest = true
};

View File

@ -81,39 +81,53 @@
#endif /* H5_VERS_MAJOR > 1 && H5_VERS_MINOR > 6 */
/**************************** P R O T O T Y P E S *****************************/
static IOR_offset_t SeekOffset(void *, IOR_offset_t, IOR_param_t *);
static void SetupDataSet(void *, IOR_param_t *);
static void *HDF5_Create(char *, IOR_param_t *);
static void *HDF5_Open(char *, IOR_param_t *);
static IOR_offset_t HDF5_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void HDF5_Close(void *, IOR_param_t *);
static void HDF5_Delete(char *, IOR_param_t *);
static IOR_offset_t SeekOffset(void *, IOR_offset_t, aiori_mod_opt_t *);
static void SetupDataSet(void *, int flags, aiori_mod_opt_t *);
static aiori_fd_t *HDF5_Create(char *, int flags, aiori_mod_opt_t *);
static aiori_fd_t *HDF5_Open(char *, int flags, aiori_mod_opt_t *);
static IOR_offset_t HDF5_Xfer(int, aiori_fd_t *, IOR_size_t *,
IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *);
static void HDF5_Close(aiori_fd_t *, aiori_mod_opt_t *);
static void HDF5_Delete(char *, aiori_mod_opt_t *);
static char* HDF5_GetVersion();
static void HDF5_Fsync(void *, IOR_param_t *);
static IOR_offset_t HDF5_GetFileSize(IOR_param_t *, MPI_Comm, char *);
static int HDF5_Access(const char *, int, IOR_param_t *);
static void HDF5_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static IOR_offset_t HDF5_GetFileSize(aiori_mod_opt_t *, MPI_Comm, char *);
static int HDF5_Access(const char *, int, aiori_mod_opt_t *);
static void HDF5_init_xfer_options(aiori_xfer_hint_t * params);
static int HDF5_check_params(aiori_mod_opt_t * options);
/************************** O P T I O N S *****************************/
typedef struct{
int collective_md;
char * hintsFileName; /* full name for hints file */
int showHints; /* show hints */
int individualDataSets; /* datasets not shared by all procs */
int noFill; /* no fill in file creation */
IOR_offset_t setAlignment; /* alignment in bytes */
} HDF5_options_t;
/***************************** F U N C T I O N S ******************************/
static option_help * HDF5_options(void ** init_backend_options, void * init_values){
static option_help * HDF5_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * init_values){
HDF5_options_t * o = malloc(sizeof(HDF5_options_t));
if (init_values != NULL){
memcpy(o, init_values, sizeof(HDF5_options_t));
}else{
memset(o, 0, sizeof(HDF5_options_t));
/* initialize the options properly */
o->collective_md = 0;
o->setAlignment = 1;
}
*init_backend_options = o;
*init_backend_options = (aiori_mod_opt_t*) o;
option_help h [] = {
{0, "hdf5.collectiveMetadata", "Use collectiveMetadata (available since HDF5-1.10.0)", OPTION_FLAG, 'd', & o->collective_md},
{0, "hdf5.hintsFileName","Full name for hints file", OPTION_OPTIONAL_ARGUMENT, 's', & o->hintsFileName},
{0, "hdf5.showHints", "Show MPI hints", OPTION_FLAG, 'd', & o->showHints},
{0, "hdf5.individualDataSets", "Datasets not shared by all procs [not working]", OPTION_FLAG, 'd', & o->individualDataSets},
{0, "hdf5.setAlignment", "HDF5 alignment in bytes (e.g.: 8, 4k, 2m, 1g)", OPTION_OPTIONAL_ARGUMENT, 'd', & o->setAlignment},
{0, "hdf5.noFill", "No fill in HDF5 file creation", OPTION_FLAG, 'd', & o->noFill},
LAST_OPTION
};
option_help * help = malloc(sizeof(h));
@ -133,6 +147,7 @@ ior_aiori_t hdf5_aiori = {
.close = HDF5_Close,
.delete = HDF5_Delete,
.get_version = HDF5_GetVersion,
.xfer_hints = HDF5_init_xfer_options,
.fsync = HDF5_Fsync,
.get_file_size = HDF5_GetFileSize,
.statfs = aiori_posix_statfs,
@ -140,7 +155,8 @@ ior_aiori_t hdf5_aiori = {
.rmdir = aiori_posix_rmdir,
.access = HDF5_Access,
.stat = aiori_posix_stat,
.get_options = HDF5_options
.get_options = HDF5_options,
.check_params = HDF5_check_params
};
static hid_t xferPropList; /* xfer property list */
@ -151,20 +167,47 @@ hid_t memDataSpace; /* memory data space id */
int newlyOpenedFile; /* newly opened file */
/***************************** F U N C T I O N S ******************************/
static aiori_xfer_hint_t * hints = NULL;
static void HDF5_init_xfer_options(aiori_xfer_hint_t * params){
hints = params;
}
static int HDF5_check_params(aiori_mod_opt_t * options){
HDF5_options_t *o = (HDF5_options_t*) options;
if (o->setAlignment < 0)
ERR("alignment must be non-negative integer");
if (o->individualDataSets)
ERR("individual data sets not implemented");
if (o->noFill) {
/* check if hdf5 available */
#if defined (H5_VERS_MAJOR) && defined (H5_VERS_MINOR)
/* no-fill option not available until hdf5-1.6.x */
#if (H5_VERS_MAJOR > 0 && H5_VERS_MINOR > 5)
#else
ERRF("'no fill' option not available in HDF5");
#endif
#else
WARN("unable to determine HDF5 version for 'no fill' usage");
#endif
}
return 0;
}
/*
* Create and open a file through the HDF5 interface.
*/
static void *HDF5_Create(char *testFileName, IOR_param_t * param)
static aiori_fd_t *HDF5_Create(char *testFileName, int flags, aiori_mod_opt_t * param)
{
return HDF5_Open(testFileName, param);
return HDF5_Open(testFileName, flags, param);
}
/*
* Open a file through the HDF5 interface.
*/
static void *HDF5_Open(char *testFileName, IOR_param_t * param)
static aiori_fd_t *HDF5_Open(char *testFileName, int flags, aiori_mod_opt_t * param)
{
HDF5_options_t *o = (HDF5_options_t*) param;
hid_t accessPropList, createPropList;
hsize_t memStart[NUM_DIMS],
dataSetDims[NUM_DIMS],
@ -182,36 +225,27 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
/*
* HDF5 uses different flags than those for POSIX/MPIIO
*/
if (param->open == WRITE) { /* WRITE flags */
param->openFlags = IOR_TRUNC;
} else { /* READ or check WRITE/READ flags */
param->openFlags = IOR_RDONLY;
}
/* set IOR file flags to HDF5 flags */
/* -- file open flags -- */
if (param->openFlags & IOR_RDONLY) {
if (flags & IOR_RDONLY) {
fd_mode |= H5F_ACC_RDONLY;
}
if (param->openFlags & IOR_WRONLY) {
fprintf(stdout, "File write only not implemented in HDF5\n");
}
if (param->openFlags & IOR_RDWR) {
if (flags & IOR_WRONLY || flags & IOR_RDWR) {
fd_mode |= H5F_ACC_RDWR;
}
if (param->openFlags & IOR_APPEND) {
if (flags & IOR_APPEND) {
fprintf(stdout, "File append not implemented in HDF5\n");
}
if (param->openFlags & IOR_CREAT) {
if (flags & IOR_CREAT) {
fd_mode |= H5F_ACC_CREAT;
}
if (param->openFlags & IOR_EXCL) {
if (flags & IOR_EXCL) {
fd_mode |= H5F_ACC_EXCL;
}
if (param->openFlags & IOR_TRUNC) {
if (flags & IOR_TRUNC) {
fd_mode |= H5F_ACC_TRUNC;
}
if (param->openFlags & IOR_DIRECT) {
if (flags & IOR_DIRECT) {
fprintf(stdout, "O_DIRECT not implemented in HDF5\n");
}
@ -231,13 +265,13 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
* someday HDF5 implementation will allow subsets of MPI_COMM_WORLD
*/
/* store MPI communicator info for the file access property list */
if (param->filePerProc) {
if (hints->filePerProc) {
comm = MPI_COMM_SELF;
} else {
comm = testComm;
}
SetHints(&mpiHints, param->hintsFileName);
SetHints(&mpiHints, o->hintsFileName);
/*
* note that with MP_HINTS_FILTERED=no, all key/value pairs will
* be in the info object. The info object that is attached to
@ -245,7 +279,7 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
* deemed valid by the implementation.
*/
/* show hints passed to file */
if (rank == 0 && param->showHints) {
if (rank == 0 && o->showHints) {
fprintf(stdout, "\nhints passed to access property list {\n");
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
@ -254,12 +288,11 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
"cannot set file access property list");
/* set alignment */
HDF5_CHECK(H5Pset_alignment(accessPropList, param->setAlignment,
param->setAlignment),
HDF5_CHECK(H5Pset_alignment(accessPropList, o->setAlignment, o->setAlignment),
"cannot set alignment");
#ifdef HAVE_H5PSET_ALL_COLL_METADATA_OPS
HDF5_options_t *o = (HDF5_options_t*) param->backend_options;
if (o->collective_md) {
/* more scalable metadata */
@ -271,10 +304,9 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
#endif
/* open file */
if(! param->dryRun){
if (param->open == WRITE) { /* WRITE */
*fd = H5Fcreate(testFileName, fd_mode,
createPropList, accessPropList);
if(! hints->dryRun){
if (flags & IOR_CREAT) { /* WRITE */
*fd = H5Fcreate(testFileName, H5F_ACC_TRUNC, createPropList, accessPropList);
HDF5_CHECK(*fd, "cannot create file");
} else { /* READ or CHECK */
*fd = H5Fopen(testFileName, fd_mode, accessPropList);
@ -283,9 +315,8 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
}
/* show hints actually attached to file handle */
if (param->showHints || (1) /* WEL - this needs fixing */ ) {
if (rank == 0
&& (param->showHints) /* WEL - this needs fixing */ ) {
if (o->showHints || (1) /* WEL - this needs fixing */ ) {
if (rank == 0 && (o->showHints) /* WEL - this needs fixing */ ) {
WARN("showHints not working for HDF5");
}
} else {
@ -334,7 +365,7 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
HDF5_CHECK(xferPropList, "cannot create transfer property list");
/* set data transfer mode */
if (param->collective) {
if (hints->collective) {
HDF5_CHECK(H5Pset_dxpl_mpio(xferPropList, H5FD_MPIO_COLLECTIVE),
"cannot set collective data transfer mode");
} else {
@ -346,9 +377,9 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
/* set up memory data space for transfer */
memStart[0] = (hsize_t) 0;
memCount[0] = (hsize_t) 1;
memStride[0] = (hsize_t) (param->transferSize / sizeof(IOR_size_t));
memBlock[0] = (hsize_t) (param->transferSize / sizeof(IOR_size_t));
memDataSpaceDims[0] = (hsize_t) param->transferSize;
memStride[0] = (hsize_t) (hints->transferSize / sizeof(IOR_size_t));
memBlock[0] = (hsize_t) (hints->transferSize / sizeof(IOR_size_t));
memDataSpaceDims[0] = (hsize_t) hints->transferSize;
memDataSpace = H5Screate_simple(NUM_DIMS, memDataSpaceDims, NULL);
HDF5_CHECK(memDataSpace, "cannot create simple memory data space");
@ -358,18 +389,18 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
memBlock), "cannot create hyperslab");
/* set up parameters for fpp or different dataset count */
if (param->filePerProc) {
if (hints->filePerProc) {
tasksPerDataSet = 1;
} else {
if (param->individualDataSets) {
if (o->individualDataSets) {
/* each task in segment has single data set */
tasksPerDataSet = 1;
} else {
/* share single data set across all tasks in segment */
tasksPerDataSet = param->numTasks;
tasksPerDataSet = hints->numTasks;
}
}
dataSetDims[0] = (hsize_t) ((param->blockSize / sizeof(IOR_size_t))
dataSetDims[0] = (hsize_t) ((hints->blockSize / sizeof(IOR_size_t))
* tasksPerDataSet);
/* create a simple data space containing information on size
@ -379,14 +410,14 @@ static void *HDF5_Open(char *testFileName, IOR_param_t * param)
if (mpiHints != MPI_INFO_NULL)
MPI_Info_free(&mpiHints);
return (fd);
return (aiori_fd_t*)(fd);
}
/*
* Write or read access to file using the HDF5 interface.
*/
static IOR_offset_t HDF5_Xfer(int access, void *fd, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param)
static IOR_offset_t HDF5_Xfer(int access, aiori_fd_t *fd, IOR_size_t * buffer,
IOR_offset_t length, IOR_offset_t offset, aiori_mod_opt_t * param)
{
static int firstReadCheck = FALSE, startNewDataSet;
IOR_offset_t segmentPosition, segmentSize;
@ -405,17 +436,16 @@ static IOR_offset_t HDF5_Xfer(int access, void *fd, IOR_size_t * buffer,
}
/* determine by offset if need to start new data set */
if (param->filePerProc == TRUE) {
if (hints->filePerProc == TRUE) {
segmentPosition = (IOR_offset_t) 0;
segmentSize = param->blockSize;
segmentSize = hints->blockSize;
} else {
segmentPosition =
(IOR_offset_t) ((rank + rankOffset) % param->numTasks)
* param->blockSize;
segmentSize =
(IOR_offset_t) (param->numTasks) * param->blockSize;
(IOR_offset_t) ((rank + rankOffset) % hints->numTasks)
* hints->blockSize;
segmentSize = (IOR_offset_t) (hints->numTasks) * hints->blockSize;
}
if ((IOR_offset_t) ((param->offset - segmentPosition) % segmentSize) ==
if ((IOR_offset_t) ((offset - segmentPosition) % segmentSize) ==
0) {
/*
* ordinarily start a new data set, unless this is the
@ -427,7 +457,7 @@ static IOR_offset_t HDF5_Xfer(int access, void *fd, IOR_size_t * buffer,
}
}
if(param->dryRun)
if(hints->dryRun)
return length;
/* create new data set */
@ -438,10 +468,10 @@ static IOR_offset_t HDF5_Xfer(int access, void *fd, IOR_size_t * buffer,
HDF5_CHECK(H5Sclose(fileDataSpace),
"cannot close file data space");
}
SetupDataSet(fd, param);
SetupDataSet(fd, access == WRITE ? IOR_CREAT : IOR_RDWR, param);
}
SeekOffset(fd, param->offset, param);
SeekOffset(fd, offset, param);
/* this is necessary to reset variables for reaccessing file */
startNewDataSet = FALSE;
@ -465,19 +495,18 @@ static IOR_offset_t HDF5_Xfer(int access, void *fd, IOR_size_t * buffer,
/*
* Perform fsync().
*/
static void HDF5_Fsync(void *fd, IOR_param_t * param)
static void HDF5_Fsync(aiori_fd_t *fd, aiori_mod_opt_t * param)
{
;
}
/*
* Close a file through the HDF5 interface.
*/
static void HDF5_Close(void *fd, IOR_param_t * param)
static void HDF5_Close(aiori_fd_t *fd, aiori_mod_opt_t * param)
{
if(param->dryRun)
if(hints->dryRun)
return;
if (param->fd_fppReadCheck == NULL) {
//if (hints->fd_fppReadCheck == NULL) {
HDF5_CHECK(H5Dclose(dataSet), "cannot close data set");
HDF5_CHECK(H5Sclose(dataSpace), "cannot close data space");
HDF5_CHECK(H5Sclose(fileDataSpace),
@ -486,7 +515,7 @@ static void HDF5_Close(void *fd, IOR_param_t * param)
"cannot close memory data space");
HDF5_CHECK(H5Pclose(xferPropList),
" cannot close transfer property list");
}
//}
HDF5_CHECK(H5Fclose(*(hid_t *) fd), "cannot close file");
free(fd);
}
@ -494,9 +523,9 @@ static void HDF5_Close(void *fd, IOR_param_t * param)
/*
* Delete a file through the HDF5 interface.
*/
static void HDF5_Delete(char *testFileName, IOR_param_t * param)
static void HDF5_Delete(char *testFileName, aiori_mod_opt_t * param)
{
if(param->dryRun)
if(hints->dryRun)
return
MPIIO_Delete(testFileName, param);
return;
@ -528,23 +557,24 @@ static char * HDF5_GetVersion()
* Seek to offset in file using the HDF5 interface and set up hyperslab.
*/
static IOR_offset_t SeekOffset(void *fd, IOR_offset_t offset,
IOR_param_t * param)
aiori_mod_opt_t * param)
{
HDF5_options_t *o = (HDF5_options_t*) param;
IOR_offset_t segmentSize;
hsize_t hsStride[NUM_DIMS], hsCount[NUM_DIMS], hsBlock[NUM_DIMS];
hsize_t hsStart[NUM_DIMS];
if (param->filePerProc == TRUE) {
segmentSize = (IOR_offset_t) param->blockSize;
if (hints->filePerProc == TRUE) {
segmentSize = (IOR_offset_t) hints->blockSize;
} else {
segmentSize =
(IOR_offset_t) (param->numTasks) * param->blockSize;
(IOR_offset_t) (hints->numTasks) * hints->blockSize;
}
/* create a hyperslab representing the file data space */
if (param->individualDataSets) {
if (o->individualDataSets) {
/* start at zero offset if not */
hsStart[0] = (hsize_t) ((offset % param->blockSize)
hsStart[0] = (hsize_t) ((offset % hints->blockSize)
/ sizeof(IOR_size_t));
} else {
/* start at a unique offset if shared */
@ -552,8 +582,8 @@ static IOR_offset_t SeekOffset(void *fd, IOR_offset_t offset,
(hsize_t) ((offset % segmentSize) / sizeof(IOR_size_t));
}
hsCount[0] = (hsize_t) 1;
hsStride[0] = (hsize_t) (param->transferSize / sizeof(IOR_size_t));
hsBlock[0] = (hsize_t) (param->transferSize / sizeof(IOR_size_t));
hsStride[0] = (hsize_t) (hints->transferSize / sizeof(IOR_size_t));
hsBlock[0] = (hsize_t) (hints->transferSize / sizeof(IOR_size_t));
/* retrieve data space from data set for hyperslab */
fileDataSpace = H5Dget_space(dataSet);
@ -567,8 +597,9 @@ static IOR_offset_t SeekOffset(void *fd, IOR_offset_t offset,
/*
* Create HDF5 data set.
*/
static void SetupDataSet(void *fd, IOR_param_t * param)
static void SetupDataSet(void *fd, int flags, aiori_mod_opt_t * param)
{
HDF5_options_t *o = (HDF5_options_t*) param;
char dataSetName[MAX_STR];
hid_t dataSetPropList;
int dataSetID;
@ -582,8 +613,8 @@ static void SetupDataSet(void *fd, IOR_param_t * param)
dataSetSuffix = 0;
/* may want to use individual access to each data set someday */
if (param->individualDataSets) {
dataSetID = (rank + rankOffset) % param->numTasks;
if (o->individualDataSets) {
dataSetID = (rank + rankOffset) % hints->numTasks;
} else {
dataSetID = 0;
}
@ -591,14 +622,14 @@ static void SetupDataSet(void *fd, IOR_param_t * param)
sprintf(dataSetName, "%s-%04d.%04d", "Dataset", dataSetID,
dataSetSuffix++);
if (param->open == WRITE) { /* WRITE */
if (flags & IOR_CREAT) { /* WRITE */
/* create data set */
dataSetPropList = H5Pcreate(H5P_DATASET_CREATE);
/* check if hdf5 available */
#if defined (H5_VERS_MAJOR) && defined (H5_VERS_MINOR)
/* no-fill option not available until hdf5-1.6.x */
#if (H5_VERS_MAJOR > 0 && H5_VERS_MINOR > 5)
if (param->noFill == TRUE) {
if (o->noFill == TRUE) {
if (rank == 0 && verbose >= VERBOSE_1) {
fprintf(stdout, "\nusing 'no fill' option\n");
}
@ -629,9 +660,9 @@ static void SetupDataSet(void *fd, IOR_param_t * param)
* Use MPIIO call to get file size.
*/
static IOR_offset_t
HDF5_GetFileSize(IOR_param_t * test, MPI_Comm testComm, char *testFileName)
HDF5_GetFileSize(aiori_mod_opt_t * test, MPI_Comm testComm, char *testFileName)
{
if(test->dryRun)
if(hints->dryRun)
return 0;
return(MPIIO_GetFileSize(test, testComm, testFileName));
}
@ -639,9 +670,9 @@ HDF5_GetFileSize(IOR_param_t * test, MPI_Comm testComm, char *testFileName)
/*
* Use MPIIO call to check for access.
*/
static int HDF5_Access(const char *path, int mode, IOR_param_t *param)
static int HDF5_Access(const char *path, int mode, aiori_mod_opt_t *param)
{
if(param->dryRun)
if(hints->dryRun)
return 0;
return(MPIIO_Access(path, mode, param));
}

View File

@ -51,6 +51,12 @@ static int IME_StatFS(const char *, ior_aiori_statfs_t *,
static int IME_RmDir(const char *, IOR_param_t *);
static int IME_MkDir(const char *, mode_t, IOR_param_t *);
static int IME_Stat(const char *, struct stat *, IOR_param_t *);
#if (IME_NATIVE_API_VERSION >= 132)
static int IME_Mknod(char *);
static void IME_Sync(IOR_param_t *);
#endif
static void IME_Initialize();
static void IME_Finalize();
@ -107,6 +113,10 @@ ior_aiori_t ime_aiori = {
.initialize = IME_Initialize,
.finalize = IME_Finalize,
.get_options = IME_options,
#if (IME_NATIVE_API_VERSION >= 132)
.sync = IME_Sync,
.mknod = IME_Mknod,
#endif
.enable_mdtest = true,
};
@ -406,3 +416,27 @@ static IOR_offset_t IME_GetFileSize(IOR_param_t *test, MPI_Comm testComm,
return(aggFileSizeFromStat);
}
#if (IME_NATIVE_API_VERSION >= 132)
/*
* Create a file through mknod interface.
*/
static int IME_Mknod(char *testFileName)
{
int ret = ime_native_mknod(testFileName, S_IFREG | S_IRUSR, 0);
if (ret < 0)
ERR("mknod failed");
return ret;
}
/*
* Use IME sync to flush page cache of all opened files.
*/
static void IME_Sync(IOR_param_t * param)
{
int ret = ime_native_sync(0);
if (ret != 0)
FAIL("Error executing the sync command.");
}
#endif

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 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 *);
static option_help * MMAP_options(void ** init_backend_options, void * init_values);
static aiori_fd_t *MMAP_Create(char *, int flags, aiori_mod_opt_t *);
static aiori_fd_t *MMAP_Open(char *, int flags, aiori_mod_opt_t *);
static IOR_offset_t MMAP_Xfer(int, aiori_fd_t *, IOR_size_t *,
IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *);
static void MMAP_Close(aiori_fd_t *, aiori_mod_opt_t *);
static void MMAP_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static option_help * MMAP_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * init_values);
static void MMAP_xfer_hints(aiori_xfer_hint_t * params);
static int MMAP_check_params(aiori_mod_opt_t * 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,
.xfer_hints = MMAP_xfer_hints,
.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 ******************************/
@ -58,7 +61,7 @@ typedef struct{
int madv_pattern;
} mmap_options_t;
static option_help * MMAP_options(void ** init_backend_options, void * init_values){
static option_help * MMAP_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * init_values){
mmap_options_t * o = malloc(sizeof(mmap_options_t));
if (init_values != NULL){
@ -67,7 +70,7 @@ static option_help * MMAP_options(void ** init_backend_options, void * init_valu
memset(o, 0, sizeof(mmap_options_t));
}
*init_backend_options = o;
*init_backend_options = (aiori_mod_opt_t*) o;
option_help h [] = {
{0, "mmap.madv_dont_need", "Use advise don't need", OPTION_FLAG, 'd', & o->madv_dont_need},
@ -79,25 +82,38 @@ 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 aiori_xfer_hint_t * hints = NULL;
static void MMAP_xfer_hints(aiori_xfer_hint_t * params){
hints = params;
aiori_posix_xfer_hints(params);
}
static int MMAP_check_params(aiori_mod_opt_t * options){
if (hints->fsyncPerWrite && (hints->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 = hints->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 (hints->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,46 +130,45 @@ 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 aiori_fd_t *MMAP_Create(char *testFileName, int flags, aiori_mod_opt_t * param)
{
int *fd;
fd = POSIX_Create(testFileName, param);
if (ftruncate(*fd, param->expectedAggFileSize) != 0)
fd = (int*) POSIX_Create(testFileName, flags, param);
if (ftruncate(*fd, hints->expectedAggFileSize) != 0)
ERR("ftruncate() failed");
ior_mmap_file(fd, param);
return ((void *)fd);
ior_mmap_file(fd, flags, param);
return ((aiori_fd_t *)fd);
}
/*
* Open a file through the POSIX interface and setup mmap.
*/
static void *MMAP_Open(char *testFileName, IOR_param_t * param)
static aiori_fd_t *MMAP_Open(char *testFileName, int flags, aiori_mod_opt_t * param)
{
int *fd;
fd = POSIX_Open(testFileName, param);
ior_mmap_file(fd, param);
return ((void *)fd);
fd = (int*) POSIX_Open(testFileName, flags, param);
ior_mmap_file(fd, flags, param);
return ((aiori_fd_t *)fd);
}
/*
* 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)
static IOR_offset_t MMAP_Xfer(int access, aiori_fd_t *file, IOR_size_t * buffer,
IOR_offset_t length, IOR_offset_t offset, aiori_mod_opt_t * 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 + offset, buffer, length);
} else {
memcpy(buffer, o->mmap_ptr + param->offset, length);
memcpy(buffer, o->mmap_ptr + offset, length);
}
if (param->fsyncPerWrite == TRUE) {
if (msync(o->mmap_ptr + param->offset, length, MS_SYNC) != 0)
if (hints->fsyncPerWrite == TRUE) {
if (msync(o->mmap_ptr + offset, length, MS_SYNC) != 0)
ERR("msync() failed");
if (posix_madvise(o->mmap_ptr + param->offset, length,
if (posix_madvise(o->mmap_ptr + offset, length,
POSIX_MADV_DONTNEED) != 0)
ERR("madvise() failed");
}
@ -163,20 +178,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(aiori_fd_t *fd, aiori_mod_opt_t * 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, hints->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(aiori_fd_t *fd, aiori_mod_opt_t * 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, hints->expectedAggFileSize) != 0)
ERR("munmap failed");
o->mmap_ptr = NULL;
POSIX_Close(fd, param);

View File

@ -31,23 +31,65 @@
/**************************** 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, aiori_mod_opt_t *);
static void *MPIIO_Create(char *, IOR_param_t *);
static void *MPIIO_Open(char *, IOR_param_t *);
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 *);
static aiori_fd_t *MPIIO_Create(char *, int iorflags, aiori_mod_opt_t *);
static aiori_fd_t *MPIIO_Open(char *, int flags, aiori_mod_opt_t *);
static IOR_offset_t MPIIO_Xfer(int, aiori_fd_t *, IOR_size_t *,
IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *);
static void MPIIO_Close(aiori_fd_t *, aiori_mod_opt_t *);
static char* MPIIO_GetVersion();
static void MPIIO_Fsync(void *, IOR_param_t *);
static void MPIIO_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static void MPIIO_xfer_hints(aiori_xfer_hint_t * params);
static int MPIIO_check_params(aiori_mod_opt_t * options);
/************************** D E C L A R A T I O N S ***************************/
typedef struct{
MPI_File fd;
MPI_Datatype transferType; /* datatype for transfer */
MPI_Datatype fileType; /* filetype for file view */
} mpiio_fd_t;
typedef struct {
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(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * 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 = (aiori_mod_opt_t*) o;
option_help h [] = {
{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,
.xfer_hints = MPIIO_xfer_hints,
.open = MPIIO_Open,
.xfer = MPIIO_Xfer,
.close = MPIIO_Close,
@ -60,16 +102,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 aiori_xfer_hint_t * hints = NULL;
static void MPIIO_xfer_hints(aiori_xfer_hint_t * params){
hints = params;
}
static int MPIIO_check_params(aiori_mod_opt_t * module_options){
mpiio_options_t * param = (mpiio_options_t*) module_options;
if ((param->useFileView == TRUE)
&& (sizeof(MPI_Aint) < 8) /* used for 64-bit datatypes */
&&((hints->numTasks * hints->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 && (hints->blockSize < sizeof(IOR_size_t)
|| hints->transferSize <
sizeof(IOR_size_t)))
ERR("need larger file size for strided datatype in MPIIO");
if (hints->randomOffset && hints->collective)
ERR("random offset not available with collective MPIIO");
if (hints->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, aiori_mod_opt_t *module_options)
{
if(param->dryRun){
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(hints->dryRun){
return MPI_SUCCESS;
}
MPI_File fd;
@ -98,60 +170,51 @@ 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 aiori_fd_t *MPIIO_Create(char *testFileName, int iorflags, aiori_mod_opt_t * 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 aiori_fd_t *MPIIO_Open(char *testFileName, int flags, aiori_mod_opt_t * module_options)
{
mpiio_options_t * param = (mpiio_options_t*) module_options;
int fd_mode = (int)0,
offsetFactor,
tasksPerFile,
transfersPerBlock = param->blockSize / param->transferSize;
transfersPerBlock = hints->blockSize / hints->transferSize;
struct fileTypeStruct {
int globalSizes[2], localSizes[2], startIndices[2];
} fileTypeStruct;
MPI_File *fd;
mpiio_fd_t * mfd = malloc(sizeof(mpiio_fd_t));
memset(mfd, 0, sizeof(mpiio_fd_t));
MPI_Comm comm;
MPI_Info mpiHints = MPI_INFO_NULL;
fd = (MPI_File *) malloc(sizeof(MPI_File));
if (fd == NULL)
ERR("malloc failed()");
*fd = 0;
/* 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) {
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 +225,7 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
*/
fd_mode |= MPI_MODE_UNIQUE_OPEN;
if (param->filePerProc) {
if (hints->filePerProc) {
comm = MPI_COMM_SELF;
} else {
comm = testComm;
@ -181,16 +244,19 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
ShowHints(&mpiHints);
fprintf(stdout, "}\n");
}
if(! param->dryRun){
MPI_CHECKF(MPI_File_open(comm, testFileName, fd_mode, mpiHints, fd),
if(! hints->dryRun){
MPI_CHECKF(MPI_File_open(comm, testFileName, fd_mode, mpiHints, & mfd->fd),
"cannot open file: %s", testFileName);
if (flags & IOR_TRUNC) {
MPI_CHECKF(MPI_File_set_size(mfd->fd, 0), "cannot truncate file: %s", testFileName);
}
}
/* show hints actually attached to file handle */
if (rank == 0 && param->showHints && ! param->dryRun) {
if (rank == 0 && param->showHints && ! hints->dryRun) {
if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "MPI_Info_free failed");
MPI_CHECK(MPI_File_get_info(*fd, &mpiHints),
MPI_CHECK(MPI_File_get_info(mfd->fd, &mpiHints),
"cannot get file info");
fprintf(stdout, "\nhints returned from opened file {\n");
ShowHints(&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) {
MPI_CHECK(MPI_File_preallocate(*fd,
(MPI_Offset) (param->segmentCount
if (param->preallocate && flags & IOR_CREAT && ! hints->dryRun) {
MPI_CHECK(MPI_File_preallocate(mfd->fd,
(MPI_Offset) (hints->segmentCount
*
param->blockSize *
param->numTasks)),
hints->blockSize *
hints->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),
(hints->transferSize / sizeof(IOR_size_t),
MPI_LONG_LONG_INT, & mfd->transferType),
"cannot create contiguous datatype");
MPI_CHECK(MPI_Type_commit(&param->transferType),
MPI_CHECK(MPI_Type_commit(& mfd->transferType),
"cannot commit datatype");
if (param->filePerProc) {
if (hints->filePerProc) {
offsetFactor = 0;
tasksPerFile = 1;
} else {
offsetFactor = (rank + rankOffset) % param->numTasks;
tasksPerFile = param->numTasks;
offsetFactor = (rank + rankOffset) % hints->numTasks;
tasksPerFile = hints->numTasks;
}
/*
@ -239,37 +305,38 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
(2, fileTypeStruct.globalSizes,
fileTypeStruct.localSizes,
fileTypeStruct.startIndices, MPI_ORDER_C,
param->transferType, &param->fileType),
mfd->transferType, & mfd->fileType),
"cannot create subarray");
MPI_CHECK(MPI_Type_commit(&param->fileType),
MPI_CHECK(MPI_Type_commit(& mfd->fileType),
"cannot commit datatype");
if(! param->dryRun){
MPI_CHECK(MPI_File_set_view(*fd, (MPI_Offset) 0,
param->transferType,
param->fileType, "native",
if(! hints->dryRun){
MPI_CHECK(MPI_File_set_view(mfd->fd, (MPI_Offset) 0,
mfd->transferType,
mfd->fileType, "native",
(MPI_Info) MPI_INFO_NULL),
"cannot set file view");
}
}
if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "MPI_Info_free failed");
return ((void *)fd);
return ((void *) mfd);
}
/*
* 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)
static IOR_offset_t MPIIO_Xfer(int access, aiori_fd_t * fdp, IOR_size_t * buffer,
IOR_offset_t length, IOR_offset_t offset, aiori_mod_opt_t * 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(hints->dryRun)
return length;
mpiio_fd_t * mfd = (mpiio_fd_t*) fdp;
int (MPIAPI * Access) (MPI_File, void *, int,
MPI_Datatype, MPI_Status *);
@ -319,7 +386,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(mfd->fd, offset, module_options) <
0) {
/* if unsuccessful */
length = -1;
@ -331,24 +398,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 = hints->segmentCount;
} else {
length = 1;
}
if (param->collective) {
if (hints->collective) {
/* individual, collective call */
MPI_CHECK(Access_all
(*(MPI_File *) fd, buffer, length,
param->transferType, &status),
(mfd->fd, buffer, length,
mfd->transferType, &status),
"cannot access collective");
} else {
/* individual, noncollective call */
MPI_CHECK(Access
(*(MPI_File *) fd, buffer, length,
param->transferType, &status),
(mfd->fd, buffer, length,
mfd->transferType, &status),
"cannot access noncollective");
}
length *= param->transferSize; /* for return value in bytes */
length *= hints->transferSize; /* for return value in bytes */
}
} else {
/*
@ -358,7 +425,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) {
(mfd->fd, offset, module_options) < 0) {
/* if unsuccessful */
length = -1;
} else {
@ -374,63 +441,64 @@ static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer,
"useSharedFilePointer not implemented\n");
}
} else {
if (param->collective) {
if (hints->collective) {
/* explicit, collective call */
MPI_CHECK(Access_at_all
(*(MPI_File *) fd, param->offset,
(mfd->fd, offset,
buffer, length, MPI_BYTE, &status),
"cannot access explicit, collective");
} else {
/* explicit, noncollective call */
MPI_CHECK(Access_at
(*(MPI_File *) fd, param->offset,
(mfd->fd, 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(aiori_fd_t *fdp, aiori_mod_opt_t * module_options)
{
if(param->dryRun)
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(hints->dryRun)
return;
if (MPI_File_sync(*(MPI_File *)fdp) != MPI_SUCCESS)
mpiio_fd_t * mfd = (mpiio_fd_t*) fdp;
if (MPI_File_sync(mfd->fd) != MPI_SUCCESS)
EWARN("fsync() failed");
}
/*
* Close a file through the MPIIO interface.
*/
static void MPIIO_Close(void *fd, IOR_param_t * param)
static void MPIIO_Close(aiori_fd_t *fdp, aiori_mod_opt_t * module_options)
{
if(! param->dryRun){
MPI_CHECK(MPI_File_close((MPI_File *) fd), "cannot close file");
mpiio_options_t * param = (mpiio_options_t*) module_options;
mpiio_fd_t * mfd = (mpiio_fd_t*) fdp;
if(! hints->dryRun){
MPI_CHECK(MPI_File_close(& mfd->fd), "cannot close file");
}
if ((param->useFileView == TRUE) && (param->fd_fppReadCheck == NULL)) {
if (param->useFileView == TRUE) {
/*
* 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");
MPI_CHECK(MPI_Type_free(& mfd->fileType), "cannot free MPI file datatype");
MPI_CHECK(MPI_Type_free(& mfd->transferType), "cannot free MPI transfer datatype");
}
free(fd);
free(fdp);
}
/*
* Delete a file through the MPIIO interface.
*/
void MPIIO_Delete(char *testFileName, IOR_param_t * param)
void MPIIO_Delete(char *testFileName, aiori_mod_opt_t * module_options)
{
if(param->dryRun)
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(hints->dryRun)
return;
MPI_CHECKF(MPI_File_delete(testFileName, (MPI_Info) MPI_INFO_NULL),
"cannot delete file: %s", testFileName);
@ -452,36 +520,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)
aiori_mod_opt_t * module_options)
{
mpiio_options_t * param = (mpiio_options_t*) module_options;
int offsetFactor, tasksPerFile;
IOR_offset_t tempOffset;
tempOffset = offset;
if (param->filePerProc) {
if (hints->filePerProc) {
offsetFactor = 0;
tasksPerFile = 1;
} else {
offsetFactor = (rank + rankOffset) % param->numTasks;
tasksPerFile = param->numTasks;
offsetFactor = (rank + rankOffset) % hints->numTasks;
tasksPerFile = hints->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 (hints->filePerProc) {
tempOffset = tempOffset / hints->transferSize;
} else {
/*
* this formula finds a file view offset for a task
* from an absolute offset
*/
tempOffset = ((param->blockSize / param->transferSize)
tempOffset = ((hints->blockSize / hints->transferSize)
* (tempOffset /
(param->blockSize * tasksPerFile)))
+ (((tempOffset % (param->blockSize * tasksPerFile))
- (offsetFactor * param->blockSize))
/ param->transferSize);
(hints->blockSize * tasksPerFile)))
+ (((tempOffset % (hints->blockSize * tasksPerFile))
- (offsetFactor * hints->blockSize))
/ hints->transferSize);
}
}
MPI_CHECK(MPI_File_seek(fd, tempOffset, MPI_SEEK_SET),
@ -493,17 +562,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(aiori_mod_opt_t * module_options, MPI_Comm testComm,
char *testFileName)
{
if(test->dryRun)
mpiio_options_t * test = (mpiio_options_t*) module_options;
if(hints->dryRun)
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 (hints->filePerProc == TRUE) {
comm = MPI_COMM_SELF;
} else {
comm = testComm;
@ -519,7 +589,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 (hints->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved");

View File

@ -68,31 +68,67 @@
#endif
/**************************** 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 * );
static IOR_offset_t POSIX_Xfer(int, aiori_fd_t *, IOR_size_t *,
IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *);
static void POSIX_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static void POSIX_Sync(aiori_mod_opt_t * );
static int POSIX_check_params(aiori_mod_opt_t * options);
/************************** O P T I O N S *****************************/
typedef struct{
/* in case of a change, please update depending MMAP module too */
int direct_io;
/* Lustre variables */
int lustre_set_striping; /* flag that we need to set lustre striping */
int lustre_stripe_count;
int lustre_stripe_size;
int lustre_start_ost;
int lustre_ignore_locks;
/* gpfs variables */
int gpfs_hint_access; /* use gpfs "access range" hint */
int gpfs_release_token; /* immediately release GPFS tokens after
creating or opening a file */
/* beegfs variables */
int beegfs_numTargets; /* number storage targets to use */
int beegfs_chunkSize; /* srtipe pattern for new files */
} posix_options_t;
option_help * POSIX_options(void ** init_backend_options, void * init_values){
option_help * POSIX_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * init_values){
posix_options_t * o = malloc(sizeof(posix_options_t));
if (init_values != NULL){
memcpy(o, init_values, sizeof(posix_options_t));
}else{
memset(o, 0, sizeof(posix_options_t));
o->direct_io = 0;
o->lustre_start_ost = -1;
o->beegfs_numTargets = -1;
o->beegfs_chunkSize = -1;
}
*init_backend_options = o;
*init_backend_options = (aiori_mod_opt_t*) o;
option_help h [] = {
{0, "posix.odirect", "Direct I/O Mode", OPTION_FLAG, 'd', & o->direct_io},
#ifdef HAVE_BEEGFS_BEEGFS_H
{0, "posix.beegfs.NumTargets", "", OPTION_OPTIONAL_ARGUMENT, 'd', & o->beegfs_numTargets},
{0, "posix.beegfs.ChunkSize", "", OPTION_OPTIONAL_ARGUMENT, 'd', & o->beegfs_chunkSize},
#endif
#ifdef HAVE_GPFS_FCNTL_H
{0, "posix.gpfs.hintaccess", "", OPTION_FLAG, 'd', & o->gpfs_hint_access},
{0, "posix.gpfs.releasetoken", "", OPTION_OPTIONAL_ARGUMENT, 'd', & o->gpfs_release_token},
#endif
#ifdef HAVE_LUSTRE_LUSTRE_USER_H
{0, "posix.lustre.stripecount", "", OPTION_OPTIONAL_ARGUMENT, 'd', & o->lustre_stripe_count},
{0, "posix.lustre.stripesize", "", OPTION_OPTIONAL_ARGUMENT, 'd', & o->lustre_stripe_size},
{0, "posix.lustre.startost", "", OPTION_OPTIONAL_ARGUMENT, 'd', & o->lustre_start_ost},
{0, "posix.lustre.ignorelocks", "", OPTION_FLAG, 'd', & o->lustre_ignore_locks},
#endif
LAST_OPTION
};
option_help * help = malloc(sizeof(h));
@ -113,6 +149,7 @@ ior_aiori_t posix_aiori = {
.xfer = POSIX_Xfer,
.close = POSIX_Close,
.delete = POSIX_Delete,
.xfer_hints = aiori_posix_xfer_hints,
.get_version = aiori_get_version,
.fsync = POSIX_Fsync,
.get_file_size = POSIX_GetFileSize,
@ -123,11 +160,26 @@ ior_aiori_t posix_aiori = {
.stat = aiori_posix_stat,
.get_options = POSIX_options,
.enable_mdtest = true,
.sync = POSIX_Sync
.sync = POSIX_Sync,
.check_params = POSIX_check_params
};
/***************************** F U N C T I O N S ******************************/
static aiori_xfer_hint_t * hints = NULL;
void aiori_posix_xfer_hints(aiori_xfer_hint_t * params){
hints = params;
}
static int POSIX_check_params(aiori_mod_opt_t * param){
posix_options_t * o = (posix_options_t*) param;
if (o->beegfs_chunkSize != -1 && (!ISPOWEROFTWO(o->beegfs_chunkSize) || o->beegfs_chunkSize < (1<<16)))
ERR("beegfsChunkSize must be a power of two and >64k");
if(o->lustre_stripe_count != -1 || o->lustre_stripe_size != 0)
o->lustre_set_striping = 1;
return 0;
}
#ifdef HAVE_GPFS_FCNTL_H
void gpfs_free_all_locks(int fd)
@ -151,7 +203,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, int access)
{
int rc;
struct {
@ -165,17 +217,17 @@ void gpfs_access_start(int fd, IOR_offset_t length, IOR_param_t *param, int acce
take_locks.access.structLen = sizeof(take_locks.access);
take_locks.access.structType = GPFS_ACCESS_RANGE;
take_locks.access.start = param->offset;
take_locks.access.start = hints->offset;
take_locks.access.length = length;
take_locks.access.isWrite = (access == WRITE);
rc = gpfs_fcntl(fd, &take_locks);
if (verbose >= VERBOSE_2 && rc != 0) {
EWARNF("gpfs_fcntl(fd, ...) access range hint failed.", fd);
EWARNF("gpfs_fcntl(%d, ...) access range hint failed.", fd);
}
}
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, int access)
{
int rc;
struct {
@ -190,12 +242,12 @@ void gpfs_access_end(int fd, IOR_offset_t length, IOR_param_t *param, int access
free_locks.free.structLen = sizeof(free_locks.free);
free_locks.free.structType = GPFS_FREE_RANGE;
free_locks.free.start = param->offset;
free_locks.free.start = hints->offset;
free_locks.free.length = length;
rc = gpfs_fcntl(fd, &free_locks);
if (verbose >= VERBOSE_2 && rc != 0) {
EWARNF("gpfs_fcntl(fd, ...) free range hint failed.", fd);
EWARNF("gpfs_fcntl(%d, ...) free range hint failed.", fd);
}
}
@ -318,7 +370,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)
aiori_fd_t *POSIX_Create(char *testFileName, int flags, aiori_mod_opt_t * param)
{
int fd_oflag = O_BINARY;
int mode = 0664;
@ -327,13 +379,13 @@ 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)
return 0;
if(hints->dryRun)
return (aiori_fd_t*) 0;
#ifdef HAVE_LUSTRE_LUSTRE_USER_H
/* Add a #define for FASYNC if not available, as it forms part of
@ -341,12 +393,11 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
#ifndef FASYNC
#define FASYNC 00020000 /* fcntl, for BSD compatibility */
#endif
if (param->lustre_set_striping) {
if (o->lustre_set_striping) {
/* In the single-shared-file case, task 0 has to creat the
file with the Lustre striping options before any other processes
open the file */
if (!param->filePerProc && rank != 0) {
if (!hints->filePerProc && rank != 0) {
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
fd_oflag |= O_RDWR;
*fd = open64(testFileName, fd_oflag, mode);
@ -358,9 +409,9 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
/* Setup Lustre IOCTL striping pattern structure */
opts.lmm_magic = LOV_USER_MAGIC;
opts.lmm_stripe_size = param->lustre_stripe_size;
opts.lmm_stripe_offset = param->lustre_start_ost;
opts.lmm_stripe_count = param->lustre_stripe_count;
opts.lmm_stripe_size = o->lustre_stripe_size;
opts.lmm_stripe_offset = o->lustre_start_ost;
opts.lmm_stripe_count = o->lustre_stripe_count;
/* File needs to be opened O_EXCL because we cannot set
* Lustre striping information on a pre-existing file.*/
@ -383,7 +434,7 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1),
"MPI_Abort() error");
}
if (!param->filePerProc)
if (!hints->filePerProc)
MPI_CHECK(MPI_Barrier(testComm),
"barrier error");
}
@ -393,12 +444,12 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
fd_oflag |= O_CREAT | O_RDWR;
#ifdef HAVE_BEEGFS_BEEGFS_H
if (beegfs_isOptionSet(param->beegfs_chunkSize)
|| beegfs_isOptionSet(param->beegfs_numTargets)) {
if (beegfs_isOptionSet(o->beegfs_chunkSize)
|| beegfs_isOptionSet(o->beegfs_numTargets)) {
bool result = beegfs_createFilePath(testFileName,
mode,
param->beegfs_numTargets,
param->beegfs_chunkSize);
o->beegfs_numTargets,
o->beegfs_chunkSize);
if (result) {
fd_oflag &= ~O_CREAT;
} else {
@ -415,7 +466,7 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
#ifdef HAVE_LUSTRE_LUSTRE_USER_H
}
if (param->lustre_ignore_locks) {
if (o->lustre_ignore_locks) {
int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK;
if (ioctl(*fd, LL_IOC_SETFLAGS, &lustre_ioctl_flags) == -1)
ERRF("ioctl(%d, LL_IOC_SETFLAGS, ...) failed", *fd);
@ -426,35 +477,31 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
/* in the single shared file case, immediately release all locks, with
* the intent that we can avoid some byte range lock revocation:
* everyone will be writing/reading from individual regions */
if (param->gpfs_release_token ) {
if (o->gpfs_release_token ) {
gpfs_free_all_locks(*fd);
}
#endif
return ((void *)fd);
return (aiori_fd_t*) fd;
}
/*
* Creat a file through mknod interface.
*/
void *POSIX_Mknod(char *testFileName)
int POSIX_Mknod(char *testFileName)
{
int *fd;
int ret;
fd = (int *)malloc(sizeof(int));
if (fd == NULL)
ERR("Unable to malloc file descriptor");
ret = mknod(testFileName, S_IFREG | S_IRUSR, 0);
if (ret < 0)
ERR("mknod failed");
*fd = mknod(testFileName, S_IFREG | S_IRUSR, 0);
if (*fd < 0)
ERR("mknod failed");
return ((void *)fd);
return ret;
}
/*
* Open a file through the POSIX interface.
*/
void *POSIX_Open(char *testFileName, IOR_param_t * param)
aiori_fd_t *POSIX_Open(char *testFileName, int flags, aiori_mod_opt_t * param)
{
int fd_oflag = O_BINARY;
int *fd;
@ -463,21 +510,21 @@ 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)
return 0;
if(hints->dryRun)
return (aiori_fd_t*) 0;
*fd = open64(testFileName, fd_oflag);
if (*fd < 0)
ERRF("open64(\"%s\", %d) failed", testFileName, fd_oflag);
#ifdef HAVE_LUSTRE_LUSTRE_USER_H
if (param->lustre_ignore_locks) {
if (o->lustre_ignore_locks) {
int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK;
if (verbose >= VERBOSE_1) {
fprintf(stdout,
@ -489,40 +536,41 @@ void *POSIX_Open(char *testFileName, IOR_param_t * param)
#endif /* HAVE_LUSTRE_LUSTRE_USER_H */
#ifdef HAVE_GPFS_FCNTL_H
if(param->gpfs_release_token) {
if(o->gpfs_release_token) {
gpfs_free_all_locks(*fd);
}
#endif
return ((void *)fd);
return (aiori_fd_t*) fd;
}
/*
* 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)
static IOR_offset_t POSIX_Xfer(int access, aiori_fd_t *file, IOR_size_t * buffer,
IOR_offset_t length, IOR_offset_t offset, aiori_mod_opt_t * param)
{
int xferRetries = 0;
long long remaining = (long long)length;
char *ptr = (char *)buffer;
long long rc;
int fd;
posix_options_t * o = (posix_options_t*) param;
if(param->dryRun)
if(hints->dryRun)
return length;
fd = *(int *)file;
#ifdef HAVE_GPFS_FCNTL_H
if (param->gpfs_hint_access) {
gpfs_access_start(fd, length, param, access);
if (o->gpfs_hint_access) {
gpfs_access_start(fd, length, access);
}
#endif
/* seek to offset */
if (lseek64(fd, param->offset, SEEK_SET) == -1)
ERRF("lseek64(%d, %lld, SEEK_SET) failed", fd, param->offset);
if (lseek64(fd, offset, SEEK_SET) == -1)
ERRF("lseek64(%d, %lld, SEEK_SET) failed", fd, offset);
while (remaining > 0) {
/* write/read file */
@ -531,20 +579,21 @@ 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);
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)
POSIX_Fsync(&fd, param);
if (hints->fsyncPerWrite == TRUE){
POSIX_Fsync((aiori_fd_t*) &fd, param);
}
} else { /* READ or CHECK */
if (verbose >= VERBOSE_4) {
fprintf(stdout,
"task %d reading from offset %lld\n",
rank,
param->offset + length - remaining);
offset + length - remaining);
}
rc = read(fd, ptr, remaining);
if (rc == 0)
@ -560,8 +609,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)
offset + length - remaining);
if (hints->singleXferAttempt == TRUE)
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1),
"barrier error");
if (xferRetries > MAX_RETRY)
@ -574,7 +623,7 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
xferRetries++;
}
#ifdef HAVE_GPFS_FCNTL_H
if (param->gpfs_hint_access) {
if (o->gpfs_hint_access) {
gpfs_access_end(fd, length, param, access);
}
#endif
@ -584,14 +633,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(aiori_fd_t *fd, aiori_mod_opt_t * param)
{
if (fsync(*(int *)fd) != 0)
EWARNF("fsync(%d) failed", *(int *)fd);
}
static void POSIX_Sync(IOR_param_t * param)
static void POSIX_Sync(aiori_mod_opt_t * param)
{
int ret = system("sync");
if (ret != 0){
@ -603,9 +652,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(aiori_fd_t *fd, aiori_mod_opt_t * param)
{
if(param->dryRun)
if(hints->dryRun)
return;
if (close(*(int *)fd) != 0)
ERRF("close(%d) failed", *(int *)fd);
@ -615,9 +664,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, aiori_mod_opt_t * param)
{
if(param->dryRun)
if(hints->dryRun)
return;
if (unlink(testFileName) != 0){
EWARNF("[RANK %03d]: unlink() of file \"%s\" failed\n",
@ -628,10 +677,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(aiori_mod_opt_t * test, MPI_Comm testComm,
char *testFileName)
{
if(test->dryRun)
if(hints->dryRun)
return 0;
struct stat stat_buf;
IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum;
@ -641,7 +690,7 @@ IOR_offset_t POSIX_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
}
aggFileSizeFromStat = stat_buf.st_size;
if (test->filePerProc == TRUE) {
if (hints->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved");

View File

@ -137,9 +137,6 @@ static void *RADOS_Create_Or_Open(char *testFileName, IOR_param_t * param, int c
RADOS_Cluster_Init(param);
if (param->useO_DIRECT == TRUE)
WARN("direct I/O mode is not implemented in RADOS\n");
oid = strdup(testFileName);
if (!oid)
ERR("unable to allocate RADOS oid");

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

@ -76,6 +76,9 @@ ior_aiori_t *available_aiori[] = {
#ifdef USE_RADOS_AIORI
&rados_aiori,
#endif
#ifdef USE_CEPHFS_AIORI
&cephfs_aiori,
#endif
#ifdef USE_GFARM_AIORI
&gfarm_aiori,
#endif
@ -152,47 +155,68 @@ 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, aiori_mod_opt_t * module_options)
{
int ret;
// find the parent directory
char * fileName = strdup(path);
int i;
int directoryFound = FALSE;
/* get directory for outfile */
i = strlen(fileName);
while (i-- > 0) {
if (fileName[i] == '/') {
fileName[i] = '\0';
directoryFound = TRUE;
break;
}
}
/* if no directory/, use '.' */
if (directoryFound == FALSE) {
strcpy(fileName, ".");
}
int ret;
#if defined(HAVE_STATVFS)
struct statvfs statfs_buf;
struct statvfs statfs_buf;
ret = statvfs (path, &statfs_buf);
ret = statvfs (fileName, &statfs_buf);
#else
struct statfs statfs_buf;
struct statfs statfs_buf;
ret = statfs (path, &statfs_buf);
ret = statfs (fileName, &statfs_buf);
#endif
if (-1 == ret) {
return -1;
}
if (-1 == ret) {
perror("POSIX couldn't call statvfs");
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;
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;
free(fileName);
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, aiori_mod_opt_t * module_options)
{
return mkdir (path, mode);
}
int aiori_posix_rmdir (const char *path, IOR_param_t * param)
int aiori_posix_rmdir (const char *path, aiori_mod_opt_t * 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, aiori_mod_opt_t * 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, aiori_mod_opt_t * module_options)
{
return stat (path, buf);
}
@ -202,92 +226,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

@ -24,7 +24,6 @@
#include <sys/stat.h>
#include <stdbool.h>
#include "ior.h"
#include "iordef.h" /* IOR Definitions */
#include "option.h"
@ -63,31 +62,61 @@ typedef struct ior_aiori_statfs {
uint64_t f_ffree;
} ior_aiori_statfs_t;
/*
This structure contains information about the expected IO pattern that may be used to optimize data access. Optimally, it should be stored for each file descriptor, at the moment it can only be set globally per aiori backend module.
*/
typedef struct aiori_xfer_hint_t{
int dryRun; /* do not perform any I/Os just run evtl. inputs print dummy output */
int filePerProc; /* single file or file-per-process */
int collective; /* collective I/O */
int numTasks; /* number of tasks for test */
int numNodes; /* number of nodes for test */
int randomOffset; /* access is to random offsets */
int fsyncPerWrite; /* fsync() after each write */
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 expectedAggFileSize; /* calculated aggregate file size */
int singleXferAttempt; /* do not retry transfer if incomplete */
} aiori_xfer_hint_t;
/* this is a dummy structure to create some type safety */
typedef struct aiori_mod_opt_t{
void * dummy;
} aiori_mod_opt_t;
typedef struct aiori_fd_t{
void * dummy;
} aiori_fd_t;
typedef struct ior_aiori {
char *name;
char *name_legacy;
void *(*create)(char *, IOR_param_t *);
void *(*mknod)(char *);
void *(*open)(char *, IOR_param_t *);
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 *);
char* (*get_version)();
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)(); /* called once per program before MPI is started */
void (*finalize)(); /* 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 */
aiori_fd_t *(*create)(char *, int iorflags, aiori_mod_opt_t *);
int (*mknod)(char *);
aiori_fd_t *(*open)(char *, int iorflags, aiori_mod_opt_t *);
/*
Allow to set generic transfer options that shall be applied to any subsequent IO call.
*/
void (*xfer_hints)(aiori_xfer_hint_t * params);
IOR_offset_t (*xfer)(int access, aiori_fd_t *, IOR_size_t *,
IOR_offset_t size, IOR_offset_t offset, aiori_mod_opt_t *);
void (*close)(aiori_fd_t *, aiori_mod_opt_t *);
void (*delete)(char *, aiori_mod_opt_t *);
char* (*get_version)(void);
void (*fsync)(aiori_fd_t *, aiori_mod_opt_t *);
IOR_offset_t (*get_file_size)(aiori_mod_opt_t * module_options, MPI_Comm, char *);
int (*statfs) (const char *, ior_aiori_statfs_t *, aiori_mod_opt_t * module_options);
int (*mkdir) (const char *path, mode_t mode, aiori_mod_opt_t * module_options);
int (*rmdir) (const char *path, aiori_mod_opt_t * module_options);
int (*access) (const char *path, int mode, aiori_mod_opt_t * module_options);
int (*stat) (const char *path, struct stat *buf, aiori_mod_opt_t * module_options);
void (*initialize)(aiori_mod_opt_t * options); /* called once per program before MPI is started */
void (*finalize)(aiori_mod_opt_t * options); /* called once per program after MPI is shutdown */
option_help * (*get_options)(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t* init_values); /* initializes the backend options as well and returns the pointer to the option help structure */
int (*check_params)(aiori_mod_opt_t *); /* 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)(aiori_mod_opt_t * ); /* synchronize every pending operation for this storage */
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 */
} ior_aiori_t;
enum bench_type {
@ -110,10 +139,9 @@ extern ior_aiori_t s3_aiori;
extern ior_aiori_t s3_plus_aiori;
extern ior_aiori_t s3_emc_aiori;
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);
@ -124,26 +152,26 @@ void * airoi_update_module_options(const ior_aiori_t * backend, options_all_t *
const char *aiori_default (void);
/* some generic POSIX-based backend calls */
char * aiori_get_version();
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);
char * aiori_get_version (void);
int aiori_posix_statfs (const char *path, ior_aiori_statfs_t *stat_buf, aiori_mod_opt_t * module_options);
int aiori_posix_mkdir (const char *path, mode_t mode, aiori_mod_opt_t * module_options);
int aiori_posix_rmdir (const char *path, aiori_mod_opt_t * module_options);
int aiori_posix_access (const char *path, int mode, aiori_mod_opt_t * module_options);
int aiori_posix_stat (const char *path, struct stat *buf, aiori_mod_opt_t * module_options);
void aiori_posix_xfer_hints(aiori_xfer_hint_t * params);
void *POSIX_Create(char *testFileName, IOR_param_t * param);
void *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);
option_help * POSIX_options(void ** init_backend_options, void * init_values);
aiori_fd_t *POSIX_Create(char *testFileName, int flags, aiori_mod_opt_t * module_options);
int POSIX_Mknod(char *testFileName);
aiori_fd_t *POSIX_Open(char *testFileName, int flags, aiori_mod_opt_t * module_options);
IOR_offset_t POSIX_GetFileSize(aiori_mod_opt_t * test, MPI_Comm testComm, char *testFileName);
void POSIX_Delete(char *testFileName, aiori_mod_opt_t * module_options);
void POSIX_Close(aiori_fd_t *fd, aiori_mod_opt_t * module_options);
option_help * POSIX_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * 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,
char *testFileName);
int MPIIO_Access(const char *, int, IOR_param_t *);
void MPIIO_Delete(char *testFileName, aiori_mod_opt_t * module_options);
IOR_offset_t MPIIO_GetFileSize(aiori_mod_opt_t * options, MPI_Comm testComm, char *testFileName);
int MPIIO_Access(const char *, int, aiori_mod_opt_t *);
#endif /* not _AIORI_H */

View File

@ -17,7 +17,6 @@ void PrintShortSummary(IOR_test_t * test);
void PrintLongSummaryAllTests(IOR_test_t *tests_head);
void PrintLongSummaryHeader();
void PrintLongSummaryOneTest(IOR_test_t *test);
void DisplayFreespace(IOR_param_t * test);
void GetTestFileName(char *, IOR_param_t *);
void PrintRemoveTiming(double start, double finish, int rep);
void PrintReducedResult(IOR_test_t *test, int access, double bw, double iops, double latency,
@ -26,6 +25,9 @@ void PrintTestEnds();
void PrintTableHeader();
/* End of ior-output */
IOR_offset_t *GetOffsetArraySequential(IOR_param_t * test, int pretendRank);
IOR_offset_t *GetOffsetArrayRandom(IOR_param_t * test, int pretendRank, int access);
struct results {
double min;
double max;

View File

@ -210,7 +210,7 @@ void PrintRepeatStart(){
}
void PrintTestEnds(){
if (rank != 0 || verbose < VERBOSE_0) {
if (rank != 0 || verbose <= VERBOSE_0) {
PrintEndSection();
return;
}
@ -262,7 +262,7 @@ void PrintHeader(int argc, char **argv)
if (outputFormat != OUTPUT_DEFAULT){
PrintKeyVal("Version", META_VERSION);
}else{
printf("IOR-" META_VERSION ": MPI Coordinated Test of Parallel I/O\n");
fprintf(out_resultfile, "IOR-" META_VERSION ": MPI Coordinated Test of Parallel I/O\n");
}
PrintKeyVal("Began", CurrentTimeString());
PrintKeyValStart("Command line");
@ -322,11 +322,8 @@ void ShowTestStart(IOR_param_t *test)
PrintStartSection();
PrintKeyValInt("TestID", test->id);
PrintKeyVal("StartTime", CurrentTimeString());
/* if pvfs2:, then skip */
if (strcasecmp(test->api, "DFS") &&
Regex(test->testFileName, "^[a-z][a-z].*:") == 0) {
DisplayFreespace(test);
}
ShowFileSystemSize(test);
if (verbose >= VERBOSE_3 || outputFormat == OUTPUT_JSON) {
char* data_packets[] = {"g","t","o","i"};
@ -337,7 +334,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,9 +351,7 @@ 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);
PrintKeyValInt("readFile", test->readFile);
PrintKeyValInt("writeFile", test->writeFile);
@ -368,12 +362,7 @@ 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);
@ -452,14 +441,10 @@ void ShowSetup(IOR_param_t *params)
if(params->dryRun){
PrintKeyValInt("dryRun", params->dryRun);
}
#ifdef HAVE_LUSTRE_LUSTRE_USER_H
if (params->lustre_set_striping) {
PrintKeyVal("Lustre stripe size", ((params->lustre_stripe_size == 0) ? "Use default" :
HumanReadable(params->lustre_stripe_size, BASE_TWO)));
PrintKeyValInt("Lustre stripe count", params->lustre_stripe_count);
if(params->verbose) {
PrintKeyValInt("verbose", params->verbose);
}
#endif /* HAVE_LUSTRE_LUSTRE_USER_H */
if (params->deadlineForStonewalling > 0) {
PrintKeyValInt("stonewallingTime", params->deadlineForStonewalling);
PrintKeyValInt("stoneWallingWearOut", params->stoneWallingWearOut );
@ -535,7 +520,7 @@ static void PrintLongSummaryOneOperation(IOR_test_t *test, const int access)
struct results *ops;
int reps;
if (rank != 0 || verbose < VERBOSE_0)
if (rank != 0 || verbose <= VERBOSE_0)
return;
reps = params->repetitions;
@ -650,7 +635,7 @@ void PrintLongSummaryOneTest(IOR_test_t *test)
void PrintLongSummaryHeader()
{
if (rank != 0 || verbose < VERBOSE_0)
if (rank != 0 || verbose <= VERBOSE_0)
return;
if(outputFormat != OUTPUT_DEFAULT){
return;
@ -670,7 +655,7 @@ void PrintLongSummaryHeader()
void PrintLongSummaryAllTests(IOR_test_t *tests_head)
{
IOR_test_t *tptr;
if (rank != 0 || verbose < VERBOSE_0)
if (rank != 0 || verbose <= VERBOSE_0)
return;
PrintArrayEnd();
@ -703,7 +688,7 @@ void PrintShortSummary(IOR_test_t * test)
int reps;
int i;
if (rank != 0 || verbose < VERBOSE_0)
if (rank != 0 || verbose <= VERBOSE_0)
return;
PrintArrayEnd();
@ -740,41 +725,9 @@ void PrintShortSummary(IOR_test_t * test)
}
}
/*
* Display freespace (df).
*/
void DisplayFreespace(IOR_param_t * test)
{
char fileName[MAX_STR] = { 0 };
int i;
int directoryFound = FALSE;
/* get outfile name */
GetTestFileName(fileName, test);
/* get directory for outfile */
i = strlen(fileName);
while (i-- > 0) {
if (fileName[i] == '/') {
fileName[i] = '\0';
directoryFound = TRUE;
break;
}
}
/* if no directory/, use '.' */
if (directoryFound == FALSE) {
strcpy(fileName, ".");
}
ShowFileSystemSize(fileName);
}
void PrintRemoveTiming(double start, double finish, int rep)
{
if (rank != 0 || verbose < VERBOSE_0)
if (rank != 0 || verbose <= VERBOSE_0)
return;
if (outputFormat == OUTPUT_DEFAULT){

275
src/ior.c
View File

@ -55,9 +55,50 @@ static void InitTests(IOR_test_t * , MPI_Comm);
static void TestIoSys(IOR_test_t *);
static void ValidateTests(IOR_param_t *);
static IOR_offset_t WriteOrRead(IOR_param_t *test, IOR_results_t *results,
void *fd, const int access,
aiori_fd_t *fd, const int access,
IOR_io_buffers *ioBuffers);
static void ior_set_xfer_hints(IOR_param_t * p){
aiori_xfer_hint_t * hints = & p->hints;
hints->dryRun = p->dryRun;
hints->filePerProc = p->filePerProc;
hints->collective = p->collective;
hints->numTasks = p->numTasks;
hints->numNodes = p->numNodes;
hints->randomOffset = p->randomOffset;
hints->fsyncPerWrite = p->fsyncPerWrite;
hints->segmentCount = p->segmentCount;
hints->blockSize = p->blockSize;
hints->transferSize = p->transferSize;
hints->expectedAggFileSize = p->expectedAggFileSize;
hints->singleXferAttempt = p->singleXferAttempt;
if(backend->xfer_hints){
backend->xfer_hints(hints);
}
}
static void test_initialize(IOR_test_t * test){
verbose = test->params.verbose;
backend = test->params.backend;
if(backend->initialize){
backend->initialize(test->params.backend_options);
}
ior_set_xfer_hints(& test->params);
if (rank == 0 && verbose >= VERBOSE_0) {
ShowTestStart(& test->params);
}
}
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,14 +117,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) {
test_initialize(tptr);
totalErrorCount = 0;
verbose = tptr->params.verbose;
if (rank == 0 && verbose >= VERBOSE_0) {
ShowTestStart(&tptr->params);
}
TestIoSys(tptr);
tptr->results->errors = totalErrorCount;
ShowTestEnd(tptr);
test_finalize(tptr);
}
PrintLongSummaryAllTests(tests_head);
@ -122,17 +161,11 @@ int ior_main(int argc, char **argv)
InitTests(tests_head, mpi_comm_world);
verbose = tests_head->params.verbose;
aiori_initialize(tests_head);
PrintHeader(argc, argv);
/* perform each test */
for (tptr = tests_head; tptr != NULL; tptr = tptr->next) {
verbose = tptr->params.verbose;
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'
@ -144,18 +177,17 @@ int ior_main(int argc, char **argv)
TestIoSys(tptr);
ShowTestEnd(tptr);
test_finalize(tptr);
}
if (verbose < 0)
if (verbose <= VERBOSE_0)
/* always print final summary */
verbose = 0;
verbose = VERBOSE_1;
PrintLongSummaryAllTests(tests_head);
/* display finish time */
PrintTestEnds();
aiori_finalize(tests_head);
MPI_CHECK(MPI_Finalize(), "cannot finalize MPI");
DestroyTests(tests_head);
@ -176,10 +208,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");
@ -205,8 +233,6 @@ void init_IOR_Param_t(IOR_param_t * p)
p->randomSeed = -1;
p->incompressibleSeed = 573;
p->testComm = mpi_comm_world;
p->setAlignment = 1;
p->lustre_start_ost = -1;
hdfs_user = getenv("USER");
if (!hdfs_user)
@ -220,9 +246,6 @@ void init_IOR_Param_t(IOR_param_t * p)
p->URI = NULL;
p->part_number = 0;
p->beegfs_numTargets = -1;
p->beegfs_chunkSize = -1;
}
static void
@ -253,8 +276,13 @@ DisplayOutliers(int numTasks,
strcpy(accessString, "read");
}
if (fabs(timerVal - mean) > (double)outlierThreshold) {
fprintf(out_logfile, "WARNING: for task %d, %s %s is %f\n",
rank, accessString, timeString, timerVal);
char hostname[MAX_STR];
int ret = gethostname(hostname, MAX_STR);
if (ret != 0)
strcpy(hostname, "unknown");
fprintf(out_logfile, "WARNING: for %s, task %d, %s %s is %f\n",
hostname, rank, accessString, timeString, timerVal);
fprintf(out_logfile, " (mean=%f, stddev=%f)\n", mean, sd);
fflush(out_logfile);
}
@ -356,7 +384,7 @@ CompareBuffers(void *expectedBuffer,
if (verbose >= VERBOSE_3) {
fprintf(out_logfile,
"[%d] At file byte offset %lld, comparing %llu-byte transfer\n",
rank, test->offset, (long long)size);
rank, (long long) offset, (long long)size);
}
for (i = 0; i < length; i++) {
if (testbuf[i] != goodbuf[i]) {
@ -365,7 +393,7 @@ CompareBuffers(void *expectedBuffer,
fprintf(out_logfile,
"[%d] At transfer buffer #%lld, index #%lld (file byte offset %lld):\n",
rank, transferCount - 1, (long long)i,
test->offset +
(long long) offset +
(IOR_size_t) (i * sizeof(IOR_size_t)));
fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel1);
fprintf(out_logfile, "%016llx\n", goodbuf[i]);
@ -381,10 +409,10 @@ CompareBuffers(void *expectedBuffer,
}
} else if (verbose >= VERBOSE_5 && i % 4 == 0) {
fprintf(out_logfile,
"[%d] PASSED offset = %lld bytes, transfer %lld\n",
"[%d] PASSED offset = %lu bytes, transfer %lld\n",
rank,
((i * sizeof(unsigned long long)) +
test->offset), transferCount);
offset), transferCount);
fprintf(out_logfile, "[%d] GOOD %s0x", rank, bufferLabel1);
for (j = 0; j < 4; j++)
fprintf(out_logfile, "%016llx ", goodbuf[i + j]);
@ -407,8 +435,8 @@ CompareBuffers(void *expectedBuffer,
"%lld errors between buffer indices %lld and %lld.\n",
(long long)errorCount, (long long)first,
(long long)last);
fprintf(out_logfile, "[%d] File byte offset = %lld:\n", rank,
((first * sizeof(unsigned long long)) + test->offset));
fprintf(out_logfile, "[%d] File byte offset = %lu:\n", rank,
((first * sizeof(unsigned long long)) + offset));
fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel1);
for (j = first; j < length && j < first + 4; j++)
@ -503,8 +531,6 @@ void AllocResults(IOR_test_t *test)
if (test->results != NULL)
return;
IOR_param_t * params = & test->params;
reps = test->params.repetitions;
test->results = (IOR_results_t *) safeMalloc(sizeof(IOR_results_t) * reps);
}
@ -824,15 +850,15 @@ static char *PrependDir(IOR_param_t * test, char *rootDir)
sprintf(dir + i + 1, "%d", (rank + rankOffset) % test->numTasks);
/* dir doesn't exist, so create */
if (backend->access(dir, F_OK, test) != 0) {
if (backend->mkdir(dir, S_IRWXU, test) < 0) {
if (backend->access(dir, F_OK, test->backend_options) != 0) {
if (backend->mkdir(dir, S_IRWXU, test->backend_options) < 0) {
ERRF("cannot create directory: %s", dir);
}
/* check if correct permissions */
} else if (backend->access(dir, R_OK, test) != 0 ||
backend->access(dir, W_OK, test) != 0 ||
backend->access(dir, X_OK, test) != 0) {
} else if (backend->access(dir, R_OK, test->backend_options) != 0 ||
backend->access(dir, W_OK, test->backend_options) != 0 ||
backend->access(dir, X_OK, test->backend_options) != 0) {
ERRF("invalid directory permissions: %s", dir);
}
@ -893,7 +919,7 @@ ReduceIterResults(IOR_test_t *test, double *timer, const int rep, const int acce
* number of I/Os issued from that task; then reduce and display the
* minimum (best) latency achieved. So what is reported is the average
* latency of all ops from a single task, then taking the minimum of
* that between all tasks. */
* that between all tasks. */
latency = (timer[3] - timer[2]) / (params->blockSize / params->transferSize);
MPI_CHECK(MPI_Reduce(&latency, &minlatency, 1, MPI_DOUBLE,
MPI_MIN, 0, testComm), "MPI_Reduce()");
@ -919,24 +945,24 @@ static void RemoveFile(char *testFileName, int filePerProc, IOR_param_t * test)
rankOffset = 0;
GetTestFileName(testFileName, test);
}
if (backend->access(testFileName, F_OK, test) == 0) {
if (backend->access(testFileName, F_OK, test->backend_options) == 0) {
if (verbose >= VERBOSE_3) {
fprintf(out_logfile, "task %d removing %s\n", rank,
testFileName);
}
backend->delete(testFileName, test);
backend->delete(testFileName, test->backend_options);
}
if (test->reorderTasksRandom == TRUE) {
rankOffset = tmpRankOffset;
GetTestFileName(testFileName, test);
}
} else {
if ((rank == 0) && (backend->access(testFileName, F_OK, test) == 0)) {
if ((rank == 0) && (backend->access(testFileName, F_OK, test->backend_options) == 0)) {
if (verbose >= VERBOSE_3) {
fprintf(out_logfile, "task %d removing %s\n", rank,
testFileName);
}
backend->delete(testFileName, test);
backend->delete(testFileName, test->backend_options);
}
}
}
@ -1231,7 +1257,7 @@ static void TestIoSys(IOR_test_t *test)
double startTime;
int pretendRank;
int rep;
void *fd;
aiori_fd_t *fd;
MPI_Group orig_group, new_group;
int range[3];
IOR_offset_t dataMoved; /* for data rate calculation */
@ -1257,7 +1283,7 @@ static void TestIoSys(IOR_test_t *test)
return;
}
if (rank == 0 && verbose >= VERBOSE_1) {
fprintf(out_logfile, "Participating tasks: %d\n", params->numTasks);
fprintf(out_logfile, "Participating tasks : %d\n", params->numTasks);
fflush(out_logfile);
}
if (rank == 0 && params->reorderTasks == TRUE && verbose >= VERBOSE_1) {
@ -1265,7 +1291,6 @@ static void TestIoSys(IOR_test_t *test)
"Using reorderTasks '-C' (useful to avoid read cache in client)\n");
fflush(out_logfile);
}
backend = params->backend;
/* show test setup */
if (rank == 0 && verbose >= VERBOSE_0)
ShowSetup(params);
@ -1277,7 +1302,7 @@ static void TestIoSys(IOR_test_t *test)
/* IO Buffer Setup */
if (params->setTimeStampSignature) { // initialize the buffer properly
params->timeStampSignatureValue = (unsigned int)params->setTimeStampSignature;
params->timeStampSignatureValue = (unsigned int) params->setTimeStampSignature;
}
XferBuffersSetup(&ioBuffers, params, pretendRank);
reseed_incompressible_prng = TRUE; // reset pseudo random generator, necessary to guarantee the next call to FillBuffer produces the same value as it is right now
@ -1299,12 +1324,12 @@ static void TestIoSys(IOR_test_t *test)
}
params->timeStampSignatureValue =
(unsigned int)currentTime;
if (verbose >= VERBOSE_2) {
fprintf(out_logfile,
"Using Time Stamp %u (0x%x) for Data Signature\n",
params->timeStampSignatureValue,
params->timeStampSignatureValue);
}
}
if (verbose >= VERBOSE_2) {
fprintf(out_logfile,
"Using Time Stamp %u (0x%x) for Data Signature\n",
params->timeStampSignatureValue,
params->timeStampSignatureValue);
}
if (rep == 0 && verbose >= VERBOSE_0) {
PrintTableHeader();
@ -1339,7 +1364,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 | IOR_TRUNC, params->backend_options);
timer[1] = GetTimeStamp();
if (params->intraTestBarriers)
MPI_CHECK(MPI_Barrier(testComm),
@ -1360,14 +1385,14 @@ static void TestIoSys(IOR_test_t *test)
MPI_CHECK(MPI_Barrier(testComm),
"barrier error");
timer[4] = GetTimeStamp();
backend->close(fd, params);
backend->close(fd, params->backend_options);
timer[5] = GetTimeStamp();
MPI_CHECK(MPI_Barrier(testComm), "barrier error");
/* get the size of the file just written */
results[rep].write.aggFileSizeFromStat =
backend->get_file_size(params, testComm, testFileName);
backend->get_file_size(params->backend_options, testComm, testFileName);
/* check if stat() of file doesn't equal expected file size,
use actual amount of byte moved */
@ -1413,9 +1438,9 @@ 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->backend_options);
dataMoved = WriteOrRead(params, &results[rep], fd, WRITECHECK, &ioBuffers);
backend->close(fd, params);
backend->close(fd, params->backend_options);
rankOffset = 0;
}
/*
@ -1485,7 +1510,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->backend_options);
timer[1] = GetTimeStamp();
if (params->intraTestBarriers)
MPI_CHECK(MPI_Barrier(testComm),
@ -1502,12 +1527,12 @@ static void TestIoSys(IOR_test_t *test)
MPI_CHECK(MPI_Barrier(testComm),
"barrier error");
timer[4] = GetTimeStamp();
backend->close(fd, params);
backend->close(fd, params->backend_options);
timer[5] = GetTimeStamp();
/* get the size of the file just read */
results[rep].read.aggFileSizeFromStat =
backend->get_file_size(params, testComm,
backend->get_file_size(params->backend_options, testComm,
testFileName);
/* check if stat() of file doesn't equal expected file size,
@ -1588,8 +1613,6 @@ static void ValidateTests(IOR_param_t * test)
ERR("block size must be non-negative integer");
if ((test->transferSize % sizeof(IOR_size_t)) != 0)
ERR("transfer size must be a multiple of access size");
if (test->setAlignment < 0)
ERR("alignment must be non-negative integer");
if (test->transferSize < 0)
ERR("transfer size must be non-negative integer");
if (test->transferSize == 0) {
@ -1614,11 +1637,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);
@ -1626,43 +1644,13 @@ static void ValidateTests(IOR_param_t * test)
&& (strcasecmp(test->api, "MPIIO") != 0)
&& (strcasecmp(test->api, "MMAP") != 0)
&& (strcasecmp(test->api, "HDFS") != 0)
&& (strcasecmp(test->api, "DFS") != 0)
&& (strcasecmp(test->api, "DAOS") != 0)
&& (strcasecmp(test->api, "Gfarm") != 0)
&& (strcasecmp(test->api, "RADOS") != 0)) && test->fsync)
&& (strcasecmp(test->api, "RADOS") != 0)
&& (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,51 +1664,19 @@ 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)
ERR("random offset not available with NCMPI");
if ((strcasecmp(test->api, "HDF5") != 0) && test->individualDataSets)
WARN_RESET("individual datasets only available in HDF5",
test, &defaults, individualDataSets);
if ((strcasecmp(test->api, "HDF5") == 0) && test->individualDataSets)
WARN_RESET("individual data sets not implemented",
test, &defaults, individualDataSets);
if ((strcasecmp(test->api, "NCMPI") == 0) && test->filePerProc)
ERR("file-per-proc not available in current NCMPI");
if (test->noFill) {
if (strcasecmp(test->api, "HDF5") != 0) {
ERR("'no fill' option only available in HDF5");
} else {
/* check if hdf5 available */
#if defined (H5_VERS_MAJOR) && defined (H5_VERS_MINOR)
/* no-fill option not available until hdf5-1.6.x */
#if (H5_VERS_MAJOR > 0 && H5_VERS_MINOR > 5)
;
#else
ERRF("'no fill' option not available in %s",
test->apiVersion);
#endif
#else
WARN("unable to determine HDF5 version for 'no fill' usage");
#endif
}
}
if (test->useExistingTestFile && test->lustre_set_striping)
ERR("Lustre stripe options are incompatible with useExistingTestFile");
backend = test->backend;
ior_set_xfer_hints(test);
/* allow the backend to validate the options */
if(test->backend->check_params){
int check = test->backend->check_params(test);
if (check == 0){
int check = test->backend->check_params(test->backend_options);
if (check){
ERR("The backend returned that the test parameters are invalid.");
}
}
@ -1733,8 +1689,7 @@ static void ValidateTests(IOR_param_t * test)
* @param pretendRank int pretended Rank for shifting the offsest corectly
* @return IOR_offset_t
*/
static IOR_offset_t *GetOffsetArraySequential(IOR_param_t * test,
int pretendRank)
IOR_offset_t *GetOffsetArraySequential(IOR_param_t * test, int pretendRank)
{
IOR_offset_t i, j, k = 0;
IOR_offset_t offsets;
@ -1783,8 +1738,7 @@ static IOR_offset_t *GetOffsetArraySequential(IOR_param_t * test,
* @return IOR_offset_t
* @return
*/
static IOR_offset_t *GetOffsetArrayRandom(IOR_param_t * test, int pretendRank,
int access)
IOR_offset_t *GetOffsetArrayRandom(IOR_param_t * test, int pretendRank, int access)
{
int seed;
IOR_offset_t i, value, tmp;
@ -1854,7 +1808,7 @@ static IOR_offset_t *GetOffsetArrayRandom(IOR_param_t * test, int pretendRank,
}
static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offsetArray, int pretendRank,
IOR_offset_t * transferCount, int * errors, IOR_param_t * test, int * fd, IOR_io_buffers* ioBuffers, int access){
IOR_offset_t * transferCount, int * errors, IOR_param_t * test, aiori_fd_t * fd, IOR_io_buffers* ioBuffers, int access){
IOR_offset_t amtXferred = 0;
IOR_offset_t transfer;
@ -1862,26 +1816,26 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
void *checkBuffer = ioBuffers->checkBuffer;
void *readCheckBuffer = ioBuffers->readCheckBuffer;
test->offset = offsetArray[pairCnt];
IOR_offset_t offset = offsetArray[pairCnt]; // this looks inappropriate
transfer = test->transferSize;
if (access == WRITE) {
/* fills each transfer with a unique pattern
* containing the offset into the file */
if (test->storeFileOffset == TRUE) {
FillBuffer(buffer, test, test->offset, pretendRank);
FillBuffer(buffer, test, offset, pretendRank);
}
amtXferred =
backend->xfer(access, fd, buffer, transfer, test);
amtXferred = backend->xfer(access, fd, buffer, transfer, offset, 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);
}
} else if (access == READ) {
amtXferred =
backend->xfer(access, fd, buffer, transfer, test);
amtXferred = backend->xfer(access, fd, buffer, transfer, offset, test->backend_options);
if (amtXferred != transfer)
ERR("cannot read from file");
if (test->interIODelay > 0){
@ -1892,10 +1846,10 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
memset(checkBuffer, 'a', transfer);
if (test->storeFileOffset == TRUE) {
FillBuffer(readCheckBuffer, test, test->offset, pretendRank);
FillBuffer(readCheckBuffer, test, offset, pretendRank);
}
amtXferred = backend->xfer(access, fd, checkBuffer, transfer, test);
amtXferred = backend->xfer(access, fd, checkBuffer, transfer, offset, test->backend_options);
if (amtXferred != transfer)
ERR("cannot read from file write check");
(*transferCount)++;
@ -1905,12 +1859,12 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
} else if (access == READCHECK) {
memset(checkBuffer, 'a', transfer);
amtXferred = backend->xfer(access, fd, checkBuffer, transfer, test);
amtXferred = backend->xfer(access, fd, checkBuffer, transfer, offset, test->backend_options);
if (amtXferred != transfer){
ERR("cannot read from file");
}
if (test->storeFileOffset == TRUE) {
FillBuffer(readCheckBuffer, test, test->offset, pretendRank);
FillBuffer(readCheckBuffer, test, offset, pretendRank);
}
*errors += CompareBuffers(readCheckBuffer, checkBuffer, transfer, *transferCount, test, READCHECK);
}
@ -1922,7 +1876,7 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
* out the data to each block in transfer sizes, until the remainder left is 0.
*/
static IOR_offset_t WriteOrRead(IOR_param_t *test, IOR_results_t *results,
void *fd, const int access, IOR_io_buffers *ioBuffers)
aiori_fd_t *fd, const int access, IOR_io_buffers *ioBuffers)
{
int errors = 0;
IOR_offset_t transferCount = 0;
@ -1955,6 +1909,13 @@ static IOR_offset_t WriteOrRead(IOR_param_t *test, IOR_results_t *results,
hitStonewall = ((test->deadlineForStonewalling != 0
&& (GetTimeStamp() - startForStonewall)
> test->deadlineForStonewalling)) || (test->stoneWallingWearOutIterations != 0 && pairCnt == test->stoneWallingWearOutIterations) ;
if ( test->collective && test->deadlineForStonewalling ) {
// if collective-mode, you'll get a HANG, if some rank 'accidentally' leave this loop
// it absolutely must be an 'all or none':
MPI_CHECK(MPI_Bcast(&hitStonewall, 1, MPI_INT, 0, MPI_COMM_WORLD), "hitStonewall broadcast failed");
}
}
if (test->stoneWallingWearOut){
if (verbose >= VERBOSE_1){
@ -1995,7 +1956,7 @@ static IOR_offset_t WriteOrRead(IOR_param_t *test, IOR_results_t *results,
free(offsetArray);
if (access == WRITE && test->fsync == TRUE) {
backend->fsync(fd, test); /*fsync after all accesses */
backend->fsync(fd, test->backend_options); /*fsync after all accesses */
}
return (dataMoved);
}

View File

@ -35,10 +35,11 @@
typedef void *rados_t;
typedef void *rados_ioctx_t;
#endif
#include "option.h"
#include "iordef.h"
#include "aiori.h"
#define ISPOWEROFTWO(x) ((x != 0) && !(x & (x - 1)))
/******************** DATA Packet Type ***************************************/
/* Holds the types of data packets: generic, offset, timestamp, incompressible */
@ -79,29 +80,25 @@ typedef struct IO_BUFFERS
* USER_GUIDE
*/
struct ior_aiori;
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 */
MPI_Comm testComm; /* MPI communicator */
int dryRun; /* do not perform any I/Os just run evtl. inputs print dummy output */
int dualMount; /* dual mount points */
int numTasks; /* number of tasks for test */
int numNodes; /* number of nodes for test */
int numTasksOnNode0; /* number of tasks on node 0 (usually all the same, but don't have to be, use with caution) */
int tasksBlockMapping; /* are the tasks in contiguous blocks across nodes or round-robin */
int tasksBlockMapping; /* are the tasks in contiguous blocks across nodes or round-robin */
int repetitions; /* number of repetitions of test */
int repCounter; /* rep counter */
int multiFile; /* multiple files */
@ -121,17 +118,11 @@ 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 */
@ -146,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 */
@ -164,16 +154,6 @@ typedef struct
int fsyncPerWrite; /* fsync() after each write */
int fsync; /* fsync() after write */
/* MPI variables */
MPI_Comm testComm; /* MPI communicator */
MPI_Datatype transferType; /* datatype for transfer */
MPI_Datatype fileType; /* filetype for file view */
/* HDF5 variables */
int individualDataSets; /* datasets not shared by all procs */
int noFill; /* no fill in file creation */
IOR_offset_t setAlignment; /* alignment in bytes */
/* HDFS variables */
char * hdfs_user; /* copied from ENV, for now */
const char* hdfs_name_node;
@ -193,23 +173,10 @@ typedef struct
/* NCMPI variables */
int var_id; /* variable id handle for data set */
/* Lustre variables */
int lustre_stripe_count;
int lustre_stripe_size;
int lustre_start_ost;
int lustre_set_striping; /* flag that we need to set lustre striping */
int lustre_ignore_locks;
/* gpfs variables */
int gpfs_hint_access; /* use gpfs "access range" hint */
int gpfs_release_token; /* immediately release GPFS tokens after
creating or opening a file */
/* beegfs variables */
int beegfs_numTargets; /* number storage targets to use */
int beegfs_chunkSize; /* srtipe pattern for new files */
int id; /* test's unique ID */
int intraTestBarriers; /* barriers between open/op and op/close */
aiori_xfer_hint_t hints;
} IOR_param_t;
/* each pointer for a single test */
@ -242,7 +209,7 @@ typedef struct IOR_test_t {
IOR_test_t *CreateTest(IOR_param_t *init_params, int test_num);
void AllocResults(IOR_test_t *test);
char * GetPlatformName();
char * GetPlatformName(void);
void init_IOR_Param_t(IOR_param_t *p);
/*

View File

@ -181,13 +181,13 @@ typedef long long int IOR_size_t;
/* display error message and terminate execution */
#define ERR(MSG) do { \
#define ERR_ERRNO(MSG) do { \
ERRF("%s", MSG); \
} while (0)
/* display a simple error message (i.e. errno is not set) and terminate execution */
#define ERR_SIMPLE(MSG) do { \
#define ERR(MSG) do { \
fprintf(stdout, "ior ERROR: %s, (%s:%d)\n", \
MSG, __FILE__, __LINE__); \
fflush(stdout); \

View File

@ -166,8 +166,9 @@ static uid_t uid;
/* Use the POSIX backend by default */
static const ior_aiori_t *backend;
static IOR_param_t param;
static void * backend_options;
static aiori_xfer_hint_t hints;
static char * api = NULL;
/* This structure describes the processing status for stonewalling */
typedef struct{
@ -274,9 +275,9 @@ static void prep_testdir(int j, int dir_iter){
static void phase_end(){
if (call_sync){
if(! backend->sync){
FAIL("Error, backend does not provide the sync method, but your requested to use sync.");
FAIL("Error, backend does not provide the sync method, but you requested to use sync.\n");
}
backend->sync(& param);
backend->sync(backend_options);
}
if (barriers) {
@ -318,11 +319,11 @@ static void create_remove_dirs (const char *path, bool create, uint64_t itemNum)
VERBOSE(3,5,"create_remove_items_helper (dirs %s): curr_item is '%s'", operation, curr_item);
if (create) {
if (backend->mkdir(curr_item, DIRMODE, &param) == -1) {
if (backend->mkdir(curr_item, DIRMODE, backend_options) == -1) {
FAIL("unable to create directory %s", curr_item);
}
} else {
if (backend->rmdir(curr_item, &param) == -1) {
if (backend->rmdir(curr_item, backend_options) == -1) {
FAIL("unable to remove directory %s", curr_item);
}
}
@ -339,13 +340,13 @@ static void remove_file (const char *path, uint64_t itemNum) {
sprintf(curr_item, "%s/file.%s"LLU"", path, rm_name, itemNum);
VERBOSE(3,5,"create_remove_items_helper (non-dirs remove): curr_item is '%s'", curr_item);
if (!(shared_file && rank != 0)) {
backend->delete (curr_item, &param);
backend->delete (curr_item, backend_options);
}
}
static void create_file (const char *path, uint64_t itemNum) {
char curr_item[MAX_PATHLEN];
void *aiori_fh;
aiori_fd_t *aiori_fh = NULL;
if ( (itemNum % ITEM_COUNT==0 && (itemNum != 0))) {
VERBOSE(3,5,"create file: "LLU"", itemNum);
@ -355,36 +356,32 @@ 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);
if (collective_creates) {
param.openFlags = IOR_WRONLY;
if (make_node) {
int ret;
VERBOSE(3,5,"create_remove_items_helper : mknod..." );
ret = backend->mknod (curr_item);
if (ret != 0)
FAIL("unable to mknode file %s", curr_item);
return;
} else if (collective_creates) {
VERBOSE(3,5,"create_remove_items_helper (collective): open..." );
if (make_node)
aiori_fh = backend->mknod (curr_item);
else
aiori_fh = backend->open (curr_item, &param);
if (NULL == aiori_fh) {
aiori_fh = backend->open (curr_item, IOR_WRONLY | IOR_CREAT, backend_options);
if (NULL == aiori_fh)
FAIL("unable to open file %s", curr_item);
}
/*
* !collective_creates
*/
} else {
param.openFlags = IOR_CREAT | IOR_WRONLY;
param.filePerProc = !shared_file;
param.mode = FILEMODE;
hints.filePerProc = !shared_file;
VERBOSE(3,5,"create_remove_items_helper (non-collective, shared): open..." );
if (make_node)
aiori_fh = backend->mknod (curr_item);
else
aiori_fh = backend->create (curr_item, &param);
if (NULL == aiori_fh) {
aiori_fh = backend->create (curr_item, IOR_WRONLY | IOR_CREAT, backend_options);
if (NULL == aiori_fh)
FAIL("unable to create file %s", curr_item);
}
}
if (write_bytes > 0) {
@ -394,17 +391,14 @@ static void create_file (const char *path, uint64_t itemNum) {
* According to Bill Loewe, writes are only done one time, so they are always at
* offset 0 (zero).
*/
param.offset = 0;
param.fsyncPerWrite = sync_file;
if ( write_bytes != (size_t) backend->xfer (WRITE, aiori_fh, (IOR_size_t *) write_buffer, write_bytes, &param)) {
hints.fsyncPerWrite = sync_file;
if ( write_bytes != (size_t) backend->xfer (WRITE, aiori_fh, (IOR_size_t *) write_buffer, write_bytes, 0, backend_options)) {
FAIL("unable to write file %s", curr_item);
}
}
VERBOSE(3,5,"create_remove_items_helper: close..." );
if (!make_node)
backend->close (aiori_fh, &param);
backend->close (aiori_fh, backend_options);
}
/* helper for creating/removing items */
@ -448,20 +442,18 @@ void collective_helper(const int dirs, const int create, const char* path, uint6
VERBOSE(3,5,"create file: %s", curr_item);
if (create) {
void *aiori_fh;
aiori_fd_t *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, backend_options);
if (NULL == aiori_fh) {
FAIL("unable to create file %s", curr_item);
}
backend->close (aiori_fh, &param);
backend->close (aiori_fh, backend_options);
} else if (!(shared_file && rank != 0)) {
//remove files
backend->delete (curr_item, &param);
backend->delete (curr_item, backend_options);
}
if(CHECK_STONE_WALL(progress)){
progress->items_done = i + 1;
@ -618,7 +610,7 @@ void mdtest_stat(const int random, const int dirs, const long dir_iter, const ch
/* below temp used to be hiername */
VERBOSE(3,5,"mdtest_stat %4s: %s", (dirs ? "dir" : "file"), item);
if (-1 == backend->stat (item, &buf, &param)) {
if (-1 == backend->stat (item, &buf, backend_options)) {
FAIL("unable to stat %s %s", dirs ? "directory" : "file", item);
}
}
@ -629,14 +621,14 @@ void mdtest_stat(const int random, const int dirs, const long dir_iter, const ch
void mdtest_read(int random, int dirs, const long dir_iter, char *path) {
uint64_t parent_dir, item_num = 0;
char item[MAX_PATHLEN], temp[MAX_PATHLEN];
void *aiori_fh;
aiori_fd_t *aiori_fh;
VERBOSE(1,-1,"Entering mdtest_read on %s", path );
/* allocate read buffer */
if (read_bytes > 0) {
read_buffer = (char *)malloc(read_bytes);
if (read_buffer == NULL) {
int alloc_res = posix_memalign((void**)&read_buffer, sysconf(_SC_PAGESIZE), read_bytes);
if (alloc_res) {
FAIL("out of memory");
}
@ -715,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, backend_options);
if (NULL == aiori_fh) {
FAIL("unable to open file %s", item);
}
@ -724,7 +715,7 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) {
/* read file */
if (read_bytes > 0) {
read_buffer[0] = 42; /* use a random value to ensure that the read_buffer is now different from the expected buffer and read isn't sometimes NOOP */
if (read_bytes != (size_t) backend->xfer (READ, aiori_fh, (IOR_size_t *) read_buffer, read_bytes, &param)) {
if (read_bytes != (size_t) backend->xfer (READ, aiori_fh, (IOR_size_t *) read_buffer, read_bytes, 0, backend_options)) {
FAIL("unable to read file %s", item);
}
if(verify_read){
@ -736,7 +727,7 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) {
}
/* close file */
backend->close (aiori_fh, &param);
backend->close (aiori_fh, backend_options);
}
}
@ -1491,7 +1482,7 @@ void show_file_system_size(char *file_system) {
VERBOSE(1,-1,"Entering show_file_system_size on %s", file_system );
ret = backend->statfs (file_system, &stat_buf, &param);
ret = backend->statfs (file_system, &stat_buf, backend_options);
if (0 != ret) {
FAIL("unable to stat file system %s", file_system);
}
@ -1516,7 +1507,7 @@ void show_file_system_size(char *file_system) {
* 100;
if (realpath(file_system, real_path) == NULL) {
FAIL("unable to use realpath() on file system %s", file_system);
WARN("unable to use realpath() on file system");
}
@ -1555,9 +1546,6 @@ void display_freespace(char *testdirpath)
strcpy(dirpath, ".");
}
if (param.api && strcasecmp(param.api, "DFS") == 0)
return;
VERBOSE(3,5,"Before show_file_system_size, dirpath is '%s'", dirpath );
show_file_system_size(dirpath);
VERBOSE(3,5, "After show_file_system_size, dirpath is '%s'\n", dirpath );
@ -1579,7 +1567,7 @@ void create_remove_directory_tree(int create,
if (create) {
VERBOSE(2,5,"Making directory '%s'", dir);
if (-1 == backend->mkdir (dir, DIRMODE, &param)) {
if (-1 == backend->mkdir (dir, DIRMODE, backend_options)) {
fprintf(out_logfile, "error could not create directory '%s'\n", dir);
}
#ifdef HAVE_LUSTRE_LUSTREAPI
@ -1597,7 +1585,7 @@ void create_remove_directory_tree(int create,
if (!create) {
VERBOSE(2,5,"Remove directory '%s'", dir);
if (-1 == backend->rmdir(dir, &param)) {
if (-1 == backend->rmdir(dir, backend_options)) {
FAIL("Unable to remove directory %s", dir);
}
}
@ -1613,7 +1601,7 @@ void create_remove_directory_tree(int create,
if (create) {
VERBOSE(2,5,"Making directory '%s'", temp_path);
if (-1 == backend->mkdir(temp_path, DIRMODE, &param)) {
if (-1 == backend->mkdir(temp_path, DIRMODE, backend_options)) {
FAIL("Unable to create directory %s", temp_path);
}
}
@ -1624,7 +1612,7 @@ void create_remove_directory_tree(int create,
if (!create) {
VERBOSE(2,5,"Remove directory '%s'", temp_path);
if (-1 == backend->rmdir(temp_path, &param)) {
if (-1 == backend->rmdir(temp_path, backend_options)) {
FAIL("Unable to remove directory %s", temp_path);
}
}
@ -1653,8 +1641,8 @@ static void mdtest_iteration(int i, int j, MPI_Group testgroup, mdtest_results_t
prep_testdir(j, dir_iter);
VERBOSE(2,5,"main (for j loop): making testdir, '%s'", testdir );
if ((rank < path_count) && backend->access(testdir, F_OK, &param) != 0) {
if (backend->mkdir(testdir, DIRMODE, &param) != 0) {
if ((rank < path_count) && backend->access(testdir, F_OK, backend_options) != 0) {
if (backend->mkdir(testdir, DIRMODE, backend_options) != 0) {
FAIL("Unable to create test directory %s", testdir);
}
#ifdef HAVE_LUSTRE_LUSTREAPI
@ -1834,9 +1822,9 @@ static void mdtest_iteration(int i, int j, MPI_Group testgroup, mdtest_results_t
for (int dir_iter = 0; dir_iter < directory_loops; dir_iter ++){
prep_testdir(j, dir_iter);
if ((rank < path_count) && backend->access(testdir, F_OK, &param) == 0) {
if ((rank < path_count) && backend->access(testdir, F_OK, backend_options) == 0) {
//if (( rank == 0 ) && access(testdir, F_OK) == 0) {
if (backend->rmdir(testdir, &param) == -1) {
if (backend->rmdir(testdir, backend_options) == -1) {
FAIL("unable to remove directory %s", testdir);
}
}
@ -1917,9 +1905,10 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
aiori_supported_apis(APIs, APIs_legacy, MDTEST);
char apiStr[1024];
sprintf(apiStr, "API for I/O [%s]", APIs);
memset(& hints, 0, sizeof(hints));
option_help options [] = {
{'a', NULL, apiStr, OPTION_OPTIONAL_ARGUMENT, 's', & param.api},
{'a', NULL, apiStr, OPTION_OPTIONAL_ARGUMENT, 's', & api},
{'b', NULL, "branching factor of hierarchical directory structure", OPTION_OPTIONAL_ARGUMENT, 'd', & branch_factor},
{'d', NULL, "the directory in which the tests will run", OPTION_OPTIONAL_ARGUMENT, 's', & path},
{'B', NULL, "no barriers between phases", OPTION_OPTIONAL_ARGUMENT, 'd', & no_barriers},
@ -1964,17 +1953,26 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
};
options_all_t * global_options = airoi_create_all_module_options(options);
option_parse(argc, argv, global_options);
updateParsedOptions(& param, global_options);
backend = aiori_select(api);
if (backend == NULL)
ERR("Unrecognized I/O API");
backend_options = airoi_update_module_options(backend, global_options);
free(global_options->modules);
free(global_options);
backend = param.backend;
MPI_Comm_rank(testComm, &rank);
MPI_Comm_size(testComm, &size);
if (backend->initialize)
backend->initialize();
if (backend->initialize){
backend->initialize(backend_options);
}
if(backend->xfer_hints){
backend->xfer_hints(& hints);
}
if(backend->check_params){
backend->check_params(backend_options);
}
pid = getpid();
uid = getuid();
@ -2014,7 +2012,7 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
valid_tests();
// option_print_current(options);
VERBOSE(1,-1, "api : %s", param.api);
VERBOSE(1,-1, "api : %s", api);
VERBOSE(1,-1, "barriers : %s", ( barriers ? "True" : "False" ));
VERBOSE(1,-1, "collective_creates : %s", ( collective_creates ? "True" : "False" ));
VERBOSE(1,-1, "create_only : %s", ( create_only ? "True" : "False" ));
@ -2127,8 +2125,8 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
/* allocate and initialize write buffer with # */
if (write_bytes > 0) {
write_buffer = (char *)malloc(write_bytes);
if (write_buffer == NULL) {
int alloc_res = posix_memalign((void**)&write_buffer, sysconf(_SC_PAGESIZE), write_bytes);
if (alloc_res) {
FAIL("out of memory");
}
generate_memory_pattern(write_buffer, write_bytes);
@ -2146,8 +2144,8 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
}
/* if directory does not exist, create it */
if ((rank < path_count) && backend->access(testdirpath, F_OK, &param) != 0) {
if (backend->mkdir(testdirpath, DIRMODE, &param) != 0) {
if ((rank < path_count) && backend->access(testdirpath, F_OK, backend_options) != 0) {
if (backend->mkdir(testdirpath, DIRMODE, backend_options) != 0) {
FAIL("Unable to create test directory path %s", testdirpath);
}
}
@ -2265,8 +2263,9 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
free(rand_array);
}
if (backend->finalize)
backend->finalize(NULL);
if (backend->finalize){
backend->finalize(backend_options);
}
return summary_table;
}

View File

@ -241,116 +241,141 @@ static void option_parse_token(char ** argv, int * flag_parsed_next, int * requi
}
*flag_parsed_next = 0;
for(int m = 0; m < opt_all->module_count; m++ ){
option_help * args = opt_all->modules[m].options;
if(args == NULL) continue;
// try to find matching option help
for(option_help * o = args; o->shortVar != 0 || o->longVar != 0 || o->help != NULL ; o++ ){
if( o->shortVar == 0 && o->longVar == 0 ){
// section
continue;
}
if ( (txt[0] == '-' && o->shortVar == txt[1]) || (strlen(txt) > 2 && txt[0] == '-' && txt[1] == '-' && o->longVar != NULL && strcmp(txt + 2, o->longVar) == 0)){
// now process the option.
switch(o->arg){
case (OPTION_FLAG):{
assert(o->type == 'd');
if(arg != NULL){
int val = atoi(arg);
(*(int*) o->variable) = (val < 0) ? 0 : val;
}else{
(*(int*) o->variable)++;
}
break;
}
case (OPTION_OPTIONAL_ARGUMENT):
case (OPTION_REQUIRED_ARGUMENT):{
// check if next is an argument
if(arg == NULL){
if(o->shortVar == txt[1] && txt[2] != 0){
arg = & txt[2];
// just skip over the first dash so we don't have to handle it everywhere below
if(txt[0] != '-'){
*error = 1;
return;
}
txt++;
// support groups of multiple flags like -vvv or -vq
for(int flag_index = 0; flag_index < strlen(txt); ++flag_index){
// don't loop looking for multiple flags if we already processed a long option
if(txt[0] == '-' && flag_index > 0)
break;
for(int m = 0; m < opt_all->module_count; m++ ){
option_help * args = opt_all->modules[m].options;
if(args == NULL) continue;
// try to find matching option help
for(option_help * o = args; o->shortVar != 0 || o->longVar != 0 || o->help != NULL ; o++ ){
if( o->shortVar == 0 && o->longVar == 0 ){
// section
continue;
}
if ( (o->shortVar == txt[flag_index]) || (strlen(txt) > 2 && txt[0] == '-' && o->longVar != NULL && strcmp(txt + 1, o->longVar) == 0)){
// now process the option.
switch(o->arg){
case (OPTION_FLAG):{
assert(o->type == 'd');
if(arg != NULL){
int val = atoi(arg);
(*(int*) o->variable) = (val < 0) ? 0 : val;
}else{
// simply take the next value as argument
i++;
arg = argv[1];
*flag_parsed_next = 1;
(*(int*) o->variable)++;
}
break;
}
if(arg == NULL){
const char str[] = {o->shortVar, 0};
printf("Error, argument missing for option %s\n", (o->longVar != NULL) ? o->longVar : str);
exit(1);
}
switch(o->type){
case('p'):{
// call the function in the variable
void(*fp)() = o->variable;
fp(arg);
break;
}
case('F'):{
*(double*) o->variable = atof(arg);
break;
}
case('f'):{
*(float*) o->variable = atof(arg);
break;
}
case('d'):{
int64_t val = string_to_bytes(arg);
if (val > INT_MAX || val < INT_MIN){
printf("WARNING: parsing the number %s to integer, this produced an overflow!\n", arg);
case (OPTION_OPTIONAL_ARGUMENT):
case (OPTION_REQUIRED_ARGUMENT):{
// check if next is an argument
if(arg == NULL){
if(o->shortVar == txt[0] && txt[1] != 0){
arg = & txt[1];
}else{
// simply take the next value as argument
i++;
arg = argv[1];
*flag_parsed_next = 1;
}
*(int*) o->variable = val;
break;
}
case('H'):
case('s'):{
(*(char **) o->variable) = strdup(arg);
break;
if(arg == NULL){
const char str[] = {o->shortVar, 0};
printf("Error, argument missing for option %s\n", (o->longVar != NULL) ? o->longVar : str);
exit(1);
}
case('c'):{
(*(char *)o->variable) = arg[0];
if(strlen(arg) > 1){
printf("Error, ignoring remainder of string for option %c (%s).\n", o->shortVar, o->longVar);
switch(o->type){
case('p'):{
// call the function in the variable
void(*fp)() = o->variable;
fp(arg);
break;
}
break;
}
case('l'):{
*(long long*) o->variable = string_to_bytes(arg);
break;
}
case('u'):{
*(uint64_t*) o->variable = string_to_bytes(arg);
break;
case('F'):{
*(double*) o->variable = atof(arg);
break;
}
case('f'):{
*(float*) o->variable = atof(arg);
break;
}
case('d'):{
int64_t val = string_to_bytes(arg);
if (val > INT_MAX || val < INT_MIN){
printf("WARNING: parsing the number %s to integer, this produced an overflow!\n", arg);
}
*(int*) o->variable = val;
break;
}
case('H'):
case('s'):{
(*(char **) o->variable) = strdup(arg);
break;
}
case('c'):{
(*(char *)o->variable) = arg[0];
if(strlen(arg) > 1){
printf("Error, ignoring remainder of string for option %c (%s).\n", o->shortVar, o->longVar);
}
break;
}
case('l'):{
*(long long*) o->variable = string_to_bytes(arg);
break;
}
case('u'):{
*(uint64_t*) o->variable = string_to_bytes(arg);
break;
}
default:
printf("ERROR: Unknown option type %c\n", o->type);
break;
}
default:
printf("ERROR: Unknown option type %c\n", o->type);
}
}
}
if(replaced_equal){
arg[-1] = '=';
}
if(replaced_equal){
arg[-1] = '=';
}
if(o->arg == OPTION_REQUIRED_ARGUMENT){
(*requiredArgsSeen)++;
}
if(o->arg == OPTION_REQUIRED_ARGUMENT){
(*requiredArgsSeen)++;
}
return;
return;
}
}
}
}
if(strcmp(txt, "-h") == 0 || strcmp(txt, "--help") == 0){
if(strcmp(txt, "h") == 0 || strcmp(txt, "-help") == 0){
*print_help = 1;
}else{
*error = 1;
}
}
int option_parse_str(char*val, options_all_t * opt_all){
int flag_parsed_next;
int error = 0;
int requiredArgsSeen = 0;
int print_help = 0;
char * argv[2] = {val, NULL};
option_parse_token(argv, & flag_parsed_next, & requiredArgsSeen, opt_all, & error, & print_help);
return error;
}
int option_parse_key_value(char * key, char *val, options_all_t * opt_all){
int flag_parsed_next;
int error = 0;

View File

@ -23,10 +23,12 @@ typedef struct{
void * variable;
} option_help;
typedef struct aiori_mod_opt_t aiori_mod_opt_t;
typedef struct{
char * prefix; // may be NULL to include it in the standard name
option_help * options;
void * defaults; // these default values are taken from the command line
aiori_mod_opt_t * defaults; // these default values are taken from the command line
} option_module;
typedef struct{
@ -38,9 +40,9 @@ typedef struct{
int64_t string_to_bytes(char *size_str);
void option_print_current(option_help * args);
//@return the number of parsed arguments
int option_parse(int argc, char ** argv, options_all_t * args);
int option_parse_str(char*val, options_all_t * opt_all);
/* Parse a single line */
int option_parse_key_value(char * key, char * value, options_all_t * opt_all);

View File

@ -32,8 +32,6 @@
#include "option.h"
#include "aiori.h"
#define ISPOWEROFTWO(x) ((x != 0) && !(x & (x - 1)))
IOR_param_t initialTestParams;
option_help * createGlobalOptions(IOR_param_t * params);
@ -63,24 +61,6 @@ static void CheckRunSettings(IOR_test_t *tests)
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;
}
if(params->dualMount && !params->filePerProc) {
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "Dual Mount can only be used with File Per Process");
}
@ -143,8 +123,6 @@ void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_opt
params->testFileName = strdup(value);
} else if (strcasecmp(option, "dualmount") == 0){
params->dualMount = atoi(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) {
@ -205,34 +183,16 @@ void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_opt
params->blockSize = string_to_bytes(value);
} else if (strcasecmp(option, "transfersize") == 0) {
params->transferSize = string_to_bytes(value);
} else if (strcasecmp(option, "setalignment") == 0) {
params->setAlignment = string_to_bytes(value);
} else if (strcasecmp(option, "singlexferattempt") == 0) {
params->singleXferAttempt = atoi(value);
} else if (strcasecmp(option, "individualdatasets") == 0) {
params->individualDataSets = atoi(value);
} else if (strcasecmp(option, "intraTestBarriers") == 0) {
params->intraTestBarriers = atoi(value);
} else if (strcasecmp(option, "nofill") == 0) {
params->noFill = atoi(value);
} else if (strcasecmp(option, "verbose") == 0) {
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) {
@ -249,53 +209,6 @@ void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_opt
} else if (strcasecmp(option, "memoryPerNode") == 0) {
params->memoryPerNode = NodeMemoryStringToBytes(value);
params->memoryPerTask = 0;
} else if (strcasecmp(option, "lustrestripecount") == 0) {
#ifndef HAVE_LUSTRE_LUSTRE_USER_H
ERR("ior was not compiled with Lustre support");
#endif
params->lustre_stripe_count = atoi(value);
params->lustre_set_striping = 1;
} else if (strcasecmp(option, "lustrestripesize") == 0) {
#ifndef HAVE_LUSTRE_LUSTRE_USER_H
ERR("ior was not compiled with Lustre support");
#endif
params->lustre_stripe_size = string_to_bytes(value);
params->lustre_set_striping = 1;
} else if (strcasecmp(option, "lustrestartost") == 0) {
#ifndef HAVE_LUSTRE_LUSTRE_USER_H
ERR("ior was not compiled with Lustre support");
#endif
params->lustre_start_ost = atoi(value);
params->lustre_set_striping = 1;
} else if (strcasecmp(option, "lustreignorelocks") == 0) {
#ifndef HAVE_LUSTRE_LUSTRE_USER_H
ERR("ior was not compiled with Lustre support");
#endif
params->lustre_ignore_locks = atoi(value);
} else if (strcasecmp(option, "gpfshintaccess") == 0) {
#ifndef HAVE_GPFS_FCNTL_H
ERR("ior was not compiled with GPFS hint support");
#endif
params->gpfs_hint_access = atoi(value);
} else if (strcasecmp(option, "gpfsreleasetoken") == 0) {
#ifndef HAVE_GPFS_FCNTL_H
ERR("ior was not compiled with GPFS hint support");
#endif
params->gpfs_release_token = atoi(value);
} else if (strcasecmp(option, "beegfsNumTargets") == 0) {
#ifndef HAVE_BEEGFS_BEEGFS_H
ERR("ior was not compiled with BeeGFS support");
#endif
params->beegfs_numTargets = atoi(value);
if (params->beegfs_numTargets < 1)
ERR("beegfsNumTargets must be >= 1");
} else if (strcasecmp(option, "beegfsChunkSize") == 0) {
#ifndef HAVE_BEEGFS_BEEGFS_H
ERR("ior was not compiled with BeeGFS support");
#endif
params->beegfs_chunkSize = string_to_bytes(value);
if (!ISPOWEROFTWO(params->beegfs_chunkSize) || params->beegfs_chunkSize < (1<<16))
ERR("beegfsChunkSize must be a power of two and >64k");
} else if (strcasecmp(option, "summaryalways") == 0) {
params->summary_every_test = atoi(value);
} else {
@ -478,7 +391,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},
@ -495,34 +408,25 @@ 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},
{'J', NULL, "setAlignment -- HDF5 alignment in bytes (e.g.: 8, 4k, 2m, 1g)", OPTION_OPTIONAL_ARGUMENT, 'd', & params->setAlignment},
{'k', NULL, "keepFile -- don't remove the test file(s) on program exit", OPTION_FLAG, 'd', & params->keepFile},
{'K', NULL, "keepFileWithError -- keep error-filled file(s) after data-checking", OPTION_FLAG, 'd', & params->keepFileWithError},
{'l', NULL, "datapacket type-- type of packet that will be created [offset|incompressible|timestamp|o|i|t]", OPTION_OPTIONAL_ARGUMENT, 's', & params->buffer_type},
{'m', NULL, "multiFile -- use number of reps (-i) for multiple file count", OPTION_FLAG, 'd', & params->multiFile},
{'M', NULL, "memoryPerNode -- hog memory on the node (e.g.: 2g, 75%)", OPTION_OPTIONAL_ARGUMENT, 's', & params->memoryPerNodeStr},
{'n', NULL, "noFill -- no fill in HDF5 file creation", OPTION_FLAG, 'd', & params->noFill},
{'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},
@ -551,7 +455,7 @@ IOR_test_t *ParseCommandLine(int argc, char **argv)
IOR_test_t *tests = NULL;
GetPlatformName(initialTestParams.platform);
initialTestParams.platform = GetPlatformName();
option_help * options = createGlobalOptions( & initialTestParams);
parameters = & initialTestParams;

8
src/test/Makefile.am Executable file
View File

@ -0,0 +1,8 @@
LDFLAGS = $(extraLDFLAGS)
LDADD = ../libaiori.a $(extraLDADD)
# Add test here
TESTS = testlib testexample
check_PROGRAMS = $(TESTS)
testexample_SOURCES = example.c
testlib_SOURCES = lib.c

31
src/test/example.c Normal file
View File

@ -0,0 +1,31 @@
#include <assert.h>
#include <ior.h>
#include <ior-internal.h>
// build a single test via, e.g., mpicc example.c -I ../src/ ../src/libaiori.a -lm
int main(){
IOR_param_t test;
init_IOR_Param_t(& test);
test.blockSize = 10;
test.transferSize = 10;
test.segmentCount = 5;
test.numTasks = 2;
// having an individual file
test.filePerProc = 1;
IOR_offset_t * offsets;
offsets = GetOffsetArraySequential(& test, 0);
assert(offsets[0] == 0);
assert(offsets[1] == 10);
assert(offsets[2] == 20);
assert(offsets[3] == 30);
assert(offsets[4] == 40);
// for(int i = 0; i < test.segmentCount; i++){
// printf("%lld\n", (long long int) offsets[i]);
// }
printf("OK\n");
return 0;
}

View File

@ -47,6 +47,7 @@
#include "utilities.h"
#include "aiori.h"
#include "ior.h"
#include "ior-internal.h"
/************************** D E C L A R A T I O N S ***************************/
@ -146,7 +147,7 @@ void updateParsedOptions(IOR_param_t * options, options_all_t * global_options){
}
const ior_aiori_t * backend = aiori_select(options->api);
if (backend == NULL)
ERR_SIMPLE("unrecognized I/O API");
ERR("Unrecognized I/O API");
options->backend = backend;
/* copy the actual module options into the test */
@ -272,6 +273,15 @@ int QueryNodeMapping(MPI_Comm comm, int print_nodemap) {
* tasks on node rank 0.
*/
int GetNumNodes(MPI_Comm comm) {
if (getenv("IOR_FAKE_NODES")){
int numNodes = atoi(getenv("IOR_FAKE_NODES"));
int rank;
MPI_Comm_rank(comm, & rank);
if(rank == 0){
printf("Fake number of node: using %d\n", numNodes);
}
return numNodes;
}
#if MPI_VERSION >= 3
MPI_Comm shared_comm;
int shared_rank = 0;
@ -338,6 +348,15 @@ int GetNumTasks(MPI_Comm comm) {
* method will return the same value it always has.
*/
int GetNumTasksOnNode0(MPI_Comm comm) {
if (getenv("IOR_FAKE_TASK_PER_NODES")){
int tasksPerNode = atoi(getenv("IOR_FAKE_TASK_PER_NODES"));
int rank;
MPI_Comm_rank(comm, & rank);
if(rank == 0){
printf("Fake tasks per node: using %d\n", tasksPerNode);
}
return tasksPerNode;
}
#if MPI_VERSION >= 3
MPI_Comm shared_comm;
int shared_rank = 0;
@ -368,15 +387,6 @@ int GetNumTasksOnNode0(MPI_Comm comm) {
int size;
MPI_Comm_size(comm, & size);
/* for debugging and testing */
if (getenv("IOR_FAKE_TASK_PER_NODES")){
int tasksPerNode = atoi(getenv("IOR_FAKE_TASK_PER_NODES"));
int rank;
MPI_Comm_rank(comm, & rank);
if(rank == 0){
printf("Fake tasks per node: using %d\n", tasksPerNode);
}
return tasksPerNode;
}
char localhost[MAX_PATHLEN],
hostname[MAX_PATHLEN];
int count = 1,
@ -556,88 +566,66 @@ IOR_offset_t StringToBytes(char *size_str)
/*
* Displays size of file system and percent of data blocks and inodes used.
*/
void ShowFileSystemSize(char *fileSystem)
void ShowFileSystemSize(IOR_param_t * test) // this might be converted to an AIORI call
{
#ifndef _WIN32 /* FIXME */
char realPath[PATH_MAX];
char *fileSystemUnitStr;
long long int totalFileSystemSize;
long long int freeFileSystemSize;
long long int totalInodes;
long long int freeInodes;
double totalFileSystemSizeHR;
double usedFileSystemPercentage;
double usedInodePercentage;
#ifdef __sun /* SunOS does not support statfs(), instead uses statvfs() */
struct statvfs statusBuffer;
#else /* !__sun */
struct statfs statusBuffer;
#endif /* __sun */
ior_aiori_statfs_t stat;
if(! test->backend->statfs){
WARN("Backend doesn't implement statfs");
return;
}
char filename[MAX_PATHLEN];
GetTestFileName(filename, test);
int ret = test->backend->statfs(filename, & stat, test->backend_options);
if( ret != 0 ){
WARN("Backend returned error during statfs");
return;
}
long long int totalFileSystemSize;
long long int freeFileSystemSize;
long long int totalInodes;
long long int freeInodes;
double totalFileSystemSizeHR;
double usedFileSystemPercentage;
double usedInodePercentage;
char *fileSystemUnitStr;
#ifdef __sun
if (statvfs(fileSystem, &statusBuffer) != 0) {
ERR("unable to statvfs() file system");
}
#else /* !__sun */
if (statfs(fileSystem, &statusBuffer) != 0) {
ERR("unable to statfs() file system");
}
#endif /* __sun */
totalFileSystemSize = stat.f_blocks * stat.f_bsize;
freeFileSystemSize = stat.f_bfree * stat.f_bsize;
usedFileSystemPercentage = (1 - ((double)freeFileSystemSize / (double)totalFileSystemSize)) * 100;
totalFileSystemSizeHR = (double)totalFileSystemSize / (double)(1<<30);
/* data blocks */
#ifdef __sun
totalFileSystemSize = statusBuffer.f_blocks * statusBuffer.f_frsize;
freeFileSystemSize = statusBuffer.f_bfree * statusBuffer.f_frsize;
#else /* !__sun */
totalFileSystemSize = statusBuffer.f_blocks * statusBuffer.f_bsize;
freeFileSystemSize = statusBuffer.f_bfree * statusBuffer.f_bsize;
#endif /* __sun */
/* inodes */
totalInodes = stat.f_files;
freeInodes = stat.f_ffree;
usedInodePercentage = (1 - ((double)freeInodes / (double)totalInodes)) * 100;
usedFileSystemPercentage = (1 - ((double)freeFileSystemSize
/ (double)totalFileSystemSize)) * 100;
totalFileSystemSizeHR =
(double)totalFileSystemSize / (double)(1<<30);
fileSystemUnitStr = "GiB";
if (totalFileSystemSizeHR > 1024) {
totalFileSystemSizeHR = (double)totalFileSystemSize / (double)((long long)1<<40);
fileSystemUnitStr = "TiB";
}
fileSystemUnitStr = "GiB";
if (totalFileSystemSizeHR > 1024) {
totalFileSystemSizeHR = (double)totalFileSystemSize / (double)((long long)1<<40);
fileSystemUnitStr = "TiB";
}
if(outputFormat == OUTPUT_DEFAULT){
fprintf(out_resultfile, "%-20s: %s\n", "Path", filename);
fprintf(out_resultfile, "%-20s: %.1f %s Used FS: %2.1f%% ",
"FS", totalFileSystemSizeHR, fileSystemUnitStr,
usedFileSystemPercentage);
fprintf(out_resultfile, "Inodes: %.1f Mi Used Inodes: %2.1f%%\n",
(double)totalInodes / (double)(1<<20),
usedInodePercentage);
fflush(out_logfile);
}else if(outputFormat == OUTPUT_JSON){
fprintf(out_resultfile, " , \"Path\": \"%s\",", filename);
fprintf(out_resultfile, "\"Capacity\": \"%.1f %s\", \"Used Capacity\": \"%2.1f%%\",",
totalFileSystemSizeHR, fileSystemUnitStr,
usedFileSystemPercentage);
fprintf(out_resultfile, "\"Inodes\": \"%.1f Mi\", \"Used Inodes\" : \"%2.1f%%\"\n",
(double)totalInodes / (double)(1<<20),
usedInodePercentage);
}else if(outputFormat == OUTPUT_CSV){
/* inodes */
totalInodes = statusBuffer.f_files;
freeInodes = statusBuffer.f_ffree;
usedInodePercentage =
(1 - ((double)freeInodes / (double)totalInodes)) * 100;
}
/* show results */
if (realpath(fileSystem, realPath) == NULL) {
ERR("unable to use realpath()");
}
if(outputFormat == OUTPUT_DEFAULT){
fprintf(out_resultfile, "%-20s: %s\n", "Path", realPath);
fprintf(out_resultfile, "%-20s: %.1f %s Used FS: %2.1f%% ",
"FS", totalFileSystemSizeHR, fileSystemUnitStr,
usedFileSystemPercentage);
fprintf(out_resultfile, "Inodes: %.1f Mi Used Inodes: %2.1f%%\n",
(double)totalInodes / (double)(1<<20),
usedInodePercentage);
fflush(out_logfile);
}else if(outputFormat == OUTPUT_JSON){
fprintf(out_resultfile, " , \"Path\": \"%s\",", realPath);
fprintf(out_resultfile, "\"Capacity\": \"%.1f %s\", \"Used Capacity\": \"%2.1f%%\",",
totalFileSystemSizeHR, fileSystemUnitStr,
usedFileSystemPercentage);
fprintf(out_resultfile, "\"Inodes\": \"%.1f Mi\", \"Used Inodes\" : \"%2.1f%%\"\n",
(double)totalInodes / (double)(1<<20),
usedInodePercentage);
}else if(outputFormat == OUTPUT_CSV){
}
#endif /* !_WIN32 */
return;
return;
}
/*

View File

@ -47,7 +47,7 @@ void set_o_direct_flag(int *fd);
char *CurrentTimeString(void);
int Regex(char *, char *);
void ShowFileSystemSize(char *);
void ShowFileSystemSize(IOR_param_t * test);
void DumpBuffer(void *, size_t);
void SeedRandGen(MPI_Comm);
void SetHints (MPI_Info *, char *);