Merge pull request #225 from hpc/fix-modules

Improve AIORI module behavior
master
Julian Kunkel 2020-06-24 09:26:19 +01:00 committed by GitHub
commit 6e507f732c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1089 additions and 1137 deletions

View File

@ -24,15 +24,16 @@
#include <libgen.h> #include <libgen.h>
#include <stdbool.h> #include <stdbool.h>
#include <mpi.h>
#include <gurt/common.h> #include <gurt/common.h>
#include <daos.h> #include <daos.h>
#include "ior.h"
#include "aiori.h" #include "aiori.h"
#include "utilities.h"
#include "iordef.h" #include "iordef.h"
/************************** O P T I O N S *****************************/ /************************** O P T I O N S *****************************/
struct daos_options{ typedef struct {
char *pool; char *pool;
char *svcl; char *svcl;
char *group; char *group;
@ -40,49 +41,62 @@ struct daos_options{
int chunk_size; int chunk_size;
int destroy; int destroy;
char *oclass; char *oclass;
}; } DAOS_options_t;
static struct daos_options o = { static option_help * DAOS_options(aiori_mod_opt_t ** init_backend_options,
.pool = NULL, aiori_mod_opt_t * init_values){
.svcl = NULL, DAOS_options_t * o = malloc(sizeof(DAOS_options_t));
.group = NULL,
.cont = NULL,
.chunk_size = 1048576,
.destroy = 0,
.oclass = NULL,
};
static option_help options [] = { if (init_values != NULL) {
{0, "daos.pool", "pool uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o.pool}, memcpy(o, init_values, sizeof(DAOS_options_t));
{0, "daos.svcl", "pool SVCL", OPTION_OPTIONAL_ARGUMENT, 's', &o.svcl}, } else {
{0, "daos.group", "server group", OPTION_OPTIONAL_ARGUMENT, 's', &o.group}, memset(o, 0, sizeof(DAOS_options_t));
{0, "daos.cont", "container uuid", OPTION_OPTIONAL_ARGUMENT, 's', &o.cont}, /* initialize the options properly */
{0, "daos.chunk_size", "chunk size", OPTION_OPTIONAL_ARGUMENT, 'd', &o.chunk_size}, o->chunk_size = 1048576;
{0, "daos.destroy", "Destroy Container", OPTION_FLAG, 'd', &o.destroy}, }
{0, "daos.oclass", "object class", OPTION_OPTIONAL_ARGUMENT, 's', &o.oclass},
LAST_OPTION *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 *****************************/ /**************************** P R O T O T Y P E S *****************************/
static void DAOS_Init(); static void DAOS_Init(aiori_mod_opt_t *);
static void DAOS_Fini(); static void DAOS_Fini(aiori_mod_opt_t *);
static void *DAOS_Create(char *, IOR_param_t *); static aiori_fd_t *DAOS_Create(char *, int, aiori_mod_opt_t *);
static void *DAOS_Open(char *, IOR_param_t *); static aiori_fd_t *DAOS_Open(char *, int, aiori_mod_opt_t *);
static int DAOS_Access(const char *, int, IOR_param_t *); static int DAOS_Access(const char *, int, aiori_mod_opt_t *);
static IOR_offset_t DAOS_Xfer(int, void *, IOR_size_t *, static IOR_offset_t DAOS_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t,
IOR_offset_t, IOR_param_t *); IOR_offset_t, aiori_mod_opt_t *);
static void DAOS_Close(void *, IOR_param_t *); static void DAOS_Close(aiori_fd_t *, aiori_mod_opt_t *);
static void DAOS_Delete(char *, IOR_param_t *); static void DAOS_Delete(char *, aiori_mod_opt_t *);
static char* DAOS_GetVersion(); static char* DAOS_GetVersion();
static void DAOS_Fsync(void *, IOR_param_t *); static void DAOS_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static IOR_offset_t DAOS_GetFileSize(IOR_param_t *, MPI_Comm, char *); static IOR_offset_t DAOS_GetFileSize(aiori_mod_opt_t *, MPI_Comm, char *);
static option_help * DAOS_options(); 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 ***************************/ /************************** D E C L A R A T I O N S ***************************/
ior_aiori_t daos_aiori = { ior_aiori_t daos_aiori = {
.name = "DAOS", .name = "DAOS",
.initialize = DAOS_Init,
.finalize = DAOS_Fini,
.create = DAOS_Create, .create = DAOS_Create,
.open = DAOS_Open, .open = DAOS_Open,
.access = DAOS_Access, .access = DAOS_Access,
@ -90,15 +104,17 @@ ior_aiori_t daos_aiori = {
.close = DAOS_Close, .close = DAOS_Close,
.delete = DAOS_Delete, .delete = DAOS_Delete,
.get_version = DAOS_GetVersion, .get_version = DAOS_GetVersion,
.xfer_hints = DAOS_init_xfer_options,
.fsync = DAOS_Fsync, .fsync = DAOS_Fsync,
.get_file_size = DAOS_GetFileSize, .get_file_size = DAOS_GetFileSize,
.initialize = DAOS_Init,
.finalize = DAOS_Fini,
.get_options = DAOS_options,
.statfs = aiori_posix_statfs, .statfs = aiori_posix_statfs,
.mkdir = aiori_posix_mkdir, .mkdir = aiori_posix_mkdir,
.rmdir = aiori_posix_rmdir, .rmdir = aiori_posix_rmdir,
.stat = aiori_posix_stat, .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 #define IOR_DAOS_MUR_SEED 0xDEAD10CC
@ -144,6 +160,22 @@ do { \
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error"); \ MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error"); \
} while (0) } 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. */ /* Distribute process 0's pool or container handle to others. */
static void static void
HandleDistribute(daos_handle_t *handle, enum handleType type) HandleDistribute(daos_handle_t *handle, enum handleType type)
@ -202,27 +234,22 @@ HandleDistribute(daos_handle_t *handle, enum handleType type)
free(global.iov_buf); free(global.iov_buf);
} }
static option_help *
DAOS_options()
{
return options;
}
static void static void
DAOS_Init() DAOS_Init(aiori_mod_opt_t * options)
{ {
DAOS_options_t *o = (DAOS_options_t *)options;
int rc; int rc;
if (daos_initialized) if (daos_initialized)
return; return;
if (o.pool == NULL || o.svcl == NULL || o.cont == NULL) if (o->pool == NULL || o->svcl == NULL || o->cont == NULL)
return; return;
if (o.oclass) { if (o->oclass) {
objectClass = daos_oclass_name2id(o.oclass); objectClass = daos_oclass_name2id(o->oclass);
if (objectClass == OC_UNKNOWN) 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(); rc = daos_init();
@ -235,25 +262,25 @@ DAOS_Init()
static daos_pool_info_t po_info; static daos_pool_info_t po_info;
static daos_cont_info_t co_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); rc = uuid_parse(o->pool, uuid);
DCHECK(rc, "Failed to parse 'pool': %s", o.pool); 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) if (svcl == NULL)
ERR("Failed to allocate svcl"); 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); &poh, &po_info, NULL);
d_rank_list_free(svcl); 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); uuid_clear(uuid);
rc = uuid_parse(o.cont, uuid); rc = uuid_parse(o->cont, uuid);
DCHECK(rc, "Failed to parse 'cont': %s", o.cont); DCHECK(rc, "Failed to parse 'cont': %s", o->cont);
rc = daos_cont_open(poh, uuid, DAOS_COO_RW, &coh, &co_info, rc = daos_cont_open(poh, uuid, DAOS_COO_RW, &coh, &co_info,
NULL); NULL);
@ -276,8 +303,9 @@ DAOS_Init()
} }
static void static void
DAOS_Fini() DAOS_Fini(aiori_mod_opt_t *options)
{ {
DAOS_options_t *o = (DAOS_options_t *)options;
int rc; int rc;
if (!daos_initialized) if (!daos_initialized)
@ -286,18 +314,18 @@ DAOS_Fini()
MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD);
rc = daos_cont_close(coh, NULL); rc = daos_cont_close(coh, NULL);
if (rc) { 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_Abort(MPI_COMM_WORLD, -1);
} }
MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD);
if (o.destroy) { if (o->destroy) {
if (rank == 0) { if (rank == 0) {
uuid_t uuid; uuid_t uuid;
double t1, t2; double t1, t2;
INFO(VERBOSE_1, "Destroying DAOS Container %s", o.cont); INFO(VERBOSE_1, "Destroying DAOS Container %s", o->cont);
uuid_parse(o.cont, uuid); uuid_parse(o->cont, uuid);
t1 = MPI_Wtime(); t1 = MPI_Wtime();
rc = daos_cont_destroy(poh, uuid, 1, NULL); rc = daos_cont_destroy(poh, uuid, 1, NULL);
t2 = MPI_Wtime(); t2 = MPI_Wtime();
@ -308,7 +336,7 @@ DAOS_Fini()
MPI_Bcast(&rc, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&rc, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (rc) { if (rc) {
if (rank == 0) 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); MPI_Abort(MPI_COMM_WORLD, -1);
} }
} }
@ -317,7 +345,7 @@ DAOS_Fini()
INFO(VERBOSE_1, "Disconnecting from DAOS POOL.."); INFO(VERBOSE_1, "Disconnecting from DAOS POOL..");
rc = daos_pool_disconnect(poh, NULL); 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"); MPI_CHECK(MPI_Barrier(MPI_COMM_WORLD), "barrier error");
if (rank == 0) if (rank == 0)
@ -332,38 +360,38 @@ DAOS_Fini()
static void static void
gen_oid(const char *name, daos_obj_id_t *oid) gen_oid(const char *name, daos_obj_id_t *oid)
{ {
oid->lo = d_hash_murmur64(name, strlen(name), IOR_DAOS_MUR_SEED); oid->lo = d_hash_murmur64(name, strlen(name), IOR_DAOS_MUR_SEED);
oid->hi = 0; oid->hi = 0;
daos_array_generate_id(oid, objectClass, true, 0); daos_array_generate_id(oid, objectClass, true, 0);
} }
static void * static aiori_fd_t *
DAOS_Create(char *testFileName, IOR_param_t *param) DAOS_Create(char *testFileName, int flags, aiori_mod_opt_t *param)
{ {
DAOS_options_t *o = (DAOS_options_t*) param;
daos_obj_id_t oid; daos_obj_id_t oid;
int rc; int rc;
/** Convert file name into object ID */ /** Convert file name into object ID */
gen_oid(testFileName, &oid); gen_oid(testFileName, &oid);
/** Create the array */ /** Create the array */
if (param->filePerProc || rank == 0) { if (hints->filePerProc || rank == 0) {
rc = daos_array_create(coh, oid, DAOS_TX_NONE, 1, o.chunk_size, rc = daos_array_create(coh, oid, DAOS_TX_NONE, 1, o->chunk_size,
&aoh, NULL); &aoh, NULL);
DCHECK(rc, "Failed to create array object\n"); DCHECK(rc, "Failed to create array object\n");
} }
/** Distribute the array handle if not FPP */ /** Distribute the array handle if not FPP */
if (!param->filePerProc) if (!hints->filePerProc)
HandleDistribute(&aoh, ARRAY_HANDLE); HandleDistribute(&aoh, ARRAY_HANDLE);
return &aoh; return (aiori_fd_t*)(&aoh);
} }
static int 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_obj_id_t oid;
daos_size_t cell_size, chunk_size; daos_size_t cell_size, chunk_size;
@ -385,8 +413,8 @@ DAOS_Access(const char *testFileName, int mode, IOR_param_t * param)
return rc; return rc;
} }
static void * static aiori_fd_t *
DAOS_Open(char *testFileName, IOR_param_t *param) DAOS_Open(char *testFileName, int flags, aiori_mod_opt_t *param)
{ {
daos_obj_id_t oid; daos_obj_id_t oid;
@ -394,7 +422,7 @@ DAOS_Open(char *testFileName, IOR_param_t *param)
gen_oid(testFileName, &oid); gen_oid(testFileName, &oid);
/** Open the array */ /** Open the array */
if (param->filePerProc || rank == 0) { if (hints->filePerProc || rank == 0) {
daos_size_t cell_size, chunk_size; daos_size_t cell_size, chunk_size;
int rc; int rc;
@ -407,15 +435,15 @@ DAOS_Open(char *testFileName, IOR_param_t *param)
} }
/** Distribute the array handle if not FPP */ /** Distribute the array handle if not FPP */
if (!param->filePerProc) if (!hints->filePerProc)
HandleDistribute(&aoh, ARRAY_HANDLE); HandleDistribute(&aoh, ARRAY_HANDLE);
return &aoh; return (aiori_fd_t*)(&aoh);
} }
static IOR_offset_t static IOR_offset_t
DAOS_Xfer(int access, void *file, IOR_size_t *buffer, DAOS_Xfer(int access, aiori_fd_t *file, IOR_size_t *buffer, IOR_offset_t length,
IOR_offset_t length, IOR_param_t *param) IOR_offset_t off, aiori_mod_opt_t *param)
{ {
daos_array_iod_t iod; daos_array_iod_t iod;
daos_range_t rg; daos_range_t rg;
@ -426,7 +454,7 @@ DAOS_Xfer(int access, void *file, IOR_size_t *buffer,
/** set array location */ /** set array location */
iod.arr_nr = 1; iod.arr_nr = 1;
rg.rg_len = length; rg.rg_len = length;
rg.rg_idx = param->offset; rg.rg_idx = off;
iod.arr_rgs = &rg; iod.arr_rgs = &rg;
/** set memory location */ /** set memory location */
@ -446,7 +474,7 @@ DAOS_Xfer(int access, void *file, IOR_size_t *buffer,
} }
static void static void
DAOS_Close(void *file, IOR_param_t *param) DAOS_Close(aiori_fd_t *file, aiori_mod_opt_t *param)
{ {
int rc; int rc;
@ -460,7 +488,7 @@ DAOS_Close(void *file, IOR_param_t *param)
} }
static void 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_obj_id_t oid;
daos_size_t cell_size, chunk_size; daos_size_t cell_size, chunk_size;
@ -498,13 +526,13 @@ DAOS_GetVersion()
} }
static void static void
DAOS_Fsync(void *file, IOR_param_t *param) DAOS_Fsync(aiori_fd_t *file, aiori_mod_opt_t *param)
{ {
return; return;
} }
static IOR_offset_t 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_obj_id_t oid;
daos_size_t size; daos_size_t size;
@ -517,7 +545,7 @@ DAOS_GetFileSize(IOR_param_t *param, MPI_Comm testComm, char *testFileName)
gen_oid(testFileName, &oid); gen_oid(testFileName, &oid);
/** open the array to verify it exists */ /** open the array to verify it exists */
if (param->filePerProc || rank == 0) { if (hints->filePerProc || rank == 0) {
daos_size_t cell_size, chunk_size; daos_size_t cell_size, chunk_size;
rc = daos_array_open(coh, oid, DAOS_TX_NONE, DAOS_OO_RO, rc = daos_array_open(coh, oid, DAOS_TX_NONE, DAOS_OO_RO,
@ -535,7 +563,7 @@ DAOS_GetFileSize(IOR_param_t *param, MPI_Comm testComm, char *testFileName)
aoh.cookie = 0; aoh.cookie = 0;
} }
if (!param->filePerProc) if (!hints->filePerProc)
MPI_Bcast(&size, 1, MPI_LONG, 0, MPI_COMM_WORLD); MPI_Bcast(&size, 1, MPI_LONG, 0, MPI_COMM_WORLD);
return size; return size;

View File

@ -27,15 +27,15 @@
#include <fcntl.h> #include <fcntl.h>
#include <libgen.h> #include <libgen.h>
#include <mpi.h>
#include <gurt/common.h> #include <gurt/common.h>
#include <gurt/hash.h> #include <gurt/hash.h>
#include <daos.h> #include <daos.h>
#include <daos_fs.h> #include <daos_fs.h>
#include "ior.h"
#include "iordef.h"
#include "aiori.h" #include "aiori.h"
#include "utilities.h" #include "utilities.h"
#include "iordef.h"
dfs_t *dfs; dfs_t *dfs;
static daos_handle_t poh, coh; static daos_handle_t poh, coh;
@ -57,7 +57,7 @@ enum handleType {
}; };
/************************** O P T I O N S *****************************/ /************************** O P T I O N S *****************************/
struct dfs_options{ typedef struct {
char *pool; char *pool;
char *svcl; char *svcl;
char *group; char *group;
@ -67,57 +67,69 @@ struct dfs_options{
char *dir_oclass; char *dir_oclass;
char *prefix; char *prefix;
int destroy; int destroy;
}; } DFS_options_t;
static struct dfs_options o = { static option_help * DFS_options(aiori_mod_opt_t ** init_backend_options,
.pool = NULL, aiori_mod_opt_t * init_values){
.svcl = NULL, DFS_options_t * o = malloc(sizeof(DFS_options_t));
.group = NULL,
.cont = NULL,
.chunk_size = 1048576,
.oclass = NULL,
.dir_oclass = NULL,
.prefix = NULL,
.destroy = 0,
};
static option_help options [] = { if (init_values != NULL) {
{0, "dfs.pool", "pool uuid", OPTION_OPTIONAL_ARGUMENT, 's', & o.pool}, memcpy(o, init_values, sizeof(DFS_options_t));
{0, "dfs.svcl", "pool SVCL", OPTION_OPTIONAL_ARGUMENT, 's', & o.svcl}, } else {
{0, "dfs.group", "server group", OPTION_OPTIONAL_ARGUMENT, 's', & o.group}, memset(o, 0, sizeof(DFS_options_t));
{0, "dfs.cont", "DFS container uuid", OPTION_OPTIONAL_ARGUMENT, 's', & o.cont}, /* initialize the options properly */
{0, "dfs.chunk_size", "chunk size", OPTION_OPTIONAL_ARGUMENT, 'd', &o.chunk_size}, o->chunk_size = 1048576;
{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}, *init_backend_options = (aiori_mod_opt_t *) o;
{0, "dfs.destroy", "Destroy DFS Container", OPTION_FLAG, 'd', &o.destroy},
LAST_OPTION 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 *****************************/ /**************************** P R O T O T Y P E S *****************************/
static void *DFS_Create(char *, IOR_param_t *); static void DFS_Init(aiori_mod_opt_t *);
static void *DFS_Open(char *, IOR_param_t *); static void DFS_Finalize(aiori_mod_opt_t *);
static IOR_offset_t DFS_Xfer(int, void *, IOR_size_t *, static aiori_fd_t *DFS_Create(char *, int, aiori_mod_opt_t *);
IOR_offset_t, IOR_param_t *); static aiori_fd_t *DFS_Open(char *, int, aiori_mod_opt_t *);
static void DFS_Close(void *, IOR_param_t *); static IOR_offset_t DFS_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t,
static void DFS_Delete(char *, IOR_param_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 char* DFS_GetVersion();
static void DFS_Fsync(void *, IOR_param_t *); static void DFS_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static void DFS_Sync(IOR_param_t *); static void DFS_Sync(aiori_mod_opt_t *);
static IOR_offset_t DFS_GetFileSize(IOR_param_t *, MPI_Comm, char *); static IOR_offset_t DFS_GetFileSize(aiori_mod_opt_t *, MPI_Comm, char *);
static int DFS_Statfs (const char *, ior_aiori_statfs_t *, IOR_param_t *); static int DFS_Statfs (const char *, ior_aiori_statfs_t *, aiori_mod_opt_t *);
static int DFS_Stat (const char *, struct stat *, IOR_param_t *); static int DFS_Stat (const char *, struct stat *, aiori_mod_opt_t *);
static int DFS_Mkdir (const char *, mode_t, IOR_param_t *); static int DFS_Mkdir (const char *, mode_t, aiori_mod_opt_t *);
static int DFS_Rmdir (const char *, IOR_param_t *); static int DFS_Rmdir (const char *, aiori_mod_opt_t *);
static int DFS_Access (const char *, int, IOR_param_t *); static int DFS_Access (const char *, int, aiori_mod_opt_t *);
static void DFS_Init();
static void DFS_Finalize();
static option_help * DFS_options(); 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 ***************************/ /************************** D E C L A R A T I O N S ***************************/
ior_aiori_t dfs_aiori = { ior_aiori_t dfs_aiori = {
.name = "DFS", .name = "DFS",
.initialize = DFS_Init,
.finalize = DFS_Finalize,
.create = DFS_Create, .create = DFS_Create,
.open = DFS_Open, .open = DFS_Open,
.xfer = DFS_Xfer, .xfer = DFS_Xfer,
@ -127,14 +139,14 @@ ior_aiori_t dfs_aiori = {
.fsync = DFS_Fsync, .fsync = DFS_Fsync,
.sync = DFS_Sync, .sync = DFS_Sync,
.get_file_size = DFS_GetFileSize, .get_file_size = DFS_GetFileSize,
.xfer_hints = DFS_init_xfer_options,
.statfs = DFS_Statfs, .statfs = DFS_Statfs,
.mkdir = DFS_Mkdir, .mkdir = DFS_Mkdir,
.rmdir = DFS_Rmdir, .rmdir = DFS_Rmdir,
.access = DFS_Access, .access = DFS_Access,
.stat = DFS_Stat, .stat = DFS_Stat,
.initialize = DFS_Init,
.finalize = DFS_Finalize,
.get_options = DFS_options, .get_options = DFS_options,
.check_params = DFS_check_params,
.enable_mdtest = true, .enable_mdtest = true,
}; };
@ -166,6 +178,22 @@ do { \
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error"); \ MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), "MPI_Abort() error"); \
} while (0) } 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 * static inline struct aiori_dir_hdl *
hdl_obj(d_list_t *rlink) hdl_obj(d_list_t *rlink)
{ {
@ -379,12 +407,10 @@ lookup_insert_dir(const char *name, mode_t *mode)
return hdl->oh; return hdl->oh;
} }
static option_help * DFS_options(){
return options;
}
static void static void
DFS_Init() { DFS_Init(aiori_mod_opt_t * options)
{
DFS_options_t *o = (DFS_options_t *)options;
int rc; int rc;
/** in case we are already initialized, return */ /** in case we are already initialized, return */
@ -392,22 +418,22 @@ DFS_Init() {
return; return;
/** shouldn't be fatal since it can be called with POSIX backend selection */ /** shouldn't be fatal since it can be called with POSIX backend selection */
if (o.pool == NULL || o.svcl == NULL || o.cont == NULL) if (o->pool == NULL || o->svcl == NULL || o->cont == NULL)
return; return;
rc = daos_init(); rc = daos_init();
DCHECK(rc, "Failed to initialize daos"); DCHECK(rc, "Failed to initialize daos");
if (o.oclass) { if (o->oclass) {
objectClass = daos_oclass_name2id(o.oclass); objectClass = daos_oclass_name2id(o->oclass);
if (objectClass == OC_UNKNOWN) if (objectClass == OC_UNKNOWN)
GERR("Invalid DAOS object class %s\n", o.oclass); GERR("Invalid DAOS object class %s\n", o->oclass);
} }
if (o.dir_oclass) { if (o->dir_oclass) {
dir_oclass = daos_oclass_name2id(o.dir_oclass); dir_oclass = daos_oclass_name2id(o->dir_oclass);
if (dir_oclass == OC_UNKNOWN) if (dir_oclass == OC_UNKNOWN)
GERR("Invalid DAOS directory object class %s\n", o.dir_oclass); GERR("Invalid DAOS directory object class %s\n", o->dir_oclass);
} }
rc = d_hash_table_create(0, 16, NULL, &hdl_hash_ops, &dir_hash); rc = d_hash_table_create(0, 16, NULL, &hdl_hash_ops, &dir_hash);
@ -419,21 +445,21 @@ DFS_Init() {
daos_pool_info_t pool_info; daos_pool_info_t pool_info;
daos_cont_info_t co_info; daos_cont_info_t co_info;
rc = uuid_parse(o.pool, pool_uuid); rc = uuid_parse(o->pool, pool_uuid);
DCHECK(rc, "Failed to parse 'Pool uuid': %s", o.pool); DCHECK(rc, "Failed to parse 'Pool uuid': %s", o->pool);
rc = uuid_parse(o.cont, co_uuid); rc = uuid_parse(o->cont, co_uuid);
DCHECK(rc, "Failed to parse 'Cont uuid': %s", o.cont); 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) if (svcl == NULL)
ERR("Failed to allocate svcl"); ERR("Failed to allocate svcl");
INFO(VERBOSE_1, "Pool uuid = %s, SVCL = %s\n", o.pool, o.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, "DFS Container namespace uuid = %s\n", o->cont);
/** Connect to DAOS pool */ /** 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); &poh, &pool_info, NULL);
d_rank_list_free(svcl); d_rank_list_free(svcl);
DCHECK(rc, "Failed to connect to pool"); DCHECK(rc, "Failed to connect to pool");
@ -459,16 +485,17 @@ DFS_Init() {
HandleDistribute(CONT_HANDLE); HandleDistribute(CONT_HANDLE);
HandleDistribute(DFS_HANDLE); HandleDistribute(DFS_HANDLE);
if (o.prefix) { if (o->prefix) {
rc = dfs_set_prefix(dfs, o.prefix); rc = dfs_set_prefix(dfs, o->prefix);
DCHECK(rc, "Failed to set DFS Prefix"); DCHECK(rc, "Failed to set DFS Prefix");
} }
dfs_init = true; dfs_init = true;
} }
static void static void
DFS_Finalize() DFS_Finalize(aiori_mod_opt_t *options)
{ {
DFS_options_t *o = (DFS_options_t *)options;
int rc; int rc;
MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD);
@ -479,16 +506,16 @@ DFS_Finalize()
MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD);
rc = daos_cont_close(coh, NULL); 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); MPI_Barrier(MPI_COMM_WORLD);
if (o.destroy) { if (o->destroy) {
if (rank == 0) { if (rank == 0) {
uuid_t uuid; uuid_t uuid;
double t1, t2; double t1, t2;
INFO(VERBOSE_1, "Destorying DFS Container: %s\n", o.cont); INFO(VERBOSE_1, "Destorying DFS Container: %s\n", o->cont);
uuid_parse(o.cont, uuid); uuid_parse(o->cont, uuid);
t1 = MPI_Wtime(); t1 = MPI_Wtime();
rc = daos_cont_destroy(poh, uuid, 1, NULL); rc = daos_cont_destroy(poh, uuid, 1, NULL);
t2 = MPI_Wtime(); t2 = MPI_Wtime();
@ -499,7 +526,7 @@ DFS_Finalize()
MPI_Bcast(&rc, 1, MPI_INT, 0, MPI_COMM_WORLD); MPI_Bcast(&rc, 1, MPI_INT, 0, MPI_COMM_WORLD);
if (rc) { if (rc) {
if (rank == 0) 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); MPI_Abort(MPI_COMM_WORLD, -1);
} }
} }
@ -519,15 +546,15 @@ DFS_Finalize()
DCHECK(rc, "Failed to finalize DAOS"); DCHECK(rc, "Failed to finalize DAOS");
/** reset tunables */ /** reset tunables */
o.pool = NULL; o->pool = NULL;
o.svcl = NULL; o->svcl = NULL;
o.group = NULL; o->group = NULL;
o.cont = NULL; o->cont = NULL;
o.chunk_size = 1048576; o->chunk_size = 1048576;
o.oclass = NULL; o->oclass = NULL;
o.dir_oclass = NULL; o->dir_oclass = NULL;
o.prefix = NULL; o->prefix = NULL;
o.destroy = 0; o->destroy = 0;
objectClass = OC_SX; objectClass = OC_SX;
dir_oclass = OC_SX; dir_oclass = OC_SX;
dfs_init = false; dfs_init = false;
@ -536,17 +563,16 @@ DFS_Finalize()
/* /*
* Creat and open a file through the DFS interface. * Creat and open a file through the DFS interface.
*/ */
static void * static aiori_fd_t *
DFS_Create(char *testFileName, IOR_param_t *param) 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; char *name = NULL, *dir_name = NULL;
dfs_obj_t *obj = NULL, *parent = NULL; dfs_obj_t *obj = NULL, *parent = NULL;
mode_t mode = 0644; mode_t mode = 0664;
int fd_oflag = 0; int fd_oflag = 0;
int rc; int rc;
assert(param);
rc = parse_filename(testFileName, &name, &dir_name); rc = parse_filename(testFileName, &name, &dir_name);
DCHECK(rc, "Failed to parse path %s", testFileName); DCHECK(rc, "Failed to parse path %s", testFileName);
assert(dir_name); assert(dir_name);
@ -556,20 +582,20 @@ DFS_Create(char *testFileName, IOR_param_t *param)
if (parent == NULL) if (parent == NULL)
GERR("Failed to lookup parent dir"); GERR("Failed to lookup parent dir");
mode = S_IFREG | param->mode; mode = S_IFREG | mode;
if (param->filePerProc || rank == 0) { if (hints->filePerProc || rank == 0) {
fd_oflag |= O_CREAT | O_RDWR | O_EXCL; fd_oflag |= O_CREAT | O_RDWR | O_EXCL;
rc = dfs_open(dfs, parent, name, mode, fd_oflag, 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); DCHECK(rc, "dfs_open() of %s Failed", name);
} }
if (!param->filePerProc) { if (!hints->filePerProc) {
MPI_Barrier(MPI_COMM_WORLD); MPI_Barrier(MPI_COMM_WORLD);
if (rank != 0) { if (rank != 0) {
fd_oflag |= O_RDWR; fd_oflag |= O_RDWR;
rc = dfs_open(dfs, parent, name, mode, fd_oflag, 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); DCHECK(rc, "dfs_open() of %s Failed", name);
} }
} }
@ -579,27 +605,27 @@ DFS_Create(char *testFileName, IOR_param_t *param)
if (dir_name) if (dir_name)
free(dir_name); free(dir_name);
return ((void *)obj); return (aiori_fd_t *)(obj);
} }
/* /*
* Open a file through the DFS interface. * Open a file through the DFS interface.
*/ */
static void * static aiori_fd_t *
DFS_Open(char *testFileName, IOR_param_t *param) 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; char *name = NULL, *dir_name = NULL;
dfs_obj_t *obj = NULL, *parent = NULL; dfs_obj_t *obj = NULL, *parent = NULL;
mode_t mode; mode_t mode = 0664;
int rc;
int fd_oflag = 0; int fd_oflag = 0;
int rc;
fd_oflag |= O_RDWR; fd_oflag |= O_RDWR;
mode = S_IFREG | param->mode; mode = S_IFREG | flags;
rc = parse_filename(testFileName, &name, &dir_name); rc = parse_filename(testFileName, &name, &dir_name);
DCHECK(rc, "Failed to parse path %s", testFileName); DCHECK(rc, "Failed to parse path %s", testFileName);
assert(dir_name); assert(dir_name);
assert(name); assert(name);
@ -608,7 +634,7 @@ DFS_Open(char *testFileName, IOR_param_t *param)
GERR("Failed to lookup parent dir"); GERR("Failed to lookup parent dir");
rc = dfs_open(dfs, parent, name, mode, fd_oflag, objectClass, 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); DCHECK(rc, "dfs_open() of %s Failed", name);
if (name) if (name)
@ -616,15 +642,15 @@ DFS_Open(char *testFileName, IOR_param_t *param)
if (dir_name) if (dir_name)
free(dir_name); free(dir_name);
return ((void *)obj); return (aiori_fd_t *)(obj);
} }
/* /*
* Write or read access to file using the DFS interface. * Write or read access to file using the DFS interface.
*/ */
static IOR_offset_t static IOR_offset_t
DFS_Xfer(int access, void *file, IOR_size_t *buffer, IOR_offset_t length, DFS_Xfer(int access, aiori_fd_t *file, IOR_size_t *buffer, IOR_offset_t length,
IOR_param_t *param) IOR_offset_t off, aiori_mod_opt_t *param)
{ {
int xferRetries = 0; int xferRetries = 0;
long long remaining = (long long)length; long long remaining = (long long)length;
@ -647,20 +673,20 @@ DFS_Xfer(int access, void *file, IOR_size_t *buffer, IOR_offset_t length,
/* write/read file */ /* write/read file */
if (access == WRITE) { if (access == WRITE) {
rc = dfs_write(dfs, obj, &sgl, param->offset, NULL); rc = dfs_write(dfs, obj, &sgl, off, NULL);
if (rc) { if (rc) {
fprintf(stderr, "dfs_write() failed (%d)", rc); fprintf(stderr, "dfs_write() failed (%d)", rc);
return -1; return -1;
} }
ret = remaining; ret = remaining;
} else { } else {
rc = dfs_read(dfs, obj, &sgl, param->offset, &ret, NULL); rc = dfs_read(dfs, obj, &sgl, off, &ret, NULL);
if (rc || ret == 0) if (rc || ret == 0)
fprintf(stderr, "dfs_read() failed(%d)", rc); fprintf(stderr, "dfs_read() failed(%d)", rc);
} }
if (ret < remaining) { if (ret < remaining) {
if (param->singleXferAttempt == TRUE) if (hints->singleXferAttempt == TRUE)
exit(-1); exit(-1);
if (xferRetries > MAX_RETRY) if (xferRetries > MAX_RETRY)
ERR("too many retries -- aborting"); ERR("too many retries -- aborting");
@ -680,7 +706,7 @@ DFS_Xfer(int access, void *file, IOR_size_t *buffer, IOR_offset_t length,
* Perform fsync(). * Perform fsync().
*/ */
static void 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 */ /* no cache in DFS, so this is a no-op currently */
dfs_sync(dfs); dfs_sync(dfs);
@ -691,7 +717,7 @@ DFS_Fsync(void *fd, IOR_param_t * param)
* Perform sync() on the dfs mount. * Perform sync() on the dfs mount.
*/ */
static void static void
DFS_Sync(IOR_param_t * param) DFS_Sync(aiori_mod_opt_t * param)
{ {
/* no cache in DFS, so this is a no-op currently */ /* no cache in DFS, so this is a no-op currently */
dfs_sync(dfs); dfs_sync(dfs);
@ -702,7 +728,7 @@ DFS_Sync(IOR_param_t * param)
* Close a file through the DFS interface. * Close a file through the DFS interface.
*/ */
static void 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); dfs_release((dfs_obj_t *)fd);
} }
@ -711,7 +737,7 @@ DFS_Close(void *fd, IOR_param_t * param)
* Delete a file through the DFS interface. * Delete a file through the DFS interface.
*/ */
static void 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; char *name = NULL, *dir_name = NULL;
dfs_obj_t *parent = NULL; dfs_obj_t *parent = NULL;
@ -748,7 +774,7 @@ static char* DFS_GetVersion()
* Use DFS stat() to return aggregate file size. * Use DFS stat() to return aggregate file size.
*/ */
static IOR_offset_t 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; dfs_obj_t *obj;
daos_size_t fsize, tmpMin, tmpMax, tmpSum; daos_size_t fsize, tmpMin, tmpMax, tmpSum;
@ -766,7 +792,7 @@ DFS_GetFileSize(IOR_param_t * test, MPI_Comm comm, char *testFileName)
dfs_release(obj); dfs_release(obj);
if (test->filePerProc == TRUE) { if (hints->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&fsize, &tmpSum, 1, MPI_CHECK(MPI_Allreduce(&fsize, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, comm), MPI_LONG_LONG_INT, MPI_SUM, comm),
"cannot total data moved"); "cannot total data moved");
@ -791,13 +817,13 @@ DFS_GetFileSize(IOR_param_t * test, MPI_Comm comm, char *testFileName)
} }
static int 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; return 0;
} }
static int 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; dfs_obj_t *parent = NULL;
char *name = NULL, *dir_name = NULL; char *name = NULL, *dir_name = NULL;
@ -825,7 +851,7 @@ DFS_Mkdir(const char *path, mode_t mode, IOR_param_t * param)
} }
static int 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; dfs_obj_t *parent = NULL;
char *name = NULL, *dir_name = NULL; char *name = NULL, *dir_name = NULL;
@ -854,7 +880,7 @@ DFS_Rmdir(const char *path, IOR_param_t * param)
} }
static int 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 *obj = NULL; dfs_obj_t *obj = NULL;
mode_t fmode; mode_t fmode;
@ -871,7 +897,7 @@ DFS_Access(const char *path, int mode, IOR_param_t * param)
} }
static int 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; dfs_obj_t *parent = NULL;
char *name = NULL, *dir_name = NULL; char *name = NULL, *dir_name = NULL;

View File

@ -25,7 +25,7 @@ typedef struct {
static char * current = (char*) 1; 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)); dummy_options_t * o = malloc(sizeof(dummy_options_t));
if (init_values != NULL){ if (init_values != NULL){
memcpy(o, init_values, sizeof(dummy_options_t)); 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)); memset(o, 0, sizeof(dummy_options_t));
} }
*init_backend_options = o; *init_backend_options = (aiori_mod_opt_t*) o;
option_help h [] = { option_help h [] = {
{0, "dummy.delay-create", "Delay per create in usec", OPTION_OPTIONAL_ARGUMENT, 'l', & o->delay_creates}, {0, "dummy.delay-create", "Delay per create in usec", OPTION_OPTIONAL_ARGUMENT, 'l', & o->delay_creates},
@ -46,30 +46,38 @@ static option_help * DUMMY_options(void ** init_backend_options, void * init_val
return help; 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){ if(verbose > 4){
fprintf(out_logfile, "DUMMY create: %s = %p\n", testFileName, current); 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_creates){
if (! o->delay_rank_0_only || (o->delay_rank_0_only && rank == 0)){ 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)}; struct timespec wait = { o->delay_creates / 1000 / 1000, 1000l * (o->delay_creates % 1000000)};
nanosleep( & wait, NULL); 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){ if(verbose > 4){
fprintf(out_logfile, "DUMMY open: %s = %p\n", testFileName, current); 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){ if(verbose > 4){
fprintf(out_logfile, "DUMMY fsync %p\n", fd); fprintf(out_logfile, "DUMMY fsync %p\n", fd);
@ -77,18 +85,18 @@ static void DUMMY_Fsync(void *fd, IOR_param_t * param)
} }
static void DUMMY_Sync(IOR_param_t * param) static void DUMMY_Sync(aiori_mod_opt_t * options)
{ {
} }
static void DUMMY_Close(void *fd, IOR_param_t * param) static void DUMMY_Close(aiori_fd_t *fd, aiori_mod_opt_t * options)
{ {
if(verbose > 4){ if(verbose > 4){
fprintf(out_logfile, "DUMMY close %p\n", fd); 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){ if(verbose > 4){
fprintf(out_logfile, "DUMMY delete: %s\n", testFileName); fprintf(out_logfile, "DUMMY delete: %s\n", testFileName);
@ -100,7 +108,7 @@ static char * DUMMY_getVersion()
return "0.5"; 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){ if(verbose > 4){
fprintf(out_logfile, "DUMMY getFileSize: %s\n", testFileName); fprintf(out_logfile, "DUMMY getFileSize: %s\n", testFileName);
@ -108,11 +116,11 @@ static IOR_offset_t DUMMY_GetFileSize(IOR_param_t * test, MPI_Comm testComm, cha
return 0; 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){ if(verbose > 4){
fprintf(out_logfile, "DUMMY xfer: %p\n", file); 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_xfer){
if (! o->delay_rank_0_only || (o->delay_rank_0_only && rank == 0)){ 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)}; struct timespec wait = {o->delay_xfer / 1000 / 1000, 1000l * (o->delay_xfer % 1000000)};
@ -122,7 +130,7 @@ static IOR_offset_t DUMMY_Xfer(int access, void *file, IOR_size_t * buffer, IOR_
return length; 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_bsize = 1;
stat->f_blocks = 1; stat->f_blocks = 1;
stat->f_bfree = 1; stat->f_bfree = 1;
@ -132,26 +140,40 @@ static int DUMMY_statfs (const char * path, ior_aiori_statfs_t * stat, IOR_param
return 0; 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; 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; 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; 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; return 0;
} }
static int DUMMY_check_params(IOR_param_t * test){ static int DUMMY_check_params(aiori_mod_opt_t * options){
return 1; 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 = { ior_aiori_t dummy_aiori = {
.name = "DUMMY", .name = "DUMMY",
.name_legacy = NULL, .name_legacy = NULL,
@ -168,11 +190,10 @@ ior_aiori_t dummy_aiori = {
.rmdir = DUMMY_rmdir, .rmdir = DUMMY_rmdir,
.access = DUMMY_access, .access = DUMMY_access,
.stat = DUMMY_stat, .stat = DUMMY_stat,
.initialize = NULL, .initialize = DUMMY_init,
.finalize = NULL, .finalize = DUMMY_final,
.get_options = DUMMY_options, .get_options = DUMMY_options,
.enable_mdtest = true,
.check_params = DUMMY_check_params, .check_params = DUMMY_check_params,
.sync = DUMMY_Sync, .sync = DUMMY_Sync,
.enable_mdtest = true .enable_mdtest = true
}; };

View File

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

View File

@ -26,14 +26,15 @@
#include "utilities.h" #include "utilities.h"
/**************************** P R O T O T Y P E S *****************************/ /**************************** P R O T O T Y P E S *****************************/
static void *MMAP_Create(char *, IOR_param_t *); static aiori_fd_t *MMAP_Create(char *, int flags, aiori_mod_opt_t *);
static void *MMAP_Open(char *, IOR_param_t *); static aiori_fd_t *MMAP_Open(char *, int flags, aiori_mod_opt_t *);
static IOR_offset_t MMAP_Xfer(int, void *, IOR_size_t *, static IOR_offset_t MMAP_Xfer(int, aiori_fd_t *, IOR_size_t *,
IOR_offset_t, IOR_param_t *); IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *);
static void MMAP_Close(void *, IOR_param_t *); static void MMAP_Close(aiori_fd_t *, aiori_mod_opt_t *);
static void MMAP_Fsync(void *, IOR_param_t *); static void MMAP_Fsync(aiori_fd_t *, aiori_mod_opt_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);
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 ***************************/ /************************** D E C L A R A T I O N S ***************************/
ior_aiori_t mmap_aiori = { ior_aiori_t mmap_aiori = {
@ -43,10 +44,12 @@ ior_aiori_t mmap_aiori = {
.xfer = MMAP_Xfer, .xfer = MMAP_Xfer,
.close = MMAP_Close, .close = MMAP_Close,
.delete = POSIX_Delete, .delete = POSIX_Delete,
.xfer_hints = MMAP_xfer_hints,
.get_version = aiori_get_version, .get_version = aiori_get_version,
.fsync = MMAP_Fsync, .fsync = MMAP_Fsync,
.get_file_size = POSIX_GetFileSize, .get_file_size = POSIX_GetFileSize,
.get_options = MMAP_options, .get_options = MMAP_options,
.check_params = MMAP_check_params
}; };
/***************************** F U N C T I O N S ******************************/ /***************************** F U N C T I O N S ******************************/
@ -58,7 +61,7 @@ typedef struct{
int madv_pattern; int madv_pattern;
} mmap_options_t; } 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)); mmap_options_t * o = malloc(sizeof(mmap_options_t));
if (init_values != NULL){ 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)); memset(o, 0, sizeof(mmap_options_t));
} }
*init_backend_options = o; *init_backend_options = (aiori_mod_opt_t*) o;
option_help h [] = { option_help h [] = {
{0, "mmap.madv_dont_need", "Use advise don't need", OPTION_FLAG, 'd', & o->madv_dont_need}, {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; 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; 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; 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, o->mmap_ptr = mmap(NULL, size, flags, MAP_SHARED,
*file, 0); *file, 0);
if (o->mmap_ptr == MAP_FAILED) if (o->mmap_ptr == MAP_FAILED)
ERR("mmap() failed"); ERR("mmap() failed");
if (param->randomOffset) if (hints->randomOffset)
flags = POSIX_MADV_RANDOM; flags = POSIX_MADV_RANDOM;
else else
flags = POSIX_MADV_SEQUENTIAL; flags = POSIX_MADV_SEQUENTIAL;
if(o->madv_pattern){ if(o->madv_pattern){
if (posix_madvise(o->mmap_ptr, size, flags) != 0) if (posix_madvise(o->mmap_ptr, size, flags) != 0)
ERR("madvise() failed"); 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. * 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; int *fd;
fd = POSIX_Create(testFileName, param); fd = (int*) POSIX_Create(testFileName, flags, param);
if (ftruncate(*fd, param->expectedAggFileSize) != 0) if (ftruncate(*fd, hints->expectedAggFileSize) != 0)
ERR("ftruncate() failed"); ERR("ftruncate() failed");
ior_mmap_file(fd, param); ior_mmap_file(fd, flags, param);
return ((void *)fd); return ((aiori_fd_t *)fd);
} }
/* /*
* Open a file through the POSIX interface and setup mmap. * 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; int *fd;
fd = (int*) POSIX_Open(testFileName, flags, param);
fd = POSIX_Open(testFileName, param); ior_mmap_file(fd, flags, param);
ior_mmap_file(fd, param); return ((aiori_fd_t *)fd);
return ((void *)fd);
} }
/* /*
* Write or read access to file using mmap * Write or read access to file using mmap
*/ */
static IOR_offset_t MMAP_Xfer(int access, void *file, IOR_size_t * buffer, static IOR_offset_t MMAP_Xfer(int access, aiori_fd_t *file, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param) 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) { if (access == WRITE) {
memcpy(o->mmap_ptr + param->offset, buffer, length); memcpy(o->mmap_ptr + offset, buffer, length);
} else { } else {
memcpy(buffer, o->mmap_ptr + param->offset, length); memcpy(buffer, o->mmap_ptr + offset, length);
} }
if (param->fsyncPerWrite == TRUE) { if (hints->fsyncPerWrite == TRUE) {
if (msync(o->mmap_ptr + param->offset, length, MS_SYNC) != 0) if (msync(o->mmap_ptr + offset, length, MS_SYNC) != 0)
ERR("msync() failed"); ERR("msync() failed");
if (posix_madvise(o->mmap_ptr + param->offset, length, if (posix_madvise(o->mmap_ptr + offset, length,
POSIX_MADV_DONTNEED) != 0) POSIX_MADV_DONTNEED) != 0)
ERR("madvise() failed"); ERR("madvise() failed");
} }
@ -163,20 +178,20 @@ static IOR_offset_t MMAP_Xfer(int access, void *file, IOR_size_t * buffer,
/* /*
* Perform msync(). * 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; mmap_options_t *o = (mmap_options_t*) param;
if (msync(o->mmap_ptr, param->expectedAggFileSize, MS_SYNC) != 0) if (msync(o->mmap_ptr, hints->expectedAggFileSize, MS_SYNC) != 0)
EWARN("msync() failed"); EWARN("msync() failed");
} }
/* /*
* Close a file through the POSIX interface, after tear down the mmap. * 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; mmap_options_t *o = (mmap_options_t*) param;
if (munmap(o->mmap_ptr, param->expectedAggFileSize) != 0) if (munmap(o->mmap_ptr, hints->expectedAggFileSize) != 0)
ERR("munmap failed"); ERR("munmap failed");
o->mmap_ptr = NULL; o->mmap_ptr = NULL;
POSIX_Close(fd, param); POSIX_Close(fd, param);

View File

@ -31,23 +31,65 @@
/**************************** P R O T O T Y P E S *****************************/ /**************************** 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 aiori_fd_t *MPIIO_Create(char *, int iorflags, aiori_mod_opt_t *);
static void *MPIIO_Open(char *, IOR_param_t *); static aiori_fd_t *MPIIO_Open(char *, int flags, aiori_mod_opt_t *);
static IOR_offset_t MPIIO_Xfer(int, void *, IOR_size_t *, static IOR_offset_t MPIIO_Xfer(int, aiori_fd_t *, IOR_size_t *,
IOR_offset_t, IOR_param_t *); IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *);
static void MPIIO_Close(void *, IOR_param_t *); static void MPIIO_Close(aiori_fd_t *, aiori_mod_opt_t *);
static char* MPIIO_GetVersion(); 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 ***************************/ /************************** 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 = { ior_aiori_t mpiio_aiori = {
.name = "MPIIO", .name = "MPIIO",
.name_legacy = NULL, .name_legacy = NULL,
.create = MPIIO_Create, .create = MPIIO_Create,
.get_options = MPIIO_options,
.xfer_hints = MPIIO_xfer_hints,
.open = MPIIO_Open, .open = MPIIO_Open,
.xfer = MPIIO_Xfer, .xfer = MPIIO_Xfer,
.close = MPIIO_Close, .close = MPIIO_Close,
@ -60,16 +102,46 @@ ior_aiori_t mpiio_aiori = {
.rmdir = aiori_posix_rmdir, .rmdir = aiori_posix_rmdir,
.access = MPIIO_Access, .access = MPIIO_Access,
.stat = aiori_posix_stat, .stat = aiori_posix_stat,
.check_params = MPIIO_check_params
}; };
/***************************** F U N C T I O N S ******************************/ /***************************** 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. * 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; return MPI_SUCCESS;
} }
MPI_File fd; 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. * 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 MPIIO_Open(testFileName, iorflags, module_options);
return 0;
}
return MPIIO_Open(testFileName, param);
} }
/* /*
* Open a file through the MPIIO interface. Setup file view. * 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, int fd_mode = (int)0,
offsetFactor, offsetFactor,
tasksPerFile, tasksPerFile,
transfersPerBlock = param->blockSize / param->transferSize; transfersPerBlock = hints->blockSize / hints->transferSize;
struct fileTypeStruct { struct fileTypeStruct {
int globalSizes[2], localSizes[2], startIndices[2]; int globalSizes[2], localSizes[2], startIndices[2];
} fileTypeStruct; } fileTypeStruct;
MPI_File *fd;
mpiio_fd_t * mfd = malloc(sizeof(mpiio_fd_t));
memset(mfd, 0, sizeof(mpiio_fd_t));
MPI_Comm comm; MPI_Comm comm;
MPI_Info mpiHints = MPI_INFO_NULL; 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 */ /* set IOR file flags to MPIIO flags */
/* -- file open flags -- */ /* -- file open flags -- */
if (param->openFlags & IOR_RDONLY) { if (flags & IOR_RDONLY) {
fd_mode |= MPI_MODE_RDONLY; fd_mode |= MPI_MODE_RDONLY;
} }
if (param->openFlags & IOR_WRONLY) { if (flags & IOR_WRONLY) {
fd_mode |= MPI_MODE_WRONLY; fd_mode |= MPI_MODE_WRONLY;
} }
if (param->openFlags & IOR_RDWR) { if (flags & IOR_RDWR) {
fd_mode |= MPI_MODE_RDWR; fd_mode |= MPI_MODE_RDWR;
} }
if (param->openFlags & IOR_APPEND) { if (flags & IOR_APPEND) {
fd_mode |= MPI_MODE_APPEND; fd_mode |= MPI_MODE_APPEND;
} }
if (param->openFlags & IOR_CREAT) { if (flags & IOR_CREAT) {
fd_mode |= MPI_MODE_CREATE; fd_mode |= MPI_MODE_CREATE;
} }
if (param->openFlags & IOR_EXCL) { if (flags & IOR_EXCL) {
fd_mode |= MPI_MODE_EXCL; fd_mode |= MPI_MODE_EXCL;
} }
if (param->openFlags & IOR_TRUNC) { if (flags & IOR_DIRECT) {
fprintf(stdout, "File truncation not implemented in MPIIO\n");
}
if (param->openFlags & IOR_DIRECT) {
fprintf(stdout, "O_DIRECT not implemented in MPIIO\n"); 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; fd_mode |= MPI_MODE_UNIQUE_OPEN;
if (param->filePerProc) { if (hints->filePerProc) {
comm = MPI_COMM_SELF; comm = MPI_COMM_SELF;
} else { } else {
comm = testComm; comm = testComm;
@ -181,16 +244,19 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
ShowHints(&mpiHints); ShowHints(&mpiHints);
fprintf(stdout, "}\n"); fprintf(stdout, "}\n");
} }
if(! param->dryRun){ if(! hints->dryRun){
MPI_CHECKF(MPI_File_open(comm, testFileName, fd_mode, mpiHints, fd), MPI_CHECKF(MPI_File_open(comm, testFileName, fd_mode, mpiHints, & mfd->fd),
"cannot open file: %s", testFileName); "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 */ /* 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) if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "MPI_Info_free failed"); 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"); "cannot get file info");
fprintf(stdout, "\nhints returned from opened file {\n"); fprintf(stdout, "\nhints returned from opened file {\n");
ShowHints(&mpiHints); ShowHints(&mpiHints);
@ -198,29 +264,29 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
} }
/* preallocate space for file */ /* preallocate space for file */
if (param->preallocate && param->open == WRITE && ! param->dryRun) { if (param->preallocate && flags & IOR_CREAT && ! hints->dryRun) {
MPI_CHECK(MPI_File_preallocate(*fd, MPI_CHECK(MPI_File_preallocate(mfd->fd,
(MPI_Offset) (param->segmentCount (MPI_Offset) (hints->segmentCount
* *
param->blockSize * hints->blockSize *
param->numTasks)), hints->numTasks)),
"cannot preallocate file"); "cannot preallocate file");
} }
/* create file view */ /* create file view */
if (param->useFileView) { if (param->useFileView) {
/* create contiguous transfer datatype */ /* create contiguous transfer datatype */
MPI_CHECK(MPI_Type_contiguous MPI_CHECK(MPI_Type_contiguous
(param->transferSize / sizeof(IOR_size_t), (hints->transferSize / sizeof(IOR_size_t),
MPI_LONG_LONG_INT, &param->transferType), MPI_LONG_LONG_INT, & mfd->transferType),
"cannot create contiguous datatype"); "cannot create contiguous datatype");
MPI_CHECK(MPI_Type_commit(&param->transferType), MPI_CHECK(MPI_Type_commit(& mfd->transferType),
"cannot commit datatype"); "cannot commit datatype");
if (param->filePerProc) { if (hints->filePerProc) {
offsetFactor = 0; offsetFactor = 0;
tasksPerFile = 1; tasksPerFile = 1;
} else { } else {
offsetFactor = (rank + rankOffset) % param->numTasks; offsetFactor = (rank + rankOffset) % hints->numTasks;
tasksPerFile = param->numTasks; tasksPerFile = hints->numTasks;
} }
/* /*
@ -239,37 +305,38 @@ static void *MPIIO_Open(char *testFileName, IOR_param_t * param)
(2, fileTypeStruct.globalSizes, (2, fileTypeStruct.globalSizes,
fileTypeStruct.localSizes, fileTypeStruct.localSizes,
fileTypeStruct.startIndices, MPI_ORDER_C, fileTypeStruct.startIndices, MPI_ORDER_C,
param->transferType, &param->fileType), mfd->transferType, & mfd->fileType),
"cannot create subarray"); "cannot create subarray");
MPI_CHECK(MPI_Type_commit(&param->fileType), MPI_CHECK(MPI_Type_commit(& mfd->fileType),
"cannot commit datatype"); "cannot commit datatype");
if(! param->dryRun){ if(! hints->dryRun){
MPI_CHECK(MPI_File_set_view(*fd, (MPI_Offset) 0, MPI_CHECK(MPI_File_set_view(mfd->fd, (MPI_Offset) 0,
param->transferType, mfd->transferType,
param->fileType, "native", mfd->fileType, "native",
(MPI_Info) MPI_INFO_NULL), (MPI_Info) MPI_INFO_NULL),
"cannot set file view"); "cannot set file view");
} }
} }
if (mpiHints != MPI_INFO_NULL) if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "MPI_Info_free failed"); 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. * Write or read access to file using the MPIIO interface.
*/ */
static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer, static IOR_offset_t MPIIO_Xfer(int access, aiori_fd_t * fdp, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param) 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 *) /* NOTE: The second arg is (void *) for reads, and (const void *)
for writes. Therefore, one of the two sets of assignments below for writes. Therefore, one of the two sets of assignments below
will get "assignment from incompatible pointer-type" warnings, will get "assignment from incompatible pointer-type" warnings,
if we only use this one set of signatures. */ if we only use this one set of signatures. */
mpiio_options_t * param = (mpiio_options_t*) module_options;
if(param->dryRun) if(hints->dryRun)
return length; return length;
mpiio_fd_t * mfd = (mpiio_fd_t*) fdp;
int (MPIAPI * Access) (MPI_File, void *, int, int (MPIAPI * Access) (MPI_File, void *, int,
MPI_Datatype, MPI_Status *); 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) { if (param->useFileView) {
/* find offset in file */ /* find offset in file */
if (SeekOffset(*(MPI_File *) fd, param->offset, param) < if (SeekOffset(mfd->fd, offset, module_options) <
0) { 0) {
/* if unsuccessful */ /* if unsuccessful */
length = -1; 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' * e.g., 'IOR -s 2 -b 32K -t 32K -a MPIIO -S'
*/ */
if (param->useStridedDatatype) { if (param->useStridedDatatype) {
length = param->segmentCount; length = hints->segmentCount;
} else { } else {
length = 1; length = 1;
} }
if (param->collective) { if (hints->collective) {
/* individual, collective call */ /* individual, collective call */
MPI_CHECK(Access_all MPI_CHECK(Access_all
(*(MPI_File *) fd, buffer, length, (mfd->fd, buffer, length,
param->transferType, &status), mfd->transferType, &status),
"cannot access collective"); "cannot access collective");
} else { } else {
/* individual, noncollective call */ /* individual, noncollective call */
MPI_CHECK(Access MPI_CHECK(Access
(*(MPI_File *) fd, buffer, length, (mfd->fd, buffer, length,
param->transferType, &status), mfd->transferType, &status),
"cannot access noncollective"); "cannot access noncollective");
} }
length *= param->transferSize; /* for return value in bytes */ length *= hints->transferSize; /* for return value in bytes */
} }
} else { } else {
/* /*
@ -358,7 +425,7 @@ static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer,
if (param->useSharedFilePointer) { if (param->useSharedFilePointer) {
/* find offset in file */ /* find offset in file */
if (SeekOffset if (SeekOffset
(*(MPI_File *) fd, param->offset, param) < 0) { (mfd->fd, offset, module_options) < 0) {
/* if unsuccessful */ /* if unsuccessful */
length = -1; length = -1;
} else { } else {
@ -374,63 +441,64 @@ static IOR_offset_t MPIIO_Xfer(int access, void *fd, IOR_size_t * buffer,
"useSharedFilePointer not implemented\n"); "useSharedFilePointer not implemented\n");
} }
} else { } else {
if (param->collective) { if (hints->collective) {
/* explicit, collective call */ /* explicit, collective call */
MPI_CHECK(Access_at_all MPI_CHECK(Access_at_all
(*(MPI_File *) fd, param->offset, (mfd->fd, offset,
buffer, length, MPI_BYTE, &status), buffer, length, MPI_BYTE, &status),
"cannot access explicit, collective"); "cannot access explicit, collective");
} else { } else {
/* explicit, noncollective call */ /* explicit, noncollective call */
MPI_CHECK(Access_at MPI_CHECK(Access_at
(*(MPI_File *) fd, param->offset, (mfd->fd, offset,
buffer, length, MPI_BYTE, &status), buffer, length, MPI_BYTE, &status),
"cannot access explicit, noncollective"); "cannot access explicit, noncollective");
} }
} }
} }
if((access == WRITE) && (param->fsyncPerWrite == TRUE))
MPIIO_Fsync(fd, param);
return (length); return (length);
} }
/* /*
* Perform fsync(). * 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; 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"); EWARN("fsync() failed");
} }
/* /*
* Close a file through the MPIIO interface. * 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){ mpiio_options_t * param = (mpiio_options_t*) module_options;
MPI_CHECK(MPI_File_close((MPI_File *) fd), "cannot close file"); 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 * need to free the datatype, so done in the close process
*/ */
MPI_CHECK(MPI_Type_free(&param->fileType), MPI_CHECK(MPI_Type_free(& mfd->fileType), "cannot free MPI file datatype");
"cannot free MPI file datatype"); MPI_CHECK(MPI_Type_free(& mfd->transferType), "cannot free MPI transfer datatype");
MPI_CHECK(MPI_Type_free(&param->transferType),
"cannot free MPI transfer datatype");
} }
free(fd); free(fdp);
} }
/* /*
* Delete a file through the MPIIO interface. * 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; return;
MPI_CHECKF(MPI_File_delete(testFileName, (MPI_Info) MPI_INFO_NULL), MPI_CHECKF(MPI_File_delete(testFileName, (MPI_Info) MPI_INFO_NULL),
"cannot delete file: %s", testFileName); "cannot delete file: %s", testFileName);
@ -452,36 +520,37 @@ static char* MPIIO_GetVersion()
* Seek to offset in file using the MPIIO interface. * Seek to offset in file using the MPIIO interface.
*/ */
static IOR_offset_t SeekOffset(MPI_File fd, IOR_offset_t offset, 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; int offsetFactor, tasksPerFile;
IOR_offset_t tempOffset; IOR_offset_t tempOffset;
tempOffset = offset; tempOffset = offset;
if (param->filePerProc) { if (hints->filePerProc) {
offsetFactor = 0; offsetFactor = 0;
tasksPerFile = 1; tasksPerFile = 1;
} else { } else {
offsetFactor = (rank + rankOffset) % param->numTasks; offsetFactor = (rank + rankOffset) % hints->numTasks;
tasksPerFile = param->numTasks; tasksPerFile = hints->numTasks;
} }
if (param->useFileView) { if (param->useFileView) {
/* recall that offsets in a file view are /* recall that offsets in a file view are
counted in units of transfer size */ counted in units of transfer size */
if (param->filePerProc) { if (hints->filePerProc) {
tempOffset = tempOffset / param->transferSize; tempOffset = tempOffset / hints->transferSize;
} else { } else {
/* /*
* this formula finds a file view offset for a task * this formula finds a file view offset for a task
* from an absolute offset * from an absolute offset
*/ */
tempOffset = ((param->blockSize / param->transferSize) tempOffset = ((hints->blockSize / hints->transferSize)
* (tempOffset / * (tempOffset /
(param->blockSize * tasksPerFile))) (hints->blockSize * tasksPerFile)))
+ (((tempOffset % (param->blockSize * tasksPerFile)) + (((tempOffset % (hints->blockSize * tasksPerFile))
- (offsetFactor * param->blockSize)) - (offsetFactor * hints->blockSize))
/ param->transferSize); / hints->transferSize);
} }
} }
MPI_CHECK(MPI_File_seek(fd, tempOffset, MPI_SEEK_SET), 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. * Use MPI_File_get_size() to return aggregate file size.
* NOTE: This function is used by the HDF5 and NCMPI backends. * 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) char *testFileName)
{ {
if(test->dryRun) mpiio_options_t * test = (mpiio_options_t*) module_options;
if(hints->dryRun)
return 0; return 0;
IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum; IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum;
MPI_File fd; MPI_File fd;
MPI_Comm comm; MPI_Comm comm;
MPI_Info mpiHints = MPI_INFO_NULL; MPI_Info mpiHints = MPI_INFO_NULL;
if (test->filePerProc == TRUE) { if (hints->filePerProc == TRUE) {
comm = MPI_COMM_SELF; comm = MPI_COMM_SELF;
} else { } else {
comm = testComm; comm = testComm;
@ -519,7 +589,7 @@ IOR_offset_t MPIIO_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
if (mpiHints != MPI_INFO_NULL) if (mpiHints != MPI_INFO_NULL)
MPI_CHECK(MPI_Info_free(&mpiHints), "MPI_Info_free failed"); 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_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm), MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved"); "cannot total data moved");

View File

@ -68,31 +68,67 @@
#endif #endif
/**************************** P R O T O T Y P E S *****************************/ /**************************** P R O T O T Y P E S *****************************/
static IOR_offset_t POSIX_Xfer(int, void *, IOR_size_t *, static IOR_offset_t POSIX_Xfer(int, aiori_fd_t *, IOR_size_t *,
IOR_offset_t, IOR_param_t *); IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *);
static void POSIX_Fsync(void *, IOR_param_t *); static void POSIX_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
static void POSIX_Sync(IOR_param_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 *****************************/ /************************** O P T I O N S *****************************/
typedef struct{ typedef struct{
/* in case of a change, please update depending MMAP module too */ /* in case of a change, please update depending MMAP module too */
int direct_io; 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; } 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)); posix_options_t * o = malloc(sizeof(posix_options_t));
if (init_values != NULL){ if (init_values != NULL){
memcpy(o, init_values, sizeof(posix_options_t)); memcpy(o, init_values, sizeof(posix_options_t));
}else{ }else{
memset(o, 0, sizeof(posix_options_t));
o->direct_io = 0; 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 [] = { option_help h [] = {
{0, "posix.odirect", "Direct I/O Mode", OPTION_FLAG, 'd', & o->direct_io}, {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 LAST_OPTION
}; };
option_help * help = malloc(sizeof(h)); option_help * help = malloc(sizeof(h));
@ -113,6 +149,7 @@ ior_aiori_t posix_aiori = {
.xfer = POSIX_Xfer, .xfer = POSIX_Xfer,
.close = POSIX_Close, .close = POSIX_Close,
.delete = POSIX_Delete, .delete = POSIX_Delete,
.xfer_hints = aiori_posix_xfer_hints,
.get_version = aiori_get_version, .get_version = aiori_get_version,
.fsync = POSIX_Fsync, .fsync = POSIX_Fsync,
.get_file_size = POSIX_GetFileSize, .get_file_size = POSIX_GetFileSize,
@ -123,11 +160,26 @@ ior_aiori_t posix_aiori = {
.stat = aiori_posix_stat, .stat = aiori_posix_stat,
.get_options = POSIX_options, .get_options = POSIX_options,
.enable_mdtest = true, .enable_mdtest = true,
.sync = POSIX_Sync .sync = POSIX_Sync,
.check_params = POSIX_check_params
}; };
/***************************** F U N C T I O N S ******************************/ /***************************** 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 #ifdef HAVE_GPFS_FCNTL_H
void gpfs_free_all_locks(int fd) 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); 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; int rc;
struct { struct {
@ -165,7 +217,7 @@ 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.structLen = sizeof(take_locks.access);
take_locks.access.structType = GPFS_ACCESS_RANGE; 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.length = length;
take_locks.access.isWrite = (access == WRITE); take_locks.access.isWrite = (access == WRITE);
@ -175,7 +227,7 @@ void gpfs_access_start(int fd, IOR_offset_t length, IOR_param_t *param, int acce
} }
} }
void gpfs_access_end(int fd, IOR_offset_t length, IOR_param_t *param, int access) void gpfs_access_end(int fd, IOR_offset_t length, int access)
{ {
int rc; int rc;
struct { struct {
@ -190,7 +242,7 @@ 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.structLen = sizeof(free_locks.free);
free_locks.free.structType = GPFS_FREE_RANGE; free_locks.free.structType = GPFS_FREE_RANGE;
free_locks.free.start = param->offset; free_locks.free.start = hints->offset;
free_locks.free.length = length; free_locks.free.length = length;
rc = gpfs_fcntl(fd, &free_locks); rc = gpfs_fcntl(fd, &free_locks);
@ -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. * 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 fd_oflag = O_BINARY;
int mode = 0664; int mode = 0664;
@ -327,13 +379,13 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
fd = (int *)malloc(sizeof(int)); fd = (int *)malloc(sizeof(int));
if (fd == NULL) if (fd == NULL)
ERR("Unable to malloc file descriptor"); 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){ if (o->direct_io == TRUE){
set_o_direct_flag(&fd_oflag); set_o_direct_flag(&fd_oflag);
} }
if(param->dryRun) if(hints->dryRun)
return 0; return (aiori_fd_t*) 0;
#ifdef HAVE_LUSTRE_LUSTRE_USER_H #ifdef HAVE_LUSTRE_LUSTRE_USER_H
/* Add a #define for FASYNC if not available, as it forms part of /* 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 #ifndef FASYNC
#define FASYNC 00020000 /* fcntl, for BSD compatibility */ #define FASYNC 00020000 /* fcntl, for BSD compatibility */
#endif #endif
if (o->lustre_set_striping) {
if (param->lustre_set_striping) {
/* In the single-shared-file case, task 0 has to creat the /* In the single-shared-file case, task 0 has to creat the
file with the Lustre striping options before any other processes file with the Lustre striping options before any other processes
open the file */ open the file */
if (!param->filePerProc && rank != 0) { if (!hints->filePerProc && rank != 0) {
MPI_CHECK(MPI_Barrier(testComm), "barrier error"); MPI_CHECK(MPI_Barrier(testComm), "barrier error");
fd_oflag |= O_RDWR; fd_oflag |= O_RDWR;
*fd = open64(testFileName, fd_oflag, mode); *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 */ /* Setup Lustre IOCTL striping pattern structure */
opts.lmm_magic = LOV_USER_MAGIC; opts.lmm_magic = LOV_USER_MAGIC;
opts.lmm_stripe_size = param->lustre_stripe_size; opts.lmm_stripe_size = o->lustre_stripe_size;
opts.lmm_stripe_offset = param->lustre_start_ost; opts.lmm_stripe_offset = o->lustre_start_ost;
opts.lmm_stripe_count = param->lustre_stripe_count; opts.lmm_stripe_count = o->lustre_stripe_count;
/* File needs to be opened O_EXCL because we cannot set /* File needs to be opened O_EXCL because we cannot set
* Lustre striping information on a pre-existing file.*/ * 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_CHECK(MPI_Abort(MPI_COMM_WORLD, -1),
"MPI_Abort() error"); "MPI_Abort() error");
} }
if (!param->filePerProc) if (!hints->filePerProc)
MPI_CHECK(MPI_Barrier(testComm), MPI_CHECK(MPI_Barrier(testComm),
"barrier error"); "barrier error");
} }
@ -393,12 +444,12 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
fd_oflag |= O_CREAT | O_RDWR; fd_oflag |= O_CREAT | O_RDWR;
#ifdef HAVE_BEEGFS_BEEGFS_H #ifdef HAVE_BEEGFS_BEEGFS_H
if (beegfs_isOptionSet(param->beegfs_chunkSize) if (beegfs_isOptionSet(o->beegfs_chunkSize)
|| beegfs_isOptionSet(param->beegfs_numTargets)) { || beegfs_isOptionSet(o->beegfs_numTargets)) {
bool result = beegfs_createFilePath(testFileName, bool result = beegfs_createFilePath(testFileName,
mode, mode,
param->beegfs_numTargets, o->beegfs_numTargets,
param->beegfs_chunkSize); o->beegfs_chunkSize);
if (result) { if (result) {
fd_oflag &= ~O_CREAT; fd_oflag &= ~O_CREAT;
} else { } else {
@ -415,7 +466,7 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
#ifdef HAVE_LUSTRE_LUSTRE_USER_H #ifdef HAVE_LUSTRE_LUSTRE_USER_H
} }
if (param->lustre_ignore_locks) { if (o->lustre_ignore_locks) {
int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK; int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK;
if (ioctl(*fd, LL_IOC_SETFLAGS, &lustre_ioctl_flags) == -1) if (ioctl(*fd, LL_IOC_SETFLAGS, &lustre_ioctl_flags) == -1)
ERRF("ioctl(%d, LL_IOC_SETFLAGS, ...) failed", *fd); ERRF("ioctl(%d, LL_IOC_SETFLAGS, ...) failed", *fd);
@ -426,11 +477,11 @@ void *POSIX_Create(char *testFileName, IOR_param_t * param)
/* in the single shared file case, immediately release all locks, with /* in the single shared file case, immediately release all locks, with
* the intent that we can avoid some byte range lock revocation: * the intent that we can avoid some byte range lock revocation:
* everyone will be writing/reading from individual regions */ * everyone will be writing/reading from individual regions */
if (param->gpfs_release_token ) { if (o->gpfs_release_token ) {
gpfs_free_all_locks(*fd); gpfs_free_all_locks(*fd);
} }
#endif #endif
return ((void *)fd); return (aiori_fd_t*) fd;
} }
/* /*
@ -450,7 +501,7 @@ int POSIX_Mknod(char *testFileName)
/* /*
* Open a file through the POSIX interface. * 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_oflag = O_BINARY;
int *fd; int *fd;
@ -459,21 +510,21 @@ void *POSIX_Open(char *testFileName, IOR_param_t * param)
if (fd == NULL) if (fd == NULL)
ERR("Unable to malloc file descriptor"); 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) if (o->direct_io == TRUE)
set_o_direct_flag(&fd_oflag); set_o_direct_flag(&fd_oflag);
fd_oflag |= O_RDWR; fd_oflag |= O_RDWR;
if(param->dryRun) if(hints->dryRun)
return 0; return (aiori_fd_t*) 0;
*fd = open64(testFileName, fd_oflag); *fd = open64(testFileName, fd_oflag);
if (*fd < 0) if (*fd < 0)
ERRF("open64(\"%s\", %d) failed", testFileName, fd_oflag); ERRF("open64(\"%s\", %d) failed", testFileName, fd_oflag);
#ifdef HAVE_LUSTRE_LUSTRE_USER_H #ifdef HAVE_LUSTRE_LUSTRE_USER_H
if (param->lustre_ignore_locks) { if (o->lustre_ignore_locks) {
int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK; int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK;
if (verbose >= VERBOSE_1) { if (verbose >= VERBOSE_1) {
fprintf(stdout, fprintf(stdout,
@ -485,40 +536,41 @@ void *POSIX_Open(char *testFileName, IOR_param_t * param)
#endif /* HAVE_LUSTRE_LUSTRE_USER_H */ #endif /* HAVE_LUSTRE_LUSTRE_USER_H */
#ifdef HAVE_GPFS_FCNTL_H #ifdef HAVE_GPFS_FCNTL_H
if(param->gpfs_release_token) { if(o->gpfs_release_token) {
gpfs_free_all_locks(*fd); gpfs_free_all_locks(*fd);
} }
#endif #endif
return ((void *)fd); return (aiori_fd_t*) fd;
} }
/* /*
* Write or read access to file using the POSIX interface. * Write or read access to file using the POSIX interface.
*/ */
static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer, static IOR_offset_t POSIX_Xfer(int access, aiori_fd_t *file, IOR_size_t * buffer,
IOR_offset_t length, IOR_param_t * param) IOR_offset_t length, IOR_offset_t offset, aiori_mod_opt_t * param)
{ {
int xferRetries = 0; int xferRetries = 0;
long long remaining = (long long)length; long long remaining = (long long)length;
char *ptr = (char *)buffer; char *ptr = (char *)buffer;
long long rc; long long rc;
int fd; int fd;
posix_options_t * o = (posix_options_t*) param;
if(param->dryRun) if(hints->dryRun)
return length; return length;
fd = *(int *)file; fd = *(int *)file;
#ifdef HAVE_GPFS_FCNTL_H #ifdef HAVE_GPFS_FCNTL_H
if (param->gpfs_hint_access) { if (o->gpfs_hint_access) {
gpfs_access_start(fd, length, param, access); gpfs_access_start(fd, length, access);
} }
#endif #endif
/* seek to offset */ /* seek to offset */
if (lseek64(fd, param->offset, SEEK_SET) == -1) if (lseek64(fd, offset, SEEK_SET) == -1)
ERRF("lseek64(%d, %lld, SEEK_SET) failed", fd, param->offset); ERRF("lseek64(%d, %lld, SEEK_SET) failed", fd, offset);
while (remaining > 0) { while (remaining > 0) {
/* write/read file */ /* write/read file */
@ -527,20 +579,21 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
fprintf(stdout, fprintf(stdout,
"task %d writing to offset %lld\n", "task %d writing to offset %lld\n",
rank, rank,
param->offset + length - remaining); offset + length - remaining);
} }
rc = write(fd, ptr, remaining); rc = write(fd, ptr, remaining);
if (rc == -1) if (rc == -1)
ERRF("write(%d, %p, %lld) failed", ERRF("write(%d, %p, %lld) failed",
fd, (void*)ptr, remaining); fd, (void*)ptr, remaining);
if (param->fsyncPerWrite == TRUE) if (hints->fsyncPerWrite == TRUE){
POSIX_Fsync(&fd, param); POSIX_Fsync((aiori_fd_t*) &fd, param);
}
} else { /* READ or CHECK */ } else { /* READ or CHECK */
if (verbose >= VERBOSE_4) { if (verbose >= VERBOSE_4) {
fprintf(stdout, fprintf(stdout,
"task %d reading from offset %lld\n", "task %d reading from offset %lld\n",
rank, rank,
param->offset + length - remaining); offset + length - remaining);
} }
rc = read(fd, ptr, remaining); rc = read(fd, ptr, remaining);
if (rc == 0) if (rc == 0)
@ -556,8 +609,8 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
rank, rank,
access == WRITE ? "write()" : "read()", access == WRITE ? "write()" : "read()",
rc, remaining, rc, remaining,
param->offset + length - remaining); offset + length - remaining);
if (param->singleXferAttempt == TRUE) if (hints->singleXferAttempt == TRUE)
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1), MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1),
"barrier error"); "barrier error");
if (xferRetries > MAX_RETRY) if (xferRetries > MAX_RETRY)
@ -570,7 +623,7 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
xferRetries++; xferRetries++;
} }
#ifdef HAVE_GPFS_FCNTL_H #ifdef HAVE_GPFS_FCNTL_H
if (param->gpfs_hint_access) { if (o->gpfs_hint_access) {
gpfs_access_end(fd, length, param, access); gpfs_access_end(fd, length, param, access);
} }
#endif #endif
@ -580,14 +633,14 @@ static IOR_offset_t POSIX_Xfer(int access, void *file, IOR_size_t * buffer,
/* /*
* Perform fsync(). * 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) if (fsync(*(int *)fd) != 0)
EWARNF("fsync(%d) failed", *(int *)fd); 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"); int ret = system("sync");
if (ret != 0){ if (ret != 0){
@ -599,9 +652,9 @@ static void POSIX_Sync(IOR_param_t * param)
/* /*
* Close a file through the POSIX interface. * 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; return;
if (close(*(int *)fd) != 0) if (close(*(int *)fd) != 0)
ERRF("close(%d) failed", *(int *)fd); ERRF("close(%d) failed", *(int *)fd);
@ -611,9 +664,9 @@ void POSIX_Close(void *fd, IOR_param_t * param)
/* /*
* Delete a file through the POSIX interface. * 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; return;
if (unlink(testFileName) != 0){ if (unlink(testFileName) != 0){
EWARNF("[RANK %03d]: unlink() of file \"%s\" failed\n", EWARNF("[RANK %03d]: unlink() of file \"%s\" failed\n",
@ -624,10 +677,10 @@ void POSIX_Delete(char *testFileName, IOR_param_t * param)
/* /*
* Use POSIX stat() to return aggregate file size. * 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) char *testFileName)
{ {
if(test->dryRun) if(hints->dryRun)
return 0; return 0;
struct stat stat_buf; struct stat stat_buf;
IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum; IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum;
@ -637,7 +690,7 @@ IOR_offset_t POSIX_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
} }
aggFileSizeFromStat = stat_buf.st_size; aggFileSizeFromStat = stat_buf.st_size;
if (test->filePerProc == TRUE) { if (hints->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1, MPI_CHECK(MPI_Allreduce(&aggFileSizeFromStat, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm), MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved"); "cannot total data moved");

View File

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

View File

@ -152,47 +152,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 * This function provides a AIORI statfs for POSIX-compliant filesystems. It
* uses statvfs is available and falls back on statfs. * 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) #if defined(HAVE_STATVFS)
struct statvfs statfs_buf; struct statvfs statfs_buf;
ret = statvfs (path, &statfs_buf); ret = statvfs (fileName, &statfs_buf);
#else #else
struct statfs statfs_buf; struct statfs statfs_buf;
ret = statfs (path, &statfs_buf); ret = statfs (fileName, &statfs_buf);
#endif #endif
if (-1 == ret) { if (-1 == ret) {
return -1; perror("POSIX couldn't call statvfs");
} return -1;
}
stat_buf->f_bsize = statfs_buf.f_bsize; stat_buf->f_bsize = statfs_buf.f_bsize;
stat_buf->f_blocks = statfs_buf.f_blocks; stat_buf->f_blocks = statfs_buf.f_blocks;
stat_buf->f_bfree = statfs_buf.f_bfree; stat_buf->f_bfree = statfs_buf.f_bfree;
stat_buf->f_files = statfs_buf.f_files; stat_buf->f_files = statfs_buf.f_files;
stat_buf->f_ffree = statfs_buf.f_ffree; 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); 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); 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); 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); return stat (path, buf);
} }
@ -202,92 +223,6 @@ char* aiori_get_version()
return ""; 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) const ior_aiori_t *aiori_select (const char *api)
{ {
char warn_str[256] = {0}; char warn_str[256] = {0};

View File

@ -24,7 +24,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <stdbool.h> #include <stdbool.h>
#include "ior.h"
#include "iordef.h" /* IOR Definitions */ #include "iordef.h" /* IOR Definitions */
#include "option.h" #include "option.h"
@ -63,31 +62,61 @@ typedef struct ior_aiori_statfs {
uint64_t f_ffree; uint64_t f_ffree;
} ior_aiori_statfs_t; } 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 { typedef struct ior_aiori {
char *name; char *name;
char *name_legacy; char *name_legacy;
void *(*create)(char *, IOR_param_t *); aiori_fd_t *(*create)(char *, int iorflags, aiori_mod_opt_t *);
int (*mknod)(char *); int (*mknod)(char *);
void *(*open)(char *, IOR_param_t *); aiori_fd_t *(*open)(char *, int iorflags, aiori_mod_opt_t *);
IOR_offset_t (*xfer)(int, void *, IOR_size_t *, /*
IOR_offset_t, IOR_param_t *); Allow to set generic transfer options that shall be applied to any subsequent IO call.
void (*close)(void *, IOR_param_t *); */
void (*delete)(char *, IOR_param_t *); 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); char* (*get_version)(void);
void (*fsync)(void *, IOR_param_t *); void (*fsync)(aiori_fd_t *, aiori_mod_opt_t *);
IOR_offset_t (*get_file_size)(IOR_param_t *, MPI_Comm, char *); IOR_offset_t (*get_file_size)(aiori_mod_opt_t * module_options, MPI_Comm, char *);
int (*statfs) (const char *, ior_aiori_statfs_t *, IOR_param_t * param); int (*statfs) (const char *, ior_aiori_statfs_t *, aiori_mod_opt_t * module_options);
int (*mkdir) (const char *path, mode_t mode, IOR_param_t * param); int (*mkdir) (const char *path, mode_t mode, aiori_mod_opt_t * module_options);
int (*rmdir) (const char *path, IOR_param_t * param); int (*rmdir) (const char *path, aiori_mod_opt_t * module_options);
int (*access) (const char *path, int mode, IOR_param_t * param); int (*access) (const char *path, int mode, aiori_mod_opt_t * module_options);
int (*stat) (const char *path, struct stat *buf, IOR_param_t * param); int (*stat) (const char *path, struct stat *buf, aiori_mod_opt_t * module_options);
void (*initialize)(void); /* called once per program before MPI is started */ void (*initialize)(aiori_mod_opt_t * options); /* called once per program before MPI is started */
void (*finalize)(void); /* called once per program after MPI is shutdown */ void (*finalize)(aiori_mod_opt_t * options); /* called once per program after MPI is shutdown */
option_help * (*get_options)(void ** init_backend_options, void* init_values); /* initializes the backend options as well and returns the pointer to the option help structure */ 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; 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; } ior_aiori_t;
enum bench_type { enum bench_type {
@ -112,8 +141,6 @@ extern ior_aiori_t rados_aiori;
extern ior_aiori_t cephfs_aiori; extern ior_aiori_t cephfs_aiori;
extern ior_aiori_t gfarm_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); const ior_aiori_t *aiori_select (const char *api);
int aiori_count (void); int aiori_count (void);
void aiori_supported_apis(char * APIs, char * APIs_legacy, enum bench_type type); void aiori_supported_apis(char * APIs, char * APIs_legacy, enum bench_type type);
@ -125,25 +152,25 @@ const char *aiori_default (void);
/* some generic POSIX-based backend calls */ /* some generic POSIX-based backend calls */
char * aiori_get_version (void); char * aiori_get_version (void);
int aiori_posix_statfs (const char *path, ior_aiori_statfs_t *stat_buf, IOR_param_t * param); int aiori_posix_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, IOR_param_t * param); int aiori_posix_mkdir (const char *path, mode_t mode, aiori_mod_opt_t * module_options);
int aiori_posix_rmdir (const char *path, IOR_param_t * param); int aiori_posix_rmdir (const char *path, aiori_mod_opt_t * module_options);
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);
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);
void aiori_posix_xfer_hints(aiori_xfer_hint_t * params);
void *POSIX_Create(char *testFileName, IOR_param_t * param); aiori_fd_t *POSIX_Create(char *testFileName, int flags, aiori_mod_opt_t * module_options);
int POSIX_Mknod(char *testFileName); int POSIX_Mknod(char *testFileName);
void *POSIX_Open(char *testFileName, IOR_param_t * param); aiori_fd_t *POSIX_Open(char *testFileName, int flags, aiori_mod_opt_t * module_options);
IOR_offset_t POSIX_GetFileSize(IOR_param_t * test, MPI_Comm testComm, char *testFileName); IOR_offset_t POSIX_GetFileSize(aiori_mod_opt_t * test, MPI_Comm testComm, char *testFileName);
void POSIX_Delete(char *testFileName, IOR_param_t * param); void POSIX_Delete(char *testFileName, aiori_mod_opt_t * module_options);
void POSIX_Close(void *fd, IOR_param_t * param); void POSIX_Close(aiori_fd_t *fd, aiori_mod_opt_t * module_options);
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);
/* NOTE: these 3 MPI-IO functions are exported for reuse by HDF5/PNetCDF */ /* NOTE: these 3 MPI-IO functions are exported for reuse by HDF5/PNetCDF */
void MPIIO_Delete(char *testFileName, IOR_param_t * param); void MPIIO_Delete(char *testFileName, aiori_mod_opt_t * module_options);
IOR_offset_t MPIIO_GetFileSize(IOR_param_t * test, MPI_Comm testComm, IOR_offset_t MPIIO_GetFileSize(aiori_mod_opt_t * options, MPI_Comm testComm, char *testFileName);
char *testFileName); int MPIIO_Access(const char *, int, aiori_mod_opt_t *);
int MPIIO_Access(const char *, int, IOR_param_t *);
#endif /* not _AIORI_H */ #endif /* not _AIORI_H */

View File

@ -17,7 +17,6 @@ void PrintShortSummary(IOR_test_t * test);
void PrintLongSummaryAllTests(IOR_test_t *tests_head); void PrintLongSummaryAllTests(IOR_test_t *tests_head);
void PrintLongSummaryHeader(); void PrintLongSummaryHeader();
void PrintLongSummaryOneTest(IOR_test_t *test); void PrintLongSummaryOneTest(IOR_test_t *test);
void DisplayFreespace(IOR_param_t * test);
void GetTestFileName(char *, IOR_param_t *); void GetTestFileName(char *, IOR_param_t *);
void PrintRemoveTiming(double start, double finish, int rep); void PrintRemoveTiming(double start, double finish, int rep);
void PrintReducedResult(IOR_test_t *test, int access, double bw, double iops, double latency, void PrintReducedResult(IOR_test_t *test, int access, double bw, double iops, double latency,

View File

@ -322,11 +322,8 @@ void ShowTestStart(IOR_param_t *test)
PrintStartSection(); PrintStartSection();
PrintKeyValInt("TestID", test->id); PrintKeyValInt("TestID", test->id);
PrintKeyVal("StartTime", CurrentTimeString()); PrintKeyVal("StartTime", CurrentTimeString());
/* if pvfs2:, then skip */
if (strcasecmp(test->api, "DFS") && ShowFileSystemSize(test);
Regex(test->testFileName, "^[a-z][a-z].*:") == 0) {
DisplayFreespace(test);
}
if (verbose >= VERBOSE_3 || outputFormat == OUTPUT_JSON) { if (verbose >= VERBOSE_3 || outputFormat == OUTPUT_JSON) {
char* data_packets[] = {"g","t","o","i"}; char* data_packets[] = {"g","t","o","i"};
@ -337,7 +334,6 @@ void ShowTestStart(IOR_param_t *test)
PrintKeyVal("api", test->api); PrintKeyVal("api", test->api);
PrintKeyVal("platform", test->platform); PrintKeyVal("platform", test->platform);
PrintKeyVal("testFileName", test->testFileName); PrintKeyVal("testFileName", test->testFileName);
PrintKeyVal("hintsFileName", test->hintsFileName);
PrintKeyValInt("deadlineForStonewall", test->deadlineForStonewalling); PrintKeyValInt("deadlineForStonewall", test->deadlineForStonewalling);
PrintKeyValInt("stoneWallingWearOut", test->stoneWallingWearOut); PrintKeyValInt("stoneWallingWearOut", test->stoneWallingWearOut);
PrintKeyValInt("maxTimeDuration", test->maxTimeDuration); PrintKeyValInt("maxTimeDuration", test->maxTimeDuration);
@ -355,9 +351,7 @@ void ShowTestStart(IOR_param_t *test)
PrintKeyValInt("fsync", test->fsync); PrintKeyValInt("fsync", test->fsync);
PrintKeyValInt("fsyncperwrite", test->fsyncPerWrite); PrintKeyValInt("fsyncperwrite", test->fsyncPerWrite);
PrintKeyValInt("useExistingTestFile", test->useExistingTestFile); PrintKeyValInt("useExistingTestFile", test->useExistingTestFile);
PrintKeyValInt("showHints", test->showHints);
PrintKeyValInt("uniqueDir", test->uniqueDir); PrintKeyValInt("uniqueDir", test->uniqueDir);
PrintKeyValInt("individualDataSets", test->individualDataSets);
PrintKeyValInt("singleXferAttempt", test->singleXferAttempt); PrintKeyValInt("singleXferAttempt", test->singleXferAttempt);
PrintKeyValInt("readFile", test->readFile); PrintKeyValInt("readFile", test->readFile);
PrintKeyValInt("writeFile", test->writeFile); PrintKeyValInt("writeFile", test->writeFile);
@ -368,12 +362,7 @@ void ShowTestStart(IOR_param_t *test)
PrintKeyValInt("randomOffset", test->randomOffset); PrintKeyValInt("randomOffset", test->randomOffset);
PrintKeyValInt("checkWrite", test->checkWrite); PrintKeyValInt("checkWrite", test->checkWrite);
PrintKeyValInt("checkRead", test->checkRead); PrintKeyValInt("checkRead", test->checkRead);
PrintKeyValInt("preallocate", test->preallocate);
PrintKeyValInt("useFileView", test->useFileView);
PrintKeyValInt("setAlignment", test->setAlignment);
PrintKeyValInt("storeFileOffset", test->storeFileOffset); PrintKeyValInt("storeFileOffset", test->storeFileOffset);
PrintKeyValInt("useSharedFilePointer", test->useSharedFilePointer);
PrintKeyValInt("useStridedDatatype", test->useStridedDatatype);
PrintKeyValInt("keepFile", test->keepFile); PrintKeyValInt("keepFile", test->keepFile);
PrintKeyValInt("keepFileWithError", test->keepFileWithError); PrintKeyValInt("keepFileWithError", test->keepFileWithError);
PrintKeyValInt("quitOnError", test->quitOnError); PrintKeyValInt("quitOnError", test->quitOnError);
@ -452,14 +441,6 @@ void ShowSetup(IOR_param_t *params)
if(params->dryRun){ if(params->dryRun){
PrintKeyValInt("dryRun", 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);
}
#endif /* HAVE_LUSTRE_LUSTRE_USER_H */
if (params->deadlineForStonewalling > 0) { if (params->deadlineForStonewalling > 0) {
PrintKeyValInt("stonewallingTime", params->deadlineForStonewalling); PrintKeyValInt("stonewallingTime", params->deadlineForStonewalling);
PrintKeyValInt("stoneWallingWearOut", params->stoneWallingWearOut ); PrintKeyValInt("stoneWallingWearOut", params->stoneWallingWearOut );
@ -740,38 +721,6 @@ 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) void PrintRemoveTiming(double start, double finish, int rep)
{ {
if (rank != 0 || verbose < VERBOSE_0) if (rank != 0 || verbose < VERBOSE_0)

227
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 TestIoSys(IOR_test_t *);
static void ValidateTests(IOR_param_t *); static void ValidateTests(IOR_param_t *);
static IOR_offset_t WriteOrRead(IOR_param_t *test, IOR_results_t *results, 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); 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 * ior_run(int argc, char **argv, MPI_Comm world_com, FILE * world_out){
IOR_test_t *tests_head; IOR_test_t *tests_head;
IOR_test_t *tptr; IOR_test_t *tptr;
@ -76,17 +117,12 @@ IOR_test_t * ior_run(int argc, char **argv, MPI_Comm world_com, FILE * world_out
/* perform each test */ /* perform each test */
for (tptr = tests_head; tptr != NULL; tptr = tptr->next) { for (tptr = tests_head; tptr != NULL; tptr = tptr->next) {
aiori_initialize(tptr); test_initialize(tptr);
totalErrorCount = 0; totalErrorCount = 0;
verbose = tptr->params.verbose;
backend = tptr->params.backend;
if (rank == 0 && verbose >= VERBOSE_0) {
ShowTestStart(&tptr->params);
}
TestIoSys(tptr); TestIoSys(tptr);
tptr->results->errors = totalErrorCount; tptr->results->errors = totalErrorCount;
ShowTestEnd(tptr); ShowTestEnd(tptr);
aiori_finalize(tptr); test_finalize(tptr);
} }
PrintLongSummaryAllTests(tests_head); PrintLongSummaryAllTests(tests_head);
@ -125,18 +161,11 @@ int ior_main(int argc, char **argv)
InitTests(tests_head, mpi_comm_world); InitTests(tests_head, mpi_comm_world);
verbose = tests_head->params.verbose; verbose = tests_head->params.verbose;
aiori_initialize(tests_head); // this is quite suspicious, likely an error when multiple tests need to be executed with different backends and options
PrintHeader(argc, argv); PrintHeader(argc, argv);
/* perform each test */ /* perform each test */
for (tptr = tests_head; tptr != NULL; tptr = tptr->next) { for (tptr = tests_head; tptr != NULL; tptr = tptr->next) {
verbose = tptr->params.verbose; test_initialize(tptr);
backend = tptr->params.backend;
if (rank == 0 && verbose >= VERBOSE_0) {
backend = tptr->params.backend;
ShowTestStart(&tptr->params);
}
// This is useful for trapping a running MPI process. While // This is useful for trapping a running MPI process. While
// this is sleeping, run the script 'testing/hdfs/gdb.attach' // this is sleeping, run the script 'testing/hdfs/gdb.attach'
@ -148,6 +177,7 @@ int ior_main(int argc, char **argv)
TestIoSys(tptr); TestIoSys(tptr);
ShowTestEnd(tptr); ShowTestEnd(tptr);
test_finalize(tptr);
} }
if (verbose < 0) if (verbose < 0)
@ -158,8 +188,6 @@ int ior_main(int argc, char **argv)
/* display finish time */ /* display finish time */
PrintTestEnds(); PrintTestEnds();
aiori_finalize(tests_head);
MPI_CHECK(MPI_Finalize(), "cannot finalize MPI"); MPI_CHECK(MPI_Finalize(), "cannot finalize MPI");
DestroyTests(tests_head); DestroyTests(tests_head);
@ -180,10 +208,6 @@ void init_IOR_Param_t(IOR_param_t * p)
assert (NULL != default_aiori); assert (NULL != default_aiori);
memset(p, 0, sizeof(IOR_param_t)); 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->api = strdup(default_aiori);
p->platform = strdup("HOST(OSTYPE)"); p->platform = strdup("HOST(OSTYPE)");
p->testFileName = strdup("testFile"); p->testFileName = strdup("testFile");
@ -209,8 +233,6 @@ void init_IOR_Param_t(IOR_param_t * p)
p->randomSeed = -1; p->randomSeed = -1;
p->incompressibleSeed = 573; p->incompressibleSeed = 573;
p->testComm = mpi_comm_world; p->testComm = mpi_comm_world;
p->setAlignment = 1;
p->lustre_start_ost = -1;
hdfs_user = getenv("USER"); hdfs_user = getenv("USER");
if (!hdfs_user) if (!hdfs_user)
@ -224,9 +246,6 @@ void init_IOR_Param_t(IOR_param_t * p)
p->URI = NULL; p->URI = NULL;
p->part_number = 0; p->part_number = 0;
p->beegfs_numTargets = -1;
p->beegfs_chunkSize = -1;
} }
static void static void
@ -365,7 +384,7 @@ CompareBuffers(void *expectedBuffer,
if (verbose >= VERBOSE_3) { if (verbose >= VERBOSE_3) {
fprintf(out_logfile, fprintf(out_logfile,
"[%d] At file byte offset %lld, comparing %llu-byte transfer\n", "[%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++) { for (i = 0; i < length; i++) {
if (testbuf[i] != goodbuf[i]) { if (testbuf[i] != goodbuf[i]) {
@ -374,7 +393,7 @@ CompareBuffers(void *expectedBuffer,
fprintf(out_logfile, fprintf(out_logfile,
"[%d] At transfer buffer #%lld, index #%lld (file byte offset %lld):\n", "[%d] At transfer buffer #%lld, index #%lld (file byte offset %lld):\n",
rank, transferCount - 1, (long long)i, rank, transferCount - 1, (long long)i,
test->offset + (long long) offset +
(IOR_size_t) (i * sizeof(IOR_size_t))); (IOR_size_t) (i * sizeof(IOR_size_t)));
fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel1); fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel1);
fprintf(out_logfile, "%016llx\n", goodbuf[i]); fprintf(out_logfile, "%016llx\n", goodbuf[i]);
@ -390,10 +409,10 @@ CompareBuffers(void *expectedBuffer,
} }
} else if (verbose >= VERBOSE_5 && i % 4 == 0) { } else if (verbose >= VERBOSE_5 && i % 4 == 0) {
fprintf(out_logfile, fprintf(out_logfile,
"[%d] PASSED offset = %lld bytes, transfer %lld\n", "[%d] PASSED offset = %lu bytes, transfer %lld\n",
rank, rank,
((i * sizeof(unsigned long long)) + ((i * sizeof(unsigned long long)) +
test->offset), transferCount); offset), transferCount);
fprintf(out_logfile, "[%d] GOOD %s0x", rank, bufferLabel1); fprintf(out_logfile, "[%d] GOOD %s0x", rank, bufferLabel1);
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
fprintf(out_logfile, "%016llx ", goodbuf[i + j]); fprintf(out_logfile, "%016llx ", goodbuf[i + j]);
@ -416,8 +435,8 @@ CompareBuffers(void *expectedBuffer,
"%lld errors between buffer indices %lld and %lld.\n", "%lld errors between buffer indices %lld and %lld.\n",
(long long)errorCount, (long long)first, (long long)errorCount, (long long)first,
(long long)last); (long long)last);
fprintf(out_logfile, "[%d] File byte offset = %lld:\n", rank, fprintf(out_logfile, "[%d] File byte offset = %lu:\n", rank,
((first * sizeof(unsigned long long)) + test->offset)); ((first * sizeof(unsigned long long)) + offset));
fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel1); fprintf(out_logfile, "[%d] %s0x", rank, bufferLabel1);
for (j = first; j < length && j < first + 4; j++) for (j = first; j < length && j < first + 4; j++)
@ -824,15 +843,15 @@ static char *PrependDir(IOR_param_t * test, char *rootDir)
sprintf(dir + i + 1, "%d", (rank + rankOffset) % test->numTasks); sprintf(dir + i + 1, "%d", (rank + rankOffset) % test->numTasks);
/* dir doesn't exist, so create */ /* dir doesn't exist, so create */
if (backend->access(dir, F_OK, test) != 0) { if (backend->access(dir, F_OK, test->backend_options) != 0) {
if (backend->mkdir(dir, S_IRWXU, test) < 0) { if (backend->mkdir(dir, S_IRWXU, test->backend_options) < 0) {
ERRF("cannot create directory: %s", dir); ERRF("cannot create directory: %s", dir);
} }
/* check if correct permissions */ /* check if correct permissions */
} else if (backend->access(dir, R_OK, test) != 0 || } else if (backend->access(dir, R_OK, test->backend_options) != 0 ||
backend->access(dir, W_OK, test) != 0 || backend->access(dir, W_OK, test->backend_options) != 0 ||
backend->access(dir, X_OK, test) != 0) { backend->access(dir, X_OK, test->backend_options) != 0) {
ERRF("invalid directory permissions: %s", dir); ERRF("invalid directory permissions: %s", dir);
} }
@ -919,24 +938,24 @@ static void RemoveFile(char *testFileName, int filePerProc, IOR_param_t * test)
rankOffset = 0; rankOffset = 0;
GetTestFileName(testFileName, test); 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) { if (verbose >= VERBOSE_3) {
fprintf(out_logfile, "task %d removing %s\n", rank, fprintf(out_logfile, "task %d removing %s\n", rank,
testFileName); testFileName);
} }
backend->delete(testFileName, test); backend->delete(testFileName, test->backend_options);
} }
if (test->reorderTasksRandom == TRUE) { if (test->reorderTasksRandom == TRUE) {
rankOffset = tmpRankOffset; rankOffset = tmpRankOffset;
GetTestFileName(testFileName, test); GetTestFileName(testFileName, test);
} }
} else { } 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) { if (verbose >= VERBOSE_3) {
fprintf(out_logfile, "task %d removing %s\n", rank, fprintf(out_logfile, "task %d removing %s\n", rank,
testFileName); testFileName);
} }
backend->delete(testFileName, test); backend->delete(testFileName, test->backend_options);
} }
} }
} }
@ -1231,7 +1250,7 @@ static void TestIoSys(IOR_test_t *test)
double startTime; double startTime;
int pretendRank; int pretendRank;
int rep; int rep;
void *fd; aiori_fd_t *fd;
MPI_Group orig_group, new_group; MPI_Group orig_group, new_group;
int range[3]; int range[3];
IOR_offset_t dataMoved; /* for data rate calculation */ IOR_offset_t dataMoved; /* for data rate calculation */
@ -1338,7 +1357,7 @@ static void TestIoSys(IOR_test_t *test)
MPI_CHECK(MPI_Barrier(testComm), "barrier error"); MPI_CHECK(MPI_Barrier(testComm), "barrier error");
params->open = WRITE; params->open = WRITE;
timer[0] = GetTimeStamp(); timer[0] = GetTimeStamp();
fd = backend->create(testFileName, params); fd = backend->create(testFileName, IOR_WRONLY | IOR_CREAT | IOR_TRUNC, params->backend_options);
timer[1] = GetTimeStamp(); timer[1] = GetTimeStamp();
if (params->intraTestBarriers) if (params->intraTestBarriers)
MPI_CHECK(MPI_Barrier(testComm), MPI_CHECK(MPI_Barrier(testComm),
@ -1359,14 +1378,14 @@ static void TestIoSys(IOR_test_t *test)
MPI_CHECK(MPI_Barrier(testComm), MPI_CHECK(MPI_Barrier(testComm),
"barrier error"); "barrier error");
timer[4] = GetTimeStamp(); timer[4] = GetTimeStamp();
backend->close(fd, params); backend->close(fd, params->backend_options);
timer[5] = GetTimeStamp(); timer[5] = GetTimeStamp();
MPI_CHECK(MPI_Barrier(testComm), "barrier error"); MPI_CHECK(MPI_Barrier(testComm), "barrier error");
/* get the size of the file just written */ /* get the size of the file just written */
results[rep].write.aggFileSizeFromStat = 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, /* check if stat() of file doesn't equal expected file size,
use actual amount of byte moved */ use actual amount of byte moved */
@ -1412,9 +1431,9 @@ static void TestIoSys(IOR_test_t *test)
GetTestFileName(testFileName, params); GetTestFileName(testFileName, params);
params->open = WRITECHECK; 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); dataMoved = WriteOrRead(params, &results[rep], fd, WRITECHECK, &ioBuffers);
backend->close(fd, params); backend->close(fd, params->backend_options);
rankOffset = 0; rankOffset = 0;
} }
/* /*
@ -1484,7 +1503,7 @@ static void TestIoSys(IOR_test_t *test)
MPI_CHECK(MPI_Barrier(testComm), "barrier error"); MPI_CHECK(MPI_Barrier(testComm), "barrier error");
params->open = READ; params->open = READ;
timer[0] = GetTimeStamp(); timer[0] = GetTimeStamp();
fd = backend->open(testFileName, params); fd = backend->open(testFileName, IOR_RDONLY, params->backend_options);
timer[1] = GetTimeStamp(); timer[1] = GetTimeStamp();
if (params->intraTestBarriers) if (params->intraTestBarriers)
MPI_CHECK(MPI_Barrier(testComm), MPI_CHECK(MPI_Barrier(testComm),
@ -1501,12 +1520,12 @@ static void TestIoSys(IOR_test_t *test)
MPI_CHECK(MPI_Barrier(testComm), MPI_CHECK(MPI_Barrier(testComm),
"barrier error"); "barrier error");
timer[4] = GetTimeStamp(); timer[4] = GetTimeStamp();
backend->close(fd, params); backend->close(fd, params->backend_options);
timer[5] = GetTimeStamp(); timer[5] = GetTimeStamp();
/* get the size of the file just read */ /* get the size of the file just read */
results[rep].read.aggFileSizeFromStat = results[rep].read.aggFileSizeFromStat =
backend->get_file_size(params, testComm, backend->get_file_size(params->backend_options, testComm,
testFileName); testFileName);
/* check if stat() of file doesn't equal expected file size, /* check if stat() of file doesn't equal expected file size,
@ -1587,8 +1606,6 @@ static void ValidateTests(IOR_param_t * test)
ERR("block size must be non-negative integer"); ERR("block size must be non-negative integer");
if ((test->transferSize % sizeof(IOR_size_t)) != 0) if ((test->transferSize % sizeof(IOR_size_t)) != 0)
ERR("transfer size must be a multiple of access size"); 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) if (test->transferSize < 0)
ERR("transfer size must be non-negative integer"); ERR("transfer size must be non-negative integer");
if (test->transferSize == 0) { if (test->transferSize == 0) {
@ -1613,11 +1630,6 @@ static void ValidateTests(IOR_param_t * test)
&& (test->blockSize < sizeof(IOR_size_t) && (test->blockSize < sizeof(IOR_size_t)
|| test->transferSize < sizeof(IOR_size_t))) || test->transferSize < sizeof(IOR_size_t)))
ERR("block/transfer size may not be smaller than IOR_size_t for NCMPI"); 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) if ((strcasecmp(test->api, "POSIX") != 0) && test->singleXferAttempt)
WARN_RESET("retry only available in POSIX", WARN_RESET("retry only available in POSIX",
test, &defaults, singleXferAttempt); test, &defaults, singleXferAttempt);
@ -1632,39 +1644,6 @@ static void ValidateTests(IOR_param_t * test)
&& (strcasecmp(test->api, "CEPHFS") != 0)) && test->fsync) && (strcasecmp(test->api, "CEPHFS") != 0)) && test->fsync)
WARN_RESET("fsync() not supported in selected backend", WARN_RESET("fsync() not supported in selected backend",
test, &defaults, fsync); 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 */ /* parameter consitency */
if (test->reorderTasks == TRUE && test->reorderTasksRandom == TRUE) if (test->reorderTasks == TRUE && test->reorderTasksRandom == TRUE)
ERR("Both Constant and Random task re-ordering specified. Choose one and resubmit"); ERR("Both Constant and Random task re-ordering specified. Choose one and resubmit");
@ -1678,51 +1657,19 @@ static void ValidateTests(IOR_param_t * test)
ERR("random offset not available with read check option (use write check)"); ERR("random offset not available with read check option (use write check)");
if (test->randomOffset && test->storeFileOffset) if (test->randomOffset && test->storeFileOffset)
ERR("random offset not available with store file offset option)"); 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) if ((strcasecmp(test->api, "HDF5") == 0) && test->randomOffset)
ERR("random offset not available with HDF5"); ERR("random offset not available with HDF5");
if ((strcasecmp(test->api, "NCMPI") == 0) && test->randomOffset) if ((strcasecmp(test->api, "NCMPI") == 0) && test->randomOffset)
ERR("random offset not available with NCMPI"); 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) if ((strcasecmp(test->api, "NCMPI") == 0) && test->filePerProc)
ERR("file-per-proc not available in current NCMPI"); 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 */ /* allow the backend to validate the options */
if(test->backend->check_params){ if(test->backend->check_params){
int check = test->backend->check_params(test); int check = test->backend->check_params(test->backend_options);
if (check == 0){ if (check){
ERR("The backend returned that the test parameters are invalid."); ERR("The backend returned that the test parameters are invalid.");
} }
} }
@ -1854,7 +1801,7 @@ IOR_offset_t *GetOffsetArrayRandom(IOR_param_t * test, int pretendRank, int acce
} }
static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offsetArray, 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 amtXferred = 0;
IOR_offset_t transfer; IOR_offset_t transfer;
@ -1862,26 +1809,26 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
void *checkBuffer = ioBuffers->checkBuffer; void *checkBuffer = ioBuffers->checkBuffer;
void *readCheckBuffer = ioBuffers->readCheckBuffer; void *readCheckBuffer = ioBuffers->readCheckBuffer;
test->offset = offsetArray[pairCnt]; IOR_offset_t offset = offsetArray[pairCnt]; // this looks inappropriate
transfer = test->transferSize; transfer = test->transferSize;
if (access == WRITE) { if (access == WRITE) {
/* fills each transfer with a unique pattern /* fills each transfer with a unique pattern
* containing the offset into the file */ * containing the offset into the file */
if (test->storeFileOffset == TRUE) { if (test->storeFileOffset == TRUE) {
FillBuffer(buffer, test, test->offset, pretendRank); FillBuffer(buffer, test, offset, pretendRank);
} }
amtXferred = amtXferred = backend->xfer(access, fd, buffer, transfer, offset, test->backend_options);
backend->xfer(access, fd, buffer, transfer, test);
if (amtXferred != transfer) if (amtXferred != transfer)
ERR("cannot write to file"); ERR("cannot write to file");
if (test->fsyncPerWrite)
backend->fsync(fd, test->backend_options);
if (test->interIODelay > 0){ if (test->interIODelay > 0){
struct timespec wait = {test->interIODelay / 1000 / 1000, 1000l * (test->interIODelay % 1000000)}; struct timespec wait = {test->interIODelay / 1000 / 1000, 1000l * (test->interIODelay % 1000000)};
nanosleep( & wait, NULL); nanosleep( & wait, NULL);
} }
} else if (access == READ) { } else if (access == READ) {
amtXferred = amtXferred = backend->xfer(access, fd, buffer, transfer, offset, test->backend_options);
backend->xfer(access, fd, buffer, transfer, test);
if (amtXferred != transfer) if (amtXferred != transfer)
ERR("cannot read from file"); ERR("cannot read from file");
if (test->interIODelay > 0){ if (test->interIODelay > 0){
@ -1892,10 +1839,10 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
memset(checkBuffer, 'a', transfer); memset(checkBuffer, 'a', transfer);
if (test->storeFileOffset == TRUE) { 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) if (amtXferred != transfer)
ERR("cannot read from file write check"); ERR("cannot read from file write check");
(*transferCount)++; (*transferCount)++;
@ -1905,12 +1852,12 @@ static IOR_offset_t WriteOrReadSingle(IOR_offset_t pairCnt, IOR_offset_t *offset
} else if (access == READCHECK) { } else if (access == READCHECK) {
memset(checkBuffer, 'a', transfer); 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){ if (amtXferred != transfer){
ERR("cannot read from file"); ERR("cannot read from file");
} }
if (test->storeFileOffset == TRUE) { if (test->storeFileOffset == TRUE) {
FillBuffer(readCheckBuffer, test, test->offset, pretendRank); FillBuffer(readCheckBuffer, test, offset, pretendRank);
} }
*errors += CompareBuffers(readCheckBuffer, checkBuffer, transfer, *transferCount, test, READCHECK); *errors += CompareBuffers(readCheckBuffer, checkBuffer, transfer, *transferCount, test, READCHECK);
} }
@ -1922,7 +1869,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. * 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, 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; int errors = 0;
IOR_offset_t transferCount = 0; IOR_offset_t transferCount = 0;
@ -2002,7 +1949,7 @@ static IOR_offset_t WriteOrRead(IOR_param_t *test, IOR_results_t *results,
free(offsetArray); free(offsetArray);
if (access == WRITE && test->fsync == TRUE) { 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); return (dataMoved);
} }

View File

@ -36,8 +36,10 @@
typedef void *rados_ioctx_t; typedef void *rados_ioctx_t;
#endif #endif
#include "option.h" #include "option.h"
#include "iordef.h" #include "iordef.h"
#include "aiori.h"
#define ISPOWEROFTWO(x) ((x != 0) && !(x & (x - 1)))
/******************** DATA Packet Type ***************************************/ /******************** DATA Packet Type ***************************************/
/* Holds the types of data packets: generic, offset, timestamp, incompressible */ /* Holds the types of data packets: generic, offset, timestamp, incompressible */
@ -78,23 +80,19 @@ typedef struct IO_BUFFERS
* USER_GUIDE * USER_GUIDE
*/ */
struct ior_aiori;
typedef struct typedef struct
{ {
const struct ior_aiori * backend; const struct ior_aiori * backend;
char * debug; /* debug info string */ char * debug; /* debug info string */
unsigned int mode; /* file permissions */
unsigned int openFlags; /* open flags (see also <open>) */
int referenceNumber; /* user supplied reference number */ int referenceNumber; /* user supplied reference number */
char * api; /* API for I/O */ char * api; /* API for I/O */
char * apiVersion; /* API version */ char * apiVersion; /* API version */
char * platform; /* platform type */ char * platform; /* platform type */
char * testFileName; /* full name for test */ 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 */ char * options; /* options string */
// intermediate options // 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 dryRun; /* do not perform any I/Os just run evtl. inputs print dummy output */
int numTasks; /* number of tasks for test */ int numTasks; /* number of tasks for test */
int numNodes; /* number of nodes for test */ int numNodes; /* number of nodes for test */
@ -119,17 +117,11 @@ typedef struct
int keepFileWithError; /* don't delete the testfile with errors */ int keepFileWithError; /* don't delete the testfile with errors */
int errorFound; /* error found in data check */ int errorFound; /* error found in data check */
int quitOnError; /* quit code when error in 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 segmentCount; /* number of segments (or HDF5 datasets) */
IOR_offset_t blockSize; /* contiguous bytes to write per task */ IOR_offset_t blockSize; /* contiguous bytes to write per task */
IOR_offset_t transferSize; /* size of transfer in bytes */ 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 */ 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 summary_every_test; /* flag to print summary every test, not just at end */
int uniqueDir; /* use unique directory for each fpp */ int uniqueDir; /* use unique directory for each fpp */
int useExistingTestFile; /* do not delete test file before access */ int useExistingTestFile; /* do not delete test file before access */
@ -144,7 +136,6 @@ typedef struct
int verbose; /* verbosity */ int verbose; /* verbosity */
int setTimeStampSignature; /* set time stamp signature */ int setTimeStampSignature; /* set time stamp signature */
unsigned int timeStampSignatureValue; /* value for 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 */ int randomSeed; /* random seed for write/read check */
unsigned int incompressibleSeed; /* random seed for incompressible file creation */ unsigned int incompressibleSeed; /* random seed for incompressible file creation */
int randomOffset; /* access is to random offsets */ int randomOffset; /* access is to random offsets */
@ -162,16 +153,6 @@ typedef struct
int fsyncPerWrite; /* fsync() after each write */ int fsyncPerWrite; /* fsync() after each write */
int fsync; /* fsync() after 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 */ /* HDFS variables */
char * hdfs_user; /* copied from ENV, for now */ char * hdfs_user; /* copied from ENV, for now */
const char* hdfs_name_node; const char* hdfs_name_node;
@ -191,23 +172,10 @@ typedef struct
/* NCMPI variables */ /* NCMPI variables */
int var_id; /* variable id handle for data set */ 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 id; /* test's unique ID */
int intraTestBarriers; /* barriers between open/op and op/close */ int intraTestBarriers; /* barriers between open/op and op/close */
aiori_xfer_hint_t hints;
} IOR_param_t; } IOR_param_t;
/* each pointer for a single test */ /* each pointer for a single test */

View File

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

View File

@ -166,8 +166,9 @@ static uid_t uid;
/* Use the POSIX backend by default */ /* Use the POSIX backend by default */
static const ior_aiori_t *backend; static const ior_aiori_t *backend;
static void * backend_options;
static IOR_param_t param; static aiori_xfer_hint_t hints;
static char * api = NULL;
/* This structure describes the processing status for stonewalling */ /* This structure describes the processing status for stonewalling */
typedef struct{ typedef struct{
@ -276,7 +277,7 @@ static void phase_end(){
if(! backend->sync){ if(! backend->sync){
FAIL("Error, backend does not provide the sync method, but you requested to use sync.\n"); 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) { 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); VERBOSE(3,5,"create_remove_items_helper (dirs %s): curr_item is '%s'", operation, curr_item);
if (create) { 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); FAIL("unable to create directory %s", curr_item);
} }
} else { } else {
if (backend->rmdir(curr_item, &param) == -1) { if (backend->rmdir(curr_item, backend_options) == -1) {
FAIL("unable to remove directory %s", curr_item); 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); 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); VERBOSE(3,5,"create_remove_items_helper (non-dirs remove): curr_item is '%s'", curr_item);
if (!(shared_file && rank != 0)) { 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) { static void create_file (const char *path, uint64_t itemNum) {
char curr_item[MAX_PATHLEN]; char curr_item[MAX_PATHLEN];
void *aiori_fh = NULL; aiori_fd_t *aiori_fh = NULL;
if ( (itemNum % ITEM_COUNT==0 && (itemNum != 0))) { if ( (itemNum % ITEM_COUNT==0 && (itemNum != 0))) {
VERBOSE(3,5,"create file: "LLU"", itemNum); VERBOSE(3,5,"create file: "LLU"", itemNum);
@ -355,8 +356,6 @@ static void create_file (const char *path, uint64_t itemNum) {
sprintf(curr_item, "%s/file.%s"LLU"", path, mk_name, 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); VERBOSE(3,5,"create_remove_items_helper (non-dirs create): curr_item is '%s'", curr_item);
param.openFlags = IOR_WRONLY;
if (make_node) { if (make_node) {
int ret; int ret;
VERBOSE(3,5,"create_remove_items_helper : mknod..." ); VERBOSE(3,5,"create_remove_items_helper : mknod..." );
@ -369,7 +368,7 @@ static void create_file (const char *path, uint64_t itemNum) {
} else if (collective_creates) { } else if (collective_creates) {
VERBOSE(3,5,"create_remove_items_helper (collective): open..." ); VERBOSE(3,5,"create_remove_items_helper (collective): open..." );
aiori_fh = backend->open (curr_item, &param); aiori_fh = backend->open (curr_item, IOR_WRONLY | IOR_CREAT, backend_options);
if (NULL == aiori_fh) if (NULL == aiori_fh)
FAIL("unable to open file %s", curr_item); FAIL("unable to open file %s", curr_item);
@ -377,12 +376,10 @@ static void create_file (const char *path, uint64_t itemNum) {
* !collective_creates * !collective_creates
*/ */
} else { } else {
param.openFlags |= IOR_CREAT; hints.filePerProc = !shared_file;
param.filePerProc = !shared_file;
param.mode = FILEMODE;
VERBOSE(3,5,"create_remove_items_helper (non-collective, shared): open..." ); VERBOSE(3,5,"create_remove_items_helper (non-collective, shared): open..." );
aiori_fh = backend->create (curr_item, &param); aiori_fh = backend->create (curr_item, IOR_WRONLY | IOR_CREAT, backend_options);
if (NULL == aiori_fh) if (NULL == aiori_fh)
FAIL("unable to create file %s", curr_item); FAIL("unable to create file %s", curr_item);
} }
@ -394,15 +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 * According to Bill Loewe, writes are only done one time, so they are always at
* offset 0 (zero). * offset 0 (zero).
*/ */
param.offset = 0; hints.fsyncPerWrite = sync_file;
param.fsyncPerWrite = sync_file; if ( write_bytes != (size_t) backend->xfer (WRITE, aiori_fh, (IOR_size_t *) write_buffer, write_bytes, 0, backend_options)) {
if ( write_bytes != (size_t) backend->xfer (WRITE, aiori_fh, (IOR_size_t *) write_buffer, write_bytes, &param)) {
FAIL("unable to write file %s", curr_item); FAIL("unable to write file %s", curr_item);
} }
} }
VERBOSE(3,5,"create_remove_items_helper: close..." ); VERBOSE(3,5,"create_remove_items_helper: close..." );
backend->close (aiori_fh, &param); backend->close (aiori_fh, backend_options);
} }
/* helper for creating/removing items */ /* helper for creating/removing items */
@ -446,20 +442,18 @@ void collective_helper(const int dirs, const int create, const char* path, uint6
VERBOSE(3,5,"create file: %s", curr_item); VERBOSE(3,5,"create file: %s", curr_item);
if (create) { if (create) {
void *aiori_fh; aiori_fd_t *aiori_fh;
//create files //create files
param.openFlags = IOR_WRONLY | IOR_CREAT; aiori_fh = backend->create (curr_item, IOR_WRONLY | IOR_CREAT, backend_options);
param.mode = FILEMODE;
aiori_fh = backend->create (curr_item, &param);
if (NULL == aiori_fh) { if (NULL == aiori_fh) {
FAIL("unable to create file %s", curr_item); 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)) { } else if (!(shared_file && rank != 0)) {
//remove files //remove files
backend->delete (curr_item, &param); backend->delete (curr_item, backend_options);
} }
if(CHECK_STONE_WALL(progress)){ if(CHECK_STONE_WALL(progress)){
progress->items_done = i + 1; progress->items_done = i + 1;
@ -616,7 +610,7 @@ void mdtest_stat(const int random, const int dirs, const long dir_iter, const ch
/* below temp used to be hiername */ /* below temp used to be hiername */
VERBOSE(3,5,"mdtest_stat %4s: %s", (dirs ? "dir" : "file"), item); 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); FAIL("unable to stat %s %s", dirs ? "directory" : "file", item);
} }
} }
@ -627,7 +621,7 @@ 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) { void mdtest_read(int random, int dirs, const long dir_iter, char *path) {
uint64_t parent_dir, item_num = 0; uint64_t parent_dir, item_num = 0;
char item[MAX_PATHLEN], temp[MAX_PATHLEN]; char item[MAX_PATHLEN], temp[MAX_PATHLEN];
void *aiori_fh; aiori_fd_t *aiori_fh;
VERBOSE(1,-1,"Entering mdtest_read on %s", path ); VERBOSE(1,-1,"Entering mdtest_read on %s", path );
@ -713,8 +707,7 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) {
VERBOSE(3,5,"mdtest_read file: %s", item); VERBOSE(3,5,"mdtest_read file: %s", item);
/* open file for reading */ /* open file for reading */
param.openFlags = O_RDONLY; aiori_fh = backend->open (item, O_RDONLY, backend_options);
aiori_fh = backend->open (item, &param);
if (NULL == aiori_fh) { if (NULL == aiori_fh) {
FAIL("unable to open file %s", item); FAIL("unable to open file %s", item);
} }
@ -722,7 +715,7 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) {
/* read file */ /* read file */
if (read_bytes > 0) { 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 */ 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); FAIL("unable to read file %s", item);
} }
if(verify_read){ if(verify_read){
@ -734,7 +727,7 @@ void mdtest_read(int random, int dirs, const long dir_iter, char *path) {
} }
/* close file */ /* close file */
backend->close (aiori_fh, &param); backend->close (aiori_fh, backend_options);
} }
} }
@ -1489,7 +1482,7 @@ void show_file_system_size(char *file_system) {
VERBOSE(1,-1,"Entering show_file_system_size on %s", 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) { if (0 != ret) {
FAIL("unable to stat file system %s", file_system); FAIL("unable to stat file system %s", file_system);
} }
@ -1553,9 +1546,6 @@ void display_freespace(char *testdirpath)
strcpy(dirpath, "."); strcpy(dirpath, ".");
} }
if (param.api && strcasecmp(param.api, "DFS") == 0)
return;
VERBOSE(3,5,"Before show_file_system_size, dirpath is '%s'", dirpath ); VERBOSE(3,5,"Before show_file_system_size, dirpath is '%s'", dirpath );
show_file_system_size(dirpath); show_file_system_size(dirpath);
VERBOSE(3,5, "After show_file_system_size, dirpath is '%s'\n", dirpath ); VERBOSE(3,5, "After show_file_system_size, dirpath is '%s'\n", dirpath );
@ -1577,7 +1567,7 @@ void create_remove_directory_tree(int create,
if (create) { if (create) {
VERBOSE(2,5,"Making directory '%s'", dir); 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); fprintf(out_logfile, "error could not create directory '%s'\n", dir);
} }
#ifdef HAVE_LUSTRE_LUSTREAPI #ifdef HAVE_LUSTRE_LUSTREAPI
@ -1595,7 +1585,7 @@ void create_remove_directory_tree(int create,
if (!create) { if (!create) {
VERBOSE(2,5,"Remove directory '%s'", dir); 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); FAIL("Unable to remove directory %s", dir);
} }
} }
@ -1611,7 +1601,7 @@ void create_remove_directory_tree(int create,
if (create) { if (create) {
VERBOSE(2,5,"Making directory '%s'", temp_path); 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); FAIL("Unable to create directory %s", temp_path);
} }
} }
@ -1622,7 +1612,7 @@ void create_remove_directory_tree(int create,
if (!create) { if (!create) {
VERBOSE(2,5,"Remove directory '%s'", temp_path); 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); FAIL("Unable to remove directory %s", temp_path);
} }
} }
@ -1651,8 +1641,8 @@ static void mdtest_iteration(int i, int j, MPI_Group testgroup, mdtest_results_t
prep_testdir(j, dir_iter); prep_testdir(j, dir_iter);
VERBOSE(2,5,"main (for j loop): making testdir, '%s'", testdir ); VERBOSE(2,5,"main (for j loop): making testdir, '%s'", testdir );
if ((rank < path_count) && backend->access(testdir, F_OK, &param) != 0) { if ((rank < path_count) && backend->access(testdir, F_OK, backend_options) != 0) {
if (backend->mkdir(testdir, DIRMODE, &param) != 0) { if (backend->mkdir(testdir, DIRMODE, backend_options) != 0) {
FAIL("Unable to create test directory %s", testdir); FAIL("Unable to create test directory %s", testdir);
} }
#ifdef HAVE_LUSTRE_LUSTREAPI #ifdef HAVE_LUSTRE_LUSTREAPI
@ -1832,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 ++){ for (int dir_iter = 0; dir_iter < directory_loops; dir_iter ++){
prep_testdir(j, 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 (( 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); FAIL("unable to remove directory %s", testdir);
} }
} }
@ -1915,9 +1905,10 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
aiori_supported_apis(APIs, APIs_legacy, MDTEST); aiori_supported_apis(APIs, APIs_legacy, MDTEST);
char apiStr[1024]; char apiStr[1024];
sprintf(apiStr, "API for I/O [%s]", APIs); sprintf(apiStr, "API for I/O [%s]", APIs);
memset(& hints, 0, sizeof(hints));
option_help options [] = { 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}, {'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}, {'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}, {'B', NULL, "no barriers between phases", OPTION_OPTIONAL_ARGUMENT, 'd', & no_barriers},
@ -1962,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); options_all_t * global_options = airoi_create_all_module_options(options);
option_parse(argc, argv, global_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->modules);
free(global_options); free(global_options);
backend = param.backend;
MPI_Comm_rank(testComm, &rank); MPI_Comm_rank(testComm, &rank);
MPI_Comm_size(testComm, &size); MPI_Comm_size(testComm, &size);
if (backend->initialize) if (backend->initialize){
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(); pid = getpid();
uid = getuid(); uid = getuid();
@ -2012,7 +2012,7 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
valid_tests(); valid_tests();
// option_print_current(options); // 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, "barriers : %s", ( barriers ? "True" : "False" ));
VERBOSE(1,-1, "collective_creates : %s", ( collective_creates ? "True" : "False" )); VERBOSE(1,-1, "collective_creates : %s", ( collective_creates ? "True" : "False" ));
VERBOSE(1,-1, "create_only : %s", ( create_only ? "True" : "False" )); VERBOSE(1,-1, "create_only : %s", ( create_only ? "True" : "False" ));
@ -2144,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 directory does not exist, create it */
if ((rank < path_count) && backend->access(testdirpath, F_OK, &param) != 0) { if ((rank < path_count) && backend->access(testdirpath, F_OK, backend_options) != 0) {
if (backend->mkdir(testdirpath, DIRMODE, &param) != 0) { if (backend->mkdir(testdirpath, DIRMODE, backend_options) != 0) {
FAIL("Unable to create test directory path %s", testdirpath); FAIL("Unable to create test directory path %s", testdirpath);
} }
} }
@ -2263,8 +2263,9 @@ mdtest_results_t * mdtest_run(int argc, char **argv, MPI_Comm world_com, FILE *
free(rand_array); free(rand_array);
} }
if (backend->finalize) if (backend->finalize){
backend->finalize(); backend->finalize(backend_options);
}
return summary_table; return summary_table;
} }

View File

@ -23,10 +23,12 @@ typedef struct{
void * variable; void * variable;
} option_help; } option_help;
typedef struct aiori_mod_opt_t aiori_mod_opt_t;
typedef struct{ typedef struct{
char * prefix; // may be NULL to include it in the standard name char * prefix; // may be NULL to include it in the standard name
option_help * options; 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; } option_module;
typedef struct{ typedef struct{

View File

@ -32,8 +32,6 @@
#include "option.h" #include "option.h"
#include "aiori.h" #include "aiori.h"
#define ISPOWEROFTWO(x) ((x != 0) && !(x & (x - 1)))
IOR_param_t initialTestParams; IOR_param_t initialTestParams;
option_help * createGlobalOptions(IOR_param_t * params); option_help * createGlobalOptions(IOR_param_t * params);
@ -62,24 +60,6 @@ static void CheckRunSettings(IOR_test_t *tests)
params->readFile = TRUE; params->readFile = TRUE;
params->writeFile = TRUE; params->writeFile = TRUE;
} }
/* If only read or write is requested, then fix the default
* openFlags to not be open RDWR. It matters in the case
* of HDFS, which doesn't support opening RDWR.
* (We assume int-valued params are exclusively 0 or 1.)
*/
if ((params->openFlags & IOR_RDWR)
&& ((params->readFile | params->checkRead | params->checkWrite)
^ params->writeFile)) {
params->openFlags &= ~(IOR_RDWR);
if (params->readFile | params->checkRead) {
params->openFlags |= IOR_RDONLY;
params->openFlags &= ~(IOR_CREAT|IOR_EXCL);
}
else
params->openFlags |= IOR_WRONLY;
}
} }
} }
@ -137,8 +117,6 @@ void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_opt
params->platform = strdup(value); params->platform = strdup(value);
} else if (strcasecmp(option, "testfile") == 0) { } else if (strcasecmp(option, "testfile") == 0) {
params->testFileName = strdup(value); params->testFileName = strdup(value);
} else if (strcasecmp(option, "hintsfilename") == 0) {
params->hintsFileName = strdup(value);
} else if (strcasecmp(option, "deadlineforstonewalling") == 0) { } else if (strcasecmp(option, "deadlineforstonewalling") == 0) {
params->deadlineForStonewalling = atoi(value); params->deadlineForStonewalling = atoi(value);
} else if (strcasecmp(option, "stoneWallingWearOut") == 0) { } else if (strcasecmp(option, "stoneWallingWearOut") == 0) {
@ -199,34 +177,16 @@ void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_opt
params->blockSize = string_to_bytes(value); params->blockSize = string_to_bytes(value);
} else if (strcasecmp(option, "transfersize") == 0) { } else if (strcasecmp(option, "transfersize") == 0) {
params->transferSize = string_to_bytes(value); params->transferSize = string_to_bytes(value);
} else if (strcasecmp(option, "setalignment") == 0) {
params->setAlignment = string_to_bytes(value);
} else if (strcasecmp(option, "singlexferattempt") == 0) { } else if (strcasecmp(option, "singlexferattempt") == 0) {
params->singleXferAttempt = atoi(value); params->singleXferAttempt = atoi(value);
} else if (strcasecmp(option, "individualdatasets") == 0) {
params->individualDataSets = atoi(value);
} else if (strcasecmp(option, "intraTestBarriers") == 0) { } else if (strcasecmp(option, "intraTestBarriers") == 0) {
params->intraTestBarriers = atoi(value); params->intraTestBarriers = atoi(value);
} else if (strcasecmp(option, "nofill") == 0) {
params->noFill = atoi(value);
} else if (strcasecmp(option, "verbose") == 0) { } else if (strcasecmp(option, "verbose") == 0) {
params->verbose = atoi(value); params->verbose = atoi(value);
} else if (strcasecmp(option, "settimestampsignature") == 0) { } else if (strcasecmp(option, "settimestampsignature") == 0) {
params->setTimeStampSignature = atoi(value); 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) { } else if (strcasecmp(option, "storefileoffset") == 0) {
params->storeFileOffset = atoi(value); 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) { } else if (strcasecmp(option, "uniqueDir") == 0) {
params->uniqueDir = atoi(value); params->uniqueDir = atoi(value);
} else if (strcasecmp(option, "useexistingtestfile") == 0) { } else if (strcasecmp(option, "useexistingtestfile") == 0) {
@ -243,53 +203,6 @@ void DecodeDirective(char *line, IOR_param_t *params, options_all_t * module_opt
} else if (strcasecmp(option, "memoryPerNode") == 0) { } else if (strcasecmp(option, "memoryPerNode") == 0) {
params->memoryPerNode = NodeMemoryStringToBytes(value); params->memoryPerNode = NodeMemoryStringToBytes(value);
params->memoryPerTask = 0; 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) { } else if (strcasecmp(option, "summaryalways") == 0) {
params->summary_every_test = atoi(value); params->summary_every_test = atoi(value);
} else { } else {
@ -472,7 +385,7 @@ option_help * createGlobalOptions(IOR_param_t * params){
{'a', NULL, apiStr, OPTION_OPTIONAL_ARGUMENT, 's', & params->api}, {'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}, {'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}, {'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}, {'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, "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}, {'D', NULL, "deadlineForStonewalling -- seconds before stopping write or read phase", OPTION_OPTIONAL_ARGUMENT, 'd', & params->deadlineForStonewalling},
@ -489,34 +402,25 @@ option_help * createGlobalOptions(IOR_param_t * params){
* after all the arguments are in and we know which it keep. * 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}, {'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, "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, "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, "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}, {'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}, {'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, "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}, {'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}, {'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, "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}, {'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, "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}, {'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, "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}, {'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, "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, "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}, {'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, "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, "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, "writeFile -- write file", OPTION_FLAG, 'd', & params->writeFile},
{'W', NULL, "checkWrite -- check read after write", OPTION_FLAG, 'd', & params->checkWrite}, {'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}, {'x', NULL, "singleXferAttempt -- do not retry transfer if incomplete", OPTION_FLAG, 'd', & params->singleXferAttempt},

View File

@ -47,6 +47,7 @@
#include "utilities.h" #include "utilities.h"
#include "aiori.h" #include "aiori.h"
#include "ior.h" #include "ior.h"
#include "ior-internal.h"
/************************** D E C L A R A T I O N S ***************************/ /************************** 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); const ior_aiori_t * backend = aiori_select(options->api);
if (backend == NULL) if (backend == NULL)
ERR_SIMPLE("unrecognized I/O API"); ERR("Unrecognized I/O API");
options->backend = backend; options->backend = backend;
/* copy the actual module options into the test */ /* copy the actual module options into the test */
@ -565,91 +566,66 @@ IOR_offset_t StringToBytes(char *size_str)
/* /*
* Displays size of file system and percent of data blocks and inodes used. * Displays size of file system and percent of data blocks and inodes used.
*/ */
void ShowFileSystemSize(char *fileSystem) // this might be converted to an AIORI call void ShowFileSystemSize(IOR_param_t * test) // this might be converted to an AIORI call
{ {
#ifndef _WIN32 /* FIXME */ ior_aiori_statfs_t stat;
char realPath[PATH_MAX]; if(! test->backend->statfs){
char *fileSystemUnitStr; WARN("Backend doesn't implement statfs");
long long int totalFileSystemSize; return;
long long int freeFileSystemSize; }
long long int totalInodes; char filename[MAX_PATHLEN];
long long int freeInodes; GetTestFileName(filename, test);
double totalFileSystemSizeHR; int ret = test->backend->statfs(filename, & stat, test->backend_options);
double usedFileSystemPercentage; if( ret != 0 ){
double usedInodePercentage; WARN("Backend returned error during statfs");
#ifdef __sun /* SunOS does not support statfs(), instead uses statvfs() */ return;
struct statvfs statusBuffer; }
#else /* !__sun */ long long int totalFileSystemSize;
struct statfs statusBuffer; long long int freeFileSystemSize;
#endif /* __sun */ long long int totalInodes;
long long int freeInodes;
double totalFileSystemSizeHR;
double usedFileSystemPercentage;
double usedInodePercentage;
char *fileSystemUnitStr;
#ifdef __sun totalFileSystemSize = stat.f_blocks * stat.f_bsize;
if (statvfs(fileSystem, &statusBuffer) != 0) { freeFileSystemSize = stat.f_bfree * stat.f_bsize;
WARN("unable to statvfs() file system"); usedFileSystemPercentage = (1 - ((double)freeFileSystemSize / (double)totalFileSystemSize)) * 100;
return; totalFileSystemSizeHR = (double)totalFileSystemSize / (double)(1<<30);
}
#else /* !__sun */
if (statfs(fileSystem, &statusBuffer) != 0) {
WARN("unable to statfs() file system");
return;
}
#endif /* __sun */
/* data blocks */ /* inodes */
#ifdef __sun totalInodes = stat.f_files;
totalFileSystemSize = statusBuffer.f_blocks * statusBuffer.f_frsize; freeInodes = stat.f_ffree;
freeFileSystemSize = statusBuffer.f_bfree * statusBuffer.f_frsize; usedInodePercentage = (1 - ((double)freeInodes / (double)totalInodes)) * 100;
#else /* !__sun */
totalFileSystemSize = statusBuffer.f_blocks * statusBuffer.f_bsize;
freeFileSystemSize = statusBuffer.f_bfree * statusBuffer.f_bsize;
#endif /* __sun */
usedFileSystemPercentage = (1 - ((double)freeFileSystemSize fileSystemUnitStr = "GiB";
/ (double)totalFileSystemSize)) * 100; if (totalFileSystemSizeHR > 1024) {
totalFileSystemSizeHR = totalFileSystemSizeHR = (double)totalFileSystemSize / (double)((long long)1<<40);
(double)totalFileSystemSize / (double)(1<<30); fileSystemUnitStr = "TiB";
fileSystemUnitStr = "GiB"; }
if (totalFileSystemSizeHR > 1024) { if(outputFormat == OUTPUT_DEFAULT){
totalFileSystemSizeHR = (double)totalFileSystemSize / (double)((long long)1<<40); fprintf(out_resultfile, "%-20s: %s\n", "Path", filename);
fileSystemUnitStr = "TiB"; 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 */ return;
if (realpath(fileSystem, realPath) == NULL) {
WARN("unable to use realpath()");
return;
}
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;
} }
/* /*

View File

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