23 # include <sys/ioctl.h> 35 #ifdef HAVE_LINUX_LUSTRE_LUSTRE_USER_H 36 # include <linux/lustre/lustre_user.h> 37 #elif defined(HAVE_LUSTRE_USER) 38 # include <lustre/lustre_user.h> 43 #ifdef HAVE_GPFS_FCNTL_H 44 # include <gpfs_fcntl.h> 47 #ifdef HAVE_BEEGFS_BEEGFS_H 48 #include <beegfs/beegfs.h> 60 #ifdef HAVE_GPU_DIRECT 61 typedef long long loff_t;
62 #include <cuda_runtime.h> 68 #ifdef HAVE_GPU_DIRECT 69 CUfileHandle_t cf_handle;
79 # define lseek64 lseek 86 #ifdef HAVE_GPU_DIRECT 87 static const char* cuFileGetErrorString(CUfileError_t status){
88 if(IS_CUDA_ERR(status)){
89 return cudaGetErrorString(status.err);
91 return strerror(status.err);
94 static void init_cufile(
posix_fd * pfd){
95 CUfileDescr_t cf_descr = (CUfileDescr_t){
97 .type = CU_FILE_HANDLE_TYPE_OPAQUE_FD
99 CUfileError_t status = cuFileHandleRegister(& pfd->cf_handle, & cf_descr);
100 if(status.err != CU_FILE_SUCCESS){
101 EWARNF(
"Could not register handle %s", cuFileGetErrorString(status));
116 if (init_values !=
NULL){
131 #ifdef HAVE_BEEGFS_BEEGFS_H 135 #ifdef HAVE_GPFS_FCNTL_H 140 #ifdef HAVE_LUSTRE_USER 146 #ifdef HAVE_GPU_DIRECT 152 memcpy(help, h,
sizeof(h));
182 .enable_mdtest =
true,
198 ERR(
"beegfsChunkSize must be a power of two and >64k");
202 ERR(
"GPUDirect required direct I/O to be used!");
204 #ifndef HAVE_GPU_DIRECT 206 ERR(
"GPUDirect support is not compiled");
212 #ifdef HAVE_GPFS_FCNTL_H 213 void gpfs_free_all_locks(
int fd)
217 gpfsFcntlHeader_t header;
218 gpfsFreeRange_t release;
220 release_all.header.totalLength =
sizeof(release_all);
221 release_all.header.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
222 release_all.header.fcntlReserved = 0;
224 release_all.release.structLen =
sizeof(release_all.release);
225 release_all.release.structType = GPFS_FREE_RANGE;
226 release_all.release.start = 0;
227 release_all.release.length = 0;
229 rc = gpfs_fcntl(fd, &release_all);
231 EWARNF(
"gpfs_fcntl(%d, ...) release all locks hint failed.", fd);
238 gpfsFcntlHeader_t header;
239 gpfsAccessRange_t access;
242 take_locks.header.totalLength =
sizeof(take_locks);
243 take_locks.header.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
244 take_locks.header.fcntlReserved = 0;
246 take_locks.access.structLen =
sizeof(take_locks.access);
247 take_locks.access.structType = GPFS_ACCESS_RANGE;
248 take_locks.access.start =
offset;
249 take_locks.access.length = length;
250 take_locks.access.isWrite = (access ==
WRITE);
252 rc = gpfs_fcntl(fd, &take_locks);
254 EWARNF(
"gpfs_fcntl(%d, ...) access range hint failed.", fd);
262 gpfsFcntlHeader_t header;
263 gpfsFreeRange_t free;
267 free_locks.header.totalLength =
sizeof(free_locks);
268 free_locks.header.fcntlVersion = GPFS_FCNTL_CURRENT_VERSION;
269 free_locks.header.fcntlReserved = 0;
271 free_locks.free.structLen =
sizeof(free_locks.free);
272 free_locks.free.structType = GPFS_FREE_RANGE;
273 free_locks.free.start =
offset;
274 free_locks.free.length = length;
276 rc = gpfs_fcntl(fd, &free_locks);
278 EWARNF(
"gpfs_fcntl(%d, ...) free range hint failed.", fd);
284 #ifdef HAVE_BEEGFS_BEEGFS_H 286 int mkTempInDir(
char* dirPath)
288 unsigned long len = strlen(dirPath) + 8;
289 char* tmpfilename = (
char*)malloc(
sizeof (
char)*len+1);
290 snprintf(tmpfilename, len,
"%s/XXXXXX", dirPath);
292 int fd = mkstemp(tmpfilename);
299 bool beegfs_getStriping(
char* dirPath, u_int16_t* numTargetsOut,
unsigned* chunkSizeOut)
303 int fd = mkTempInDir(dirPath);
305 unsigned stripePattern = 0;
306 retVal = beegfs_getStripeInfo(fd, &stripePattern, chunkSizeOut, numTargetsOut);
313 bool beegfs_isOptionSet(
int opt) {
317 bool beegfs_compatibleFileExists(
char* filepath,
int numTargets,
int chunkSize)
319 int fd = open(filepath, O_RDWR);
324 unsigned read_stripePattern = 0;
325 u_int16_t read_numTargets = 0;
326 int read_chunkSize = 0;
328 bool retVal = beegfs_getStripeInfo(fd, &read_stripePattern, &read_chunkSize, &read_numTargets);
332 return retVal && read_numTargets == numTargets && read_chunkSize == chunkSize;
338 bool beegfs_createFilePath(
char* filepath, mode_t mode,
int numTargets,
int chunkSize)
341 char* dirTmp = strdup(filepath);
342 char* dir = dirname(dirTmp);
343 DIR* parentDirS = opendir(dir);
345 ERRF(
"Failed to get directory: %s", dir);
349 int parentDirFd = dirfd(parentDirS);
352 ERRF(
"Failed to get directory descriptor: %s", dir);
356 bool isBeegfs = beegfs_testIsBeeGFS(parentDirFd);
359 WARN(
"Not a BeeGFS file system");
363 if ( !beegfs_isOptionSet(numTargets)
364 || !beegfs_isOptionSet(chunkSize)) {
365 u_int16_t defaultNumTargets = 0;
366 unsigned defaultChunkSize = 0;
367 bool haveDefaults = beegfs_getStriping(dir,
371 ERR(
"Failed to get default BeeGFS striping values");
373 numTargets = beegfs_isOptionSet(numTargets) ?
374 numTargets : defaultNumTargets;
375 chunkSize = beegfs_isOptionSet(chunkSize) ?
376 chunkSize : defaultChunkSize;
379 char* filenameTmp = strdup(filepath);
380 char* filename = basename(filepath);
381 bool isFileCreated = beegfs_compatibleFileExists(filepath, numTargets, chunkSize)
382 || beegfs_createFile(parentDirFd, filename,
383 mode, numTargets, chunkSize);
385 ERR(
"Could not create file");
390 closedir(parentDirS);
414 #ifdef HAVE_LUSTRE_USER 418 #define FASYNC 00020000 427 pfd->
fd =
open64(testFileName, fd_oflag, mode);
429 ERRF(
"open64(\"%s\", %d, %#o) failed. Error: %s",
430 testFileName, fd_oflag, mode, strerror(
errno));
433 struct lov_user_md opts = { 0 };
436 opts.lmm_magic = LOV_USER_MAGIC;
444 fd_oflag |= O_CREAT | O_EXCL | O_RDWR | O_LOV_DELAY_CREATE;
445 pfd->
fd =
open64(testFileName, fd_oflag, mode);
447 ERRF(
"Unable to open '%s': %s\n",
448 testFileName, strerror(
errno));
449 }
else if (ioctl(pfd->
fd, LL_IOC_LOV_SETSTRIPE, &opts)) {
450 char *errmsg =
"stripe already set";
452 errmsg = strerror(
errno);
453 ERRF(
"Error on ioctl for '%s' (%d): %s\n",
454 testFileName, pfd->
fd, errmsg);
463 fd_oflag |= O_CREAT | O_RDWR;
465 #ifdef HAVE_BEEGFS_BEEGFS_H 468 bool result = beegfs_createFilePath(testFileName,
473 fd_oflag &= ~O_CREAT;
475 EWARN(
"BeeGFS tuning failed");
480 pfd->
fd =
open64(testFileName, fd_oflag, mode);
482 ERRF(
"open64(\"%s\", %d, %#o) failed. Error: %s",
483 testFileName, fd_oflag, mode, strerror(
errno));
486 #ifdef HAVE_LUSTRE_USER 490 int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK;
491 if (ioctl(pfd->
fd, LL_IOC_SETFLAGS, &lustre_ioctl_flags) == -1)
492 ERRF(
"ioctl(%d, LL_IOC_SETFLAGS, ...) failed", pfd->
fd);
496 #ifdef HAVE_GPFS_FCNTL_H 501 gpfs_free_all_locks(pfd->
fd);
504 #ifdef HAVE_GPU_DIRECT 519 ret = mknod(testFileName, S_IFREG | S_IRUSR, 0);
541 pfd->
fd =
open64(testFileName, fd_oflag);
543 ERRF(
"open64(\"%s\", %d) failed: %s", testFileName, fd_oflag, strerror(
errno));
545 #ifdef HAVE_LUSTRE_USER 547 int lustre_ioctl_flags = LL_FILE_IGNORE_LOCK;
549 EINFO(
"** Disabling lustre range locking **\n");
551 if (ioctl(pfd->
fd, LL_IOC_SETFLAGS, &lustre_ioctl_flags) == -1)
552 ERRF(
"ioctl(%d, LL_IOC_SETFLAGS, ...) failed", pfd->
fd);
556 #ifdef HAVE_GPFS_FCNTL_H 558 gpfs_free_all_locks(pfd->
fd);
561 #ifdef HAVE_GPU_DIRECT 576 long long remaining = (
long long)length;
577 char *ptr = (
char *)buffer;
588 #ifdef HAVE_GPFS_FCNTL_H 590 gpfs_access_start(fd, length, offset, access);
596 if (
lseek64(fd, offset, SEEK_SET) == -1)
597 ERRF(
"lseek64(%d, %lld, SEEK_SET) failed", fd, offset);
598 off_t mem_offset = 0;
599 while (remaining > 0) {
601 if (access ==
WRITE) {
603 EINFO(
"task %d writing to offset %lld\n",
605 offset + length - remaining);
607 #ifdef HAVE_GPU_DIRECT 609 rc = cuFileWrite(pfd->cf_handle, ptr, remaining, offset + mem_offset, mem_offset);
612 rc = write(fd, ptr, remaining);
613 #ifdef HAVE_GPU_DIRECT 617 ERRF(
"write(%d, %p, %lld) failed",
618 fd, (
void*)ptr, remaining);
624 EINFO(
"task %d reading from offset %lld\n",
626 offset + length - remaining);
628 #ifdef HAVE_GPU_DIRECT 630 rc = cuFileRead(pfd->cf_handle, ptr, remaining, offset + mem_offset, mem_offset);
633 rc = read(fd, ptr, remaining);
634 #ifdef HAVE_GPU_DIRECT 638 ERRF(
"read(%d, %p, %lld) returned EOF prematurely",
639 fd, (
void*)ptr, remaining);
641 ERRF(
"read(%d, %p, %lld) failed",
642 fd, (
void*)ptr, remaining);
644 if (rc < remaining) {
645 EWARNF(
"task %d, partial %s, %lld of %lld bytes at offset %lld\n",
647 access ==
WRITE ?
"write()" :
"read()",
649 offset + length - remaining);
651 ERR(
"too many retries -- aborting");
654 assert(rc <= remaining);
660 #ifdef HAVE_GPFS_FCNTL_H 662 gpfs_access_end(fd, length, offset, access);
672 EWARNF(
"fsync(%d) failed", fd);
678 int ret = system(
"sync");
680 FAIL(
"Error executing the sync command, ensure it exists.");
694 #ifdef HAVE_GPU_DIRECT 696 cuFileHandleDeregister(((
posix_fd*) afd)->cf_handle);
700 ERRF(
"close(%d) failed", fd);
712 if (unlink(testFileName) != 0){
713 EWARNF(
"[RANK %03d]: unlink() of file \"%s\" failed",
rank, testFileName);
721 if(rename(oldfile, newfile) != 0){
722 EWARNF(
"[RANK %03d]: rename() of file \"%s\" to \"%s\" failed",
rank, oldfile, newfile);
735 struct stat stat_buf;
736 IOR_offset_t aggFileSizeFromStat, tmpMin, tmpMax, tmpSum;
738 if (stat(testFileName, &stat_buf) != 0) {
739 ERRF(
"stat(\"%s\", ...) failed", testFileName);
741 aggFileSizeFromStat = stat_buf.st_size;
743 return (aggFileSizeFromStat);
747 #ifdef HAVE_GPU_DIRECT 748 CUfileError_t err = cuFileDriverOpen();
753 #ifdef HAVE_GPU_DIRECT 754 CUfileError_t err = cuFileDriverClose();
static void POSIX_Finalize(aiori_mod_opt_t *options)
struct benchmark_options o
int POSIX_Mknod(char *testFileName)
static IOR_offset_t POSIX_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *)
static void POSIX_Initialize(aiori_mod_opt_t *options)
#define EINFO(FORMAT,...)
void POSIX_Close(aiori_fd_t *afd, aiori_mod_opt_t *param)
int POSIX_Rename(const char *oldfile, const char *newfile, aiori_mod_opt_t *module_options)
#define MPI_CHECK(MPI_STATUS, MSG)
int aiori_posix_stat(const char *path, struct stat *buf, aiori_mod_opt_t *module_options)
aiori_fd_t * POSIX_Open(char *testFileName, int flags, aiori_mod_opt_t *param)
char * aiori_get_version()
aiori_fd_t * POSIX_Create(char *testFileName, int flags, aiori_mod_opt_t *param)
static option_help options[]
void POSIX_Delete(char *testFileName, aiori_mod_opt_t *param)
static aiori_xfer_hint_t * hints
void POSIX_Sync(aiori_mod_opt_t *param)
int POSIX_check_params(aiori_mod_opt_t *param)
#define EWARNF(FORMAT,...)
int aiori_posix_access(const char *path, int mode, aiori_mod_opt_t *module_options)
int aiori_posix_rmdir(const char *path, aiori_mod_opt_t *module_options)
void POSIX_Fsync(aiori_fd_t *afd, aiori_mod_opt_t *param)
void POSIX_xfer_hints(aiori_xfer_hint_t *params)
int aiori_posix_mkdir(const char *path, mode_t mode, aiori_mod_opt_t *module_options)
int aiori_posix_statfs(const char *path, ior_aiori_statfs_t *stat_buf, aiori_mod_opt_t *module_options)
void set_o_direct_flag(int *flag)
option_help * POSIX_options(aiori_mod_opt_t **init_backend_options, aiori_mod_opt_t *init_values)
long long int IOR_offset_t
IOR_offset_t POSIX_GetFileSize(aiori_mod_opt_t *test, char *testFileName)
void * safeMalloc(uint64_t size)