mdtest/src/aiori-DFS.c

563 lines
12 KiB
C
Executable File

/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
* vim:expandtab:shiftwidth=8:tabstop=8:
*/
/******************************************************************************\
* *
* Copyright (c) 2003, The Regents of the University of California *
* See the file COPYRIGHT for a complete copyright notice and license. *
* *
********************************************************************************
*
* Implement of abstract I/O interface for DFS.
*
\******************************************************************************/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <libgen.h>
#include <daos_types.h>
#include <daos_api.h>
#include <daos_fs.h>
#include "ior.h"
#include "aiori.h"
#include "iordef.h"
#include "utilities.h"
dfs_t *dfs;
static int
parse_filename(const char *path, char **_obj_name, char **_cont_name)
{
char *f1 = NULL;
char *f2 = NULL;
char *fname = NULL;
char *cont_name = NULL;
int rc = 0;
if (path == NULL || _obj_name == NULL || _cont_name == NULL)
return -EINVAL;
if (strcmp(path, "/") == 0) {
*_cont_name = strdup("/");
if (*_cont_name == NULL)
return -ENOMEM;
*_obj_name = NULL;
return 0;
}
f1 = strdup(path);
if (f1 == NULL)
D_GOTO(out, rc = -ENOMEM);
f2 = strdup(path);
if (f2 == NULL)
D_GOTO(out, rc = -ENOMEM);
fname = basename(f1);
cont_name = dirname(f2);
if (cont_name[0] == '.' || cont_name[0] != '/') {
char *cwd;
//getcwd(cwd, 1024);
cwd = strdup("/");
if (strcmp(cont_name, ".") == 0) {
cont_name = strdup(cwd);
if (cont_name == NULL)
D_GOTO(out, rc = -ENOMEM);
} else {
char *new_dir = calloc(strlen(cwd) + strlen(cont_name)
+ 1, sizeof(char));
if (new_dir == NULL)
D_GOTO(out, rc = -ENOMEM);
strcpy(new_dir, cwd);
if (cont_name[0] == '.') {
strcat(new_dir, &cont_name[1]);
} else {
strcat(new_dir, "/");
strcat(new_dir, cont_name);
}
cont_name = new_dir;
}
*_cont_name = cont_name;
} else {
*_cont_name = strdup(cont_name);
if (*_cont_name == NULL)
D_GOTO(out, rc = -ENOMEM);
}
*_obj_name = strdup(fname);
if (*_obj_name == NULL) {
free(*_cont_name);
*_cont_name = NULL;
D_GOTO(out, rc = -ENOMEM);
}
out:
if (f1)
free(f1);
if (f2)
free(f2);
return rc;
}
/**************************** P R O T O T Y P E S *****************************/
static void *DFS_Create(char *, IOR_param_t *);
static void *DFS_Open(char *, IOR_param_t *);
static IOR_offset_t DFS_Xfer(int, void *, IOR_size_t *,
IOR_offset_t, IOR_param_t *);
static void DFS_Close(void *, IOR_param_t *);
static void DFS_Delete(char *, IOR_param_t *);
static void DFS_SetVersion(IOR_param_t *);
static void DFS_Fsync(void *, IOR_param_t *);
static IOR_offset_t DFS_GetFileSize(IOR_param_t *, MPI_Comm, char *);
static int DFS_Statfs (const char *, ior_aiori_statfs_t *, IOR_param_t *);
static int DFS_Stat (const char *, struct stat *, IOR_param_t *);
static int DFS_Mkdir (const char *, mode_t, IOR_param_t *);
static int DFS_Rmdir (const char *, IOR_param_t *);
static int DFS_Access (const char *, int, IOR_param_t *);
/************************** D E C L A R A T I O N S ***************************/
ior_aiori_t dfs_aiori = {
.name = "DFS",
.create = DFS_Create,
.open = DFS_Open,
.xfer = DFS_Xfer,
.close = DFS_Close,
.delete = DFS_Delete,
.set_version = DFS_SetVersion,
.fsync = DFS_Fsync,
.get_file_size = DFS_GetFileSize,
.statfs = DFS_Statfs,
.mkdir = DFS_Mkdir,
.rmdir = DFS_Rmdir,
.access = DFS_Access,
.stat = DFS_Stat,
};
/***************************** F U N C T I O N S ******************************/
int
dfs_init(void) {
int rc;
rc = daos_init();
if (rc) {
fprintf(stderr, "daos_init() failed with %d\n", rc);
return rc;
}
rc = dfs_mount(&dfs);
if (rc) {
fprintf(stderr, "dfs_mount failed (%d)\n", rc);
return 1;
}
return rc;
}
int dfs_finalize(void)
{
dfs_umount(dfs);
daos_fini();
return 0;
}
/*
* Creat and open a file through the DFS interface.
*/
static void *
DFS_Create(char *testFileName, IOR_param_t *param)
{
char *name = NULL, *dir_name = NULL;
dfs_obj_t *obj = NULL, *parent = NULL;
mode_t pmode;
int fd_oflag = 0;
int rc;
fd_oflag |= O_CREAT | O_RDWR;
rc = parse_filename(testFileName, &name, &dir_name);
if (rc)
goto out;
assert(dir_name);
assert(name);
rc = dfs_lookup(dfs, dir_name, &parent, &pmode);
if (rc || !S_ISDIR(pmode))
goto out;
mode_t mode = S_IFREG | param->mode;
rc = dfs_open(dfs, parent, name, mode, fd_oflag, NULL, &obj);
if (rc)
goto out;
out:
if (name)
free(name);
if (dir_name)
free(dir_name);
if (parent)
dfs_release(parent);
return ((void *)obj);
}
/*
* Open a file through the DFS interface.
*/
static void *DFS_Open(char *testFileName, IOR_param_t *param)
{
char *name = NULL, *dir_name = NULL;
dfs_obj_t *obj = NULL, *parent = NULL;
mode_t pmode;
int rc;
int fd_oflag = 0;
fd_oflag |= O_RDWR;
rc = parse_filename(testFileName, &name, &dir_name);
if (rc)
goto out;
assert(dir_name);
assert(name);
rc = dfs_lookup(dfs, dir_name, &parent, &pmode);
if (rc || !S_ISDIR(pmode))
goto out;
rc = dfs_open(dfs, parent, name, S_IFREG, fd_oflag, NULL, &obj);
if (rc)
goto out;
out:
if (name)
free(name);
if (dir_name)
free(dir_name);
if (parent)
dfs_release(parent);
return ((void *)obj);
}
/*
* Write or read access to file using the DFS interface.
*/
static IOR_offset_t
DFS_Xfer(int access, void *file, IOR_size_t *buffer, IOR_offset_t length,
IOR_param_t *param)
{
int xferRetries = 0;
long long remaining = (long long)length;
char *ptr = (char *)buffer;
daos_size_t ret;
int rc;
dfs_obj_t *obj;
obj = (dfs_obj_t *)file;
while (remaining > 0) {
daos_iov_t iov;
daos_sg_list_t sgl;
/** set memory location */
sgl.sg_nr = 1;
sgl.sg_nr_out = 0;
daos_iov_set(&iov, (void *)ptr, remaining);
sgl.sg_iovs = &iov;
/* write/read file */
if (access == WRITE) {
rc = dfs_write(dfs, obj, sgl, param->offset);
if (rc)
ERR("write() failed");
ret = remaining;
} else {
rc = dfs_read(dfs, obj, sgl, param->offset, &ret);
if (rc || ret == 0)
ERR("read() failed");
}
if (ret < remaining) {
if (param->singleXferAttempt == TRUE)
MPI_CHECK(MPI_Abort(MPI_COMM_WORLD, -1),
"barrier error");
if (xferRetries > MAX_RETRY)
ERR("too many retries -- aborting");
}
assert(ret >= 0);
assert(ret <= remaining);
remaining -= ret;
ptr += ret;
xferRetries++;
}
return (length);
}
/*
* Perform fsync().
*/
static void DFS_Fsync(void *fd, IOR_param_t * param)
{
return;
}
/*
* Close a file through the DFS interface.
*/
static void DFS_Close(void *fd, IOR_param_t * param)
{
dfs_release((dfs_obj_t *)fd);
}
/*
* Delete a file through the DFS interface.
*/
static void DFS_Delete(char *testFileName, IOR_param_t * param)
{
char *name = NULL, *dir_name = NULL;
dfs_obj_t *parent = NULL;
mode_t pmode;
int rc;
rc = parse_filename(testFileName, &name, &dir_name);
if (rc)
goto out;
assert(dir_name);
assert(name);
rc = dfs_lookup(dfs, dir_name, &parent, &pmode);
if (rc || !S_ISDIR(pmode))
goto out;
rc = dfs_remove(dfs, parent, name);
if (rc)
goto out;
out:
if (name)
free(name);
if (dir_name)
free(dir_name);
if (parent)
dfs_release(parent);
}
/*
* Determine api version.
*/
static void DFS_SetVersion(IOR_param_t * test)
{
strcpy(test->apiVersion, test->api);
}
/*
* Use DFS stat() to return aggregate file size.
*/
static IOR_offset_t DFS_GetFileSize(IOR_param_t * test, MPI_Comm testComm,
char *testFileName)
{
dfs_obj_t *obj;
daos_size_t fsize, tmpMin, tmpMax, tmpSum;
int rc;
rc = dfs_lookup(dfs, testFileName, &obj, NULL);
if (rc)
return -1;
rc = dfs_get_size(dfs, obj, &fsize);
if (rc)
return -1;
dfs_release(obj);
if (test->filePerProc == TRUE) {
MPI_CHECK(MPI_Allreduce(&fsize, &tmpSum, 1,
MPI_LONG_LONG_INT, MPI_SUM, testComm),
"cannot total data moved");
fsize = tmpSum;
} else {
MPI_CHECK(MPI_Allreduce(&fsize, &tmpMin, 1,
MPI_LONG_LONG_INT, MPI_MIN, testComm),
"cannot total data moved");
MPI_CHECK(MPI_Allreduce(&fsize, &tmpMax, 1,
MPI_LONG_LONG_INT, MPI_MAX, testComm),
"cannot total data moved");
if (tmpMin != tmpMax) {
if (rank == 0) {
WARN("inconsistent file size by different tasks");
}
/* incorrect, but now consistent across tasks */
fsize = tmpMin;
}
}
return (fsize);
}
static int
DFS_Statfs(const char *path, ior_aiori_statfs_t *sfs, IOR_param_t * param)
{
return 0;
}
static int
DFS_Mkdir (const char *path, mode_t mode, IOR_param_t * param)
{
dfs_obj_t *parent = NULL;
mode_t pmode;
char *name = NULL, *dir_name = NULL;
int rc;
rc = parse_filename(path, &name, &dir_name);
if (rc)
return rc;
assert(dir_name);
assert(name);
rc = dfs_lookup(dfs, dir_name, &parent, &pmode);
if (rc || !S_ISDIR(pmode))
goto out;
rc = dfs_mkdir(dfs, parent, name, mode);
if (rc)
goto out;
out:
if (name)
free(name);
if (dir_name)
free(dir_name);
if (parent)
dfs_release(parent);
return rc;
}
static int
DFS_Rmdir (const char *path, IOR_param_t * param)
{
dfs_obj_t *parent = NULL;
mode_t pmode;
char *name = NULL, *dir_name = NULL;
int rc;
rc = parse_filename(path, &name, &dir_name);
if (rc)
return rc;
assert(dir_name);
assert(name);
rc = dfs_lookup(dfs, dir_name, &parent, &pmode);
if (rc || !S_ISDIR(pmode))
goto out;
rc = dfs_remove(dfs, parent, name);
if (rc)
goto out;
out:
if (name)
free(name);
if (dir_name)
free(dir_name);
if (parent)
dfs_release(parent);
return rc;
}
static int
DFS_Access (const char *path, int mode, IOR_param_t * param)
{
dfs_obj_t *parent = NULL;
mode_t pmode;
char *name = NULL, *dir_name = NULL;
struct stat stbuf;
int rc;
rc = parse_filename(path, &name, &dir_name);
if (rc)
return rc;
assert(dir_name);
assert(name);
rc = dfs_lookup(dfs, dir_name, &parent, &pmode);
if (rc || !S_ISDIR(pmode))
goto out;
if (strcmp(name, ".") == 0) {
free(name);
name = NULL;
}
rc = dfs_stat(dfs, parent, name, &stbuf);
if (rc) {
rc = -1;
errno = -ENOENT;
goto out;
}
out:
if (name)
free(name);
if (dir_name)
free(dir_name);
if (parent)
dfs_release(parent);
return rc;
}
static int
DFS_Stat (const char *path, struct stat *buf, IOR_param_t * param)
{
dfs_obj_t *parent = NULL;
mode_t pmode;
char *name = NULL, *dir_name = NULL;
int rc;
rc = parse_filename(path, &name, &dir_name);
if (rc)
return rc;
assert(dir_name);
assert(name);
rc = dfs_lookup(dfs, dir_name, &parent, &pmode);
if (rc || !S_ISDIR(pmode))
goto out;
rc = dfs_stat(dfs, parent, name, buf);
if (rc)
goto out;
out:
if (name)
free(name);
if (dir_name)
free(dir_name);
if (parent)
dfs_release(parent);
return rc;
}