diff --git a/client/src/Makefile.am b/client/src/Makefile.am index ac4573ee3..d39dcee23 100644 --- a/client/src/Makefile.am +++ b/client/src/Makefile.am @@ -13,6 +13,10 @@ if USE_PMPI_WRAPPERS lib_LTLIBRARIES += libunifyfs_mpi_gotcha.la endif #USE_PMPI_WRAPPERS +if ENABLE_LD_PRELOAD +lib_LTLIBRARIES += libunifyfs_preload_gotcha.la +endif #ENABLE_LD_PRELOAD + if HAVE_FORTRAN lib_LTLIBRARIES += libunifyfsf.la endif #HAVE_FORTRAN @@ -96,6 +100,8 @@ PMPI_SRC_FILES = \ pmpi_wrappers.c \ pmpi_wrappers.h +PRELOAD_SRC_FILES = \ + preload.c # Per-target flags begin here @@ -137,6 +143,14 @@ libunifyfs_gotcha_la_SOURCES = \ $(POSIX_CLIENT_SRC_FILES) \ gotcha_map_unifyfs_list.c +if ENABLE_LD_PRELOAD +libunifyfs_preload_gotcha_la_CPPFLAGS = $(CLIENT_COMMON_CPPFLAGS) +libunifyfs_preload_gotcha_la_CFLAGS = $(CLIENT_COMMON_CFLAGS) +libunifyfs_preload_gotcha_la_LDFLAGS = $(CLIENT_COMMON_LDFLAGS) +libunifyfs_preload_gotcha_la_LIBADD = libunifyfs_gotcha.la +libunifyfs_preload_gotcha_la_SOURCES = $(PRELOAD_SRC_FILES) +endif #ENABLE_LD_PRELOAD + if USE_PMPI_WRAPPERS libunifyfs_mpi_gotcha_la_CPPFLAGS = $(CLIENT_COMMON_CPPFLAGS) libunifyfs_mpi_gotcha_la_CFLAGS = $(CLIENT_COMMON_CFLAGS) diff --git a/client/src/gotcha_map_unifyfs_list.c b/client/src/gotcha_map_unifyfs_list.c index 690f0be86..44a34831f 100644 --- a/client/src/gotcha_map_unifyfs_list.c +++ b/client/src/gotcha_map_unifyfs_list.c @@ -61,6 +61,13 @@ UNIFYFS_DEF(unlink, int, UNIFYFS_DEF(remove, int, (const char* path), (path)) +UNIFYFS_DEF(utimensat, int, + (int dirfd, const char* pathname, const struct timespec times[2], + int flags), + (dirfd, pathname, times, flags)) +UNIFYFS_DEF(futimens, int, + (int fd, const struct timespec times[2]), + (fd, times)) UNIFYFS_DEF(stat, int, (const char* path, struct stat* buf), @@ -144,6 +151,12 @@ UNIFYFS_DEF(pwrite64, ssize_t, UNIFYFS_DEF(close, int, (int fd), (fd)) +UNIFYFS_DEF(dup, int, + (int fd), + (fd)) +UNIFYFS_DEF(dup2, int, + (int fd, int desired_fd), + (fd, desired_fd)) UNIFYFS_DEF(fchdir, int, (int fd), (fd)) @@ -349,6 +362,8 @@ struct gotcha_binding_t unifyfs_wrappers[] = { { "truncate", UNIFYFS_WRAP(truncate), &wrappee_handle_truncate }, { "unlink", UNIFYFS_WRAP(unlink), &wrappee_handle_unlink }, { "remove", UNIFYFS_WRAP(remove), &wrappee_handle_remove }, + { "utimensat", UNIFYFS_WRAP(utimensat), &wrappee_handle_utimensat }, + { "futimens", UNIFYFS_WRAP(futimens), &wrappee_handle_futimens }, { "stat", UNIFYFS_WRAP(stat), &wrappee_handle_stat }, { "fstat", UNIFYFS_WRAP(fstat), &wrappee_handle_fstat }, { "__xstat", UNIFYFS_WRAP(__xstat), &wrappee_handle___xstat }, @@ -386,6 +401,8 @@ struct gotcha_binding_t unifyfs_wrappers[] = { { "munmap", UNIFYFS_WRAP(munmap), &wrappee_handle_munmap }, { "mmap64", UNIFYFS_WRAP(mmap64), &wrappee_handle_mmap64 }, { "close", UNIFYFS_WRAP(close), &wrappee_handle_close }, + { "dup", UNIFYFS_WRAP(dup), &wrappee_handle_dup }, + { "dup2", UNIFYFS_WRAP(dup2), &wrappee_handle_dup2 }, { "opendir", UNIFYFS_WRAP(opendir), &wrappee_handle_opendir }, { "fdopendir", UNIFYFS_WRAP(fdopendir), &wrappee_handle_fdopendir }, { "closedir", UNIFYFS_WRAP(closedir), &wrappee_handle_closedir }, diff --git a/client/src/posix_client.c b/client/src/posix_client.c index d17840cac..59afa171c 100644 --- a/client/src/posix_client.c +++ b/client/src/posix_client.c @@ -43,6 +43,11 @@ int unifyfs_fpos_enabled = 1; unifyfs_fd_t unifyfs_fds[UNIFYFS_CLIENT_MAX_FILES]; rlim_t unifyfs_fd_limit; +/* dup/dup2() support - given a regular fd with a value up to + * UNIFYFS_CLIENT_MAX_FILES, the array holds the index of the + * corresponding entry in unifyfs_fds[] */ +int unifyfs_dup_fds[UNIFYFS_CLIENT_MAX_FILES]; + /* array of file streams */ unifyfs_stream_t unifyfs_streams[UNIFYFS_CLIENT_MAX_FILES]; @@ -263,6 +268,7 @@ int unifyfs_intercept_path(const char* path, char* upath) * convert fd to new fd value if needed */ int unifyfs_intercept_fd(int* fd) { + int newfd; int oldfd = *fd; /* don't intercept anything until we're initialized */ @@ -270,16 +276,27 @@ int unifyfs_intercept_fd(int* fd) return 0; } - if (oldfd < unifyfs_fd_limit) { - /* this fd is a real system fd, so leave it as is */ - return 0; - } else if (oldfd < 0) { + if (oldfd < 0) { /* this is an invalid fd, so we should not intercept it */ return 0; - } else { + } else if (oldfd < unifyfs_fd_limit) { + /* check if it has a valid entry in unifyfs_dup_fds[] */ + if (oldfd < UNIFYFS_CLIENT_MAX_FILES) { + newfd = unifyfs_dup_fds[oldfd]; + if (-1 != newfd) { + *fd = newfd; + LOGDBG("Changing fd from exposed dup2=%d to internal %d", + oldfd, newfd); + return 1; + } + } + + /* this fd is a real system fd, so leave it as is */ + return 0; + } else { /* >= unifyfs_fd_limit */ /* this is an fd we generated and returned to the user, * so intercept the call and shift the fd */ - int newfd = oldfd - unifyfs_fd_limit; + newfd = oldfd - unifyfs_fd_limit; *fd = newfd; LOGDBG("Changing fd from exposed %d to internal %d", oldfd, newfd); return 1; @@ -338,11 +355,19 @@ int unifyfs_fd_init(int fd) /* set fid to -1 to indicate fd is not active, * set file position to max value, * disable read and write flags */ - filedesc->fid = -1; - filedesc->pos = (off_t) -1; - filedesc->read = 0; + filedesc->fid = -1; + filedesc->pos = (off_t) -1; + filedesc->read = 0; filedesc->write = 0; + filedesc->use_count = 0; + + return UNIFYFS_SUCCESS; +} +/* initialize duped internal fd for given array index */ +int unifyfs_dup_fd_init(int fd) +{ + unifyfs_dup_fds[fd] = -1; return UNIFYFS_SUCCESS; } @@ -482,6 +507,7 @@ int posix_client_init(void) int num_fds = UNIFYFS_CLIENT_MAX_FILES; for (i = 0; i < num_fds; i++) { unifyfs_fd_init(i); + unifyfs_dup_fd_init(i); } /* initialize file stream structures */ diff --git a/client/src/posix_client.h b/client/src/posix_client.h index c510f1498..4c492db40 100644 --- a/client/src/posix_client.h +++ b/client/src/posix_client.h @@ -25,11 +25,12 @@ /* structure to represent file descriptors */ typedef struct { - int fid; /* local file id associated with fd */ - off_t pos; /* current file pointer */ - int read; /* whether file is opened for read */ - int write; /* whether file is opened for write */ - int append; /* whether file is opened for append */ + off_t pos; /* current file pointer */ + int read; /* whether file is opened for read */ + int write; /* whether file is opened for write */ + int append; /* whether file is opened for append */ + int fid; /* local file id associated with fd */ + int use_count; /* how many exposed fds refer to this */ } unifyfs_fd_t; enum unifyfs_stream_orientation { @@ -100,7 +101,8 @@ extern int unifyfs_mount_id; /* gfid of mountpoint */ /* whether we can use fgetpos/fsetpos */ extern int unifyfs_fpos_enabled; -/* array of file descriptors */ +/* arrays of file descriptors */ +extern int unifyfs_dup_fds[UNIFYFS_CLIENT_MAX_FILES]; extern unifyfs_fd_t unifyfs_fds[UNIFYFS_CLIENT_MAX_FILES]; extern rlim_t unifyfs_fd_limit; @@ -175,6 +177,9 @@ int unifyfs_get_fid_from_fd(int fd); /* initialze file descriptor structure corresponding to fd value */ int unifyfs_fd_init(int fd); +/* initialize unifyfs_dup_fds[] entry corresponding to fd value */ +int unifyfs_dup_fd_init(int fd); + /* initialze file stream structure corresponding to id value */ int unifyfs_stream_init(int sid); diff --git a/client/src/preload.c b/client/src/preload.c new file mode 100644 index 000000000..9a43c41e8 --- /dev/null +++ b/client/src/preload.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2022, Lawrence Livermore National Security, LLC. + * Produced at the Lawrence Livermore National Laboratory. + * + * Copyright 2022, UT-Battelle, LLC. + * + * LLNL-CODE-741539 + * All rights reserved. + * + * This is the license for UnifyFS. + * For details, see https://github.com/LLNL/UnifyFS. + * Please read https://github.com/LLNL/UnifyFS/LICENSE for full license text. + */ + +#include +#include +#include + +#include "unifyfs.h" +#include "unifyfs_rc.h" + +static int preload_initialized; // = 0 + +void unifyfs_preload_init(void) __attribute__ ((constructor)); +void unifyfs_preload_fini(void) __attribute__ ((destructor)); + +static void unifyfs_preload_mount(void) +{ + if (preload_initialized) { + return; + } + + char* mountpoint = getenv("UNIFYFS_PRELOAD_MOUNTPOINT"); + if (NULL == mountpoint) { + mountpoint = strdup("/unifyfs"); + } + + int rank = 0; + int world_sz = 1; + int rc = unifyfs_mount(mountpoint, rank, (size_t)world_sz); + if (UNIFYFS_SUCCESS != rc) { + fprintf(stderr, + "UNIFYFS ERROR: unifyfs_mount(%s) failed with '%s'\n", + mountpoint, unifyfs_rc_enum_description((unifyfs_rc)rc)); + } else { + fprintf(stderr, "DEBUG: mounted\n"); + preload_initialized = 1; + } +} + +static void unifyfs_preload_unmount(void) +{ + if (preload_initialized) { + int rc = unifyfs_unmount(); + if (UNIFYFS_SUCCESS != rc) { + fprintf(stderr, + "UNIFYFS ERROR: unifyfs_unmount() failed with '%s'\n", + unifyfs_rc_enum_description((unifyfs_rc)rc)); + } + fprintf(stderr, "DEBUG: unmounted\n"); + preload_initialized = 0; + } +} + +void unifyfs_preload_init(void) +{ + unifyfs_preload_mount(); + fflush(NULL); +} + +void unifyfs_preload_fini(void) +{ + unifyfs_preload_unmount(); + fflush(NULL); +} diff --git a/client/src/unifyfs-sysio.c b/client/src/unifyfs-sysio.c index dbf2f1bfc..96805721c 100644 --- a/client/src/unifyfs-sysio.c +++ b/client/src/unifyfs-sysio.c @@ -1139,11 +1139,11 @@ static int posix_create(char* upath, mode_t mode) filedesc->pos = pos; filedesc->read = 0; filedesc->write = 1; - + filedesc->use_count = 1; /* don't conflict with active system fds that range from 0 - (fd_limit) */ int ret = fd + unifyfs_fd_limit; - LOGDBG("using fds (internal=%d, external=%d) for fid %d file %s", + LOGDBG("using fds (internal=%d, exposed=%d) for fid %d file %s", fd, ret, fid, upath); errno = 0; return ret; @@ -1229,10 +1229,11 @@ int UNIFYFS_WRAP(open)(const char* path, int flags, ...) filedesc->write = ((flags & O_WRONLY) == O_WRONLY) || ((flags & O_RDWR) == O_RDWR); filedesc->append = (flags & O_APPEND); + filedesc->use_count = 1; /* don't conflict with active system fds that range from 0 - (fd_limit) */ ret = fd + unifyfs_fd_limit; - LOGDBG("using fds (internal=%d, external=%d) for fid %d file %s", + LOGDBG("using fds (internal=%d, exposed=%d) for fid %d file %s", fd, ret, fid, upath); errno = 0; return ret; @@ -1320,6 +1321,127 @@ int UNIFYFS_WRAP(__open_2)(const char* path, int flags, ...) return ret; } +int UNIFYFS_WRAP(dup)(int fd) +{ + int err = 0; + int ret; + + LOGDBG("fd=%d", fd); + + /* check whether we should intercept this file descriptor */ + int oldfd = fd; + if (unifyfs_intercept_fd(&fd)) { + /* dup() is expected to return an unused file descriptor nearest to 0, + * approximate that by calling socket(), which should be assigned the + * same fd value */ + + /* get file descriptor for this file */ + unifyfs_fd_t* fdesc = unifyfs_get_filedesc_from_fd(fd); + if (fdesc == NULL) { + errno = EBADF; + return -1; + } + + errno = 0; + int newfd = socket(PF_LOCAL, SOCK_DGRAM, 0); + err = errno; + if (-1 != newfd) { + int duped_fd = unifyfs_dup_fds[newfd]; + if (-1 == duped_fd) { + /* slot is available, set it to our internal fd index */ + unifyfs_dup_fds[newfd] = fd; + LOGDBG("assigned new fd=%d to old=%d", newfd, oldfd); + fdesc->use_count++; + + err = 0; + ret = newfd; + } else { + LOGWARN("dup_fds[newfd=%d] slot already in use (internal=%d)", + newfd, duped_fd); + /* close socket */ + MAP_OR_FAIL(close); + UNIFYFS_REAL(close)(newfd); + err = EMFILE; + ret = -1; + } + } else { + LOGERR("failed to get an unused system fd - %s", strerror(err)); + ret = -1; + } + } else { + MAP_OR_FAIL(dup); + errno = 0; + ret = UNIFYFS_REAL(dup)(fd); + err = errno; + } + + errno = err; + return ret; +} + +int UNIFYFS_WRAP(dup2)(int fd, int desired_fd) +{ + int err = 0; + int ret; + + LOGDBG("fd=%d, desired_fd=%d", fd, desired_fd); + + if (fd == desired_fd) { + errno = 0; + return desired_fd; + } + + /* check whether we should intercept this file descriptor */ + int oldfd = fd; + if (unifyfs_intercept_fd(&fd)) { + /* dup2() is expected to return the desired file descriptor, closing it + * if it's currently open. */ + + /* get file descriptor for this file */ + unifyfs_fd_t* fdesc = unifyfs_get_filedesc_from_fd(fd); + if (fdesc == NULL) { + errno = EBADF; + return -1; + } + + MAP_OR_FAIL(close); + errno = 0; + ret = UNIFYFS_REAL(close)(desired_fd); + err = errno; + if (err && (err != EBADF)) { + /* dup2() returns -1 with errno=EIO if close(desired_fd) fails. + * EBADF just means that desired_fd wasn't open, which is OK */ + err = EIO; + ret = -1; + } else { + int newfd = desired_fd; + int duped_fd = unifyfs_dup_fds[newfd]; + if (-1 == duped_fd) { + /* slot is available, set it to our internal fd index */ + unifyfs_dup_fds[newfd] = fd; + LOGDBG("assigned new fd=%d to old=%d", newfd, oldfd); + fdesc->use_count++; + + err = 0; + ret = newfd; + } else { + LOGWARN("dup_fds[newfd=%d] slot already in use (internal=%d)", + newfd, duped_fd); + err = EMFILE; + ret = -1; + } + } + } else { + MAP_OR_FAIL(dup2); + errno = 0; + ret = UNIFYFS_REAL(dup2)(fd, desired_fd); + err = errno; + } + + errno = err; + return ret; +} + off_t UNIFYFS_WRAP(lseek)(int fd, off_t offset, int whence) { /* check whether we should intercept this file descriptor */ @@ -2160,8 +2282,33 @@ void* UNIFYFS_WRAP(mmap64)(void* addr, size_t length, int prot, int flags, int UNIFYFS_WRAP(close)(int fd) { /* check whether we should intercept this file descriptor */ + int oldfd = fd; if (unifyfs_intercept_fd(&fd)) { - LOGDBG("closing fd %d", fd); + LOGDBG("closing (internal=%d, exposed=%d)", fd, oldfd); + + /* get file descriptor for this file */ + unifyfs_fd_t* fdesc = unifyfs_get_filedesc_from_fd(fd); + if (fdesc == NULL) { + errno = EBADF; + return -1; + } + fdesc->use_count--; + + if ((oldfd < UNIFYFS_CLIENT_MAX_FILES) && + (fd == unifyfs_dup_fds[oldfd])) { + LOGDBG("closing duped fd=%d", oldfd); + /* if oldfd is a socket created in dup() wrapper, close it */ + int type_val; + socklen_t type_len = sizeof(type_val); + errno = 0; + int rc = getsockopt(oldfd, SOL_SOCKET, SO_TYPE, + (void*)&type_val, &type_len); + if (rc == 0) { + MAP_OR_FAIL(close); + UNIFYFS_REAL(close)(oldfd); + } + unifyfs_dup_fds[oldfd] = -1; + } /* TODO: what to do if underlying file has been deleted? */ @@ -2172,15 +2319,9 @@ int UNIFYFS_WRAP(close)(int fd) return -1; } - /* get file descriptor for this file */ - unifyfs_fd_t* filedesc = unifyfs_get_filedesc_from_fd(fd); - if (filedesc == NULL) { - errno = EBADF; - return -1; - } - /* if file was opened for writing, sync it */ - if (filedesc->write) { + if (fdesc->write) { + LOGDBG("syncing fid=%d", fid); int sync_rc = unifyfs_fid_sync_extents(posix_client, fid); if (sync_rc != UNIFYFS_SUCCESS) { errno = unifyfs_rc_errno(sync_rc); @@ -2188,20 +2329,23 @@ int UNIFYFS_WRAP(close)(int fd) } } - /* close the file id */ - int close_rc = unifyfs_fid_close(posix_client, fid); - if (close_rc != UNIFYFS_SUCCESS) { - errno = unifyfs_rc_errno(close_rc); - return -1; - } + if (0 == fdesc->use_count) { + /* close the file id */ + LOGDBG("closing fid=%d", fid); + int close_rc = unifyfs_fid_close(posix_client, fid); + if (close_rc != UNIFYFS_SUCCESS) { + errno = unifyfs_rc_errno(close_rc); + return -1; + } - /* reinitialize file descriptor to indicate that - * it is no longer associated with a file, - * not technically needed but may help catch bugs */ - unifyfs_fd_init(fd); + /* reinitialize file descriptor to indicate that + * it is no longer associated with a file, + * not technically needed but may help catch bugs */ + unifyfs_fd_init(fd); - /* add file descriptor back to free stack */ - unifyfs_stack_push(posix_fd_stack, fd); + /* add file descriptor back to free stack */ + unifyfs_stack_push(posix_fd_stack, fd); + } errno = 0; return 0; @@ -2334,3 +2478,113 @@ int UNIFYFS_WRAP(chmod)(const char* path, mode_t mode) return ret; } } + +int UNIFYFS_WRAP(utimensat)(int dirfd, const char* pathname, + const struct timespec times[2], int flags) +{ + /* determine whether we should intercept this path */ + char upath[UNIFYFS_MAX_FILENAME]; + if (pathname == NULL) { + /* check whether we should intercept this file descriptor */ + if (unifyfs_intercept_fd(&dirfd)) { + /* TODO: what to do if underlying file has been deleted? */ + + /* check that fd is actually in use */ + int fid = unifyfs_get_fid_from_fd(dirfd); + if (fid < 0) { + errno = EBADF; + return -1; + } + + fprintf(stderr, "Function not yet supported @ %s:%d\n", + __FILE__, __LINE__); + errno = ENOSYS; + return -1; + } else { + MAP_OR_FAIL(utimensat); + int ret = UNIFYFS_REAL(utimensat)(dirfd, pathname, times, flags); + return ret; + } + } else { + if (unifyfs_intercept_path(pathname, upath)) { + /* check if path exists */ + int fid = unifyfs_fid_from_path(posix_client, upath); + if (fid < 0) { + LOGDBG("utimensat: unifyfs_get_id_from path failed," + " returning -1, %s", upath); + errno = ENOENT; + return -1; + } + + fprintf(stderr, "Function not yet supported @ %s:%d\n", + __FILE__, __LINE__); + errno = ENOSYS; + return -1; + } else { + MAP_OR_FAIL(utimensat); + int ret = UNIFYFS_REAL(utimensat)(dirfd, pathname, times, flags); + return ret; + } + } +} + +int UNIFYFS_WRAP(futimens)(int fd, const struct timespec times[2]) +{ + /* check whether we should intercept this file descriptor */ + if (unifyfs_intercept_fd(&fd)) { + /* TODO: what to do if underlying file has been deleted? */ + + /* check that fd is actually in use */ + int fid = unifyfs_get_fid_from_fd(fd); + if (fid < 0) { + errno = EBADF; + return -1; + } + + /* lookup meta to update timestamp fields */ + unifyfs_filemeta_t* meta = unifyfs_get_meta_from_fid(posix_client, + fid); + if (meta == NULL) { + /* bad file descriptor */ + errno = EBADF; + return -1; + } + + if (times[0].tv_nsec != UTIME_OMIT) { + if (times[0].tv_nsec == UTIME_NOW) { + /* use current time */ + struct timespec tp = {0}; + clock_gettime(CLOCK_REALTIME, &tp); + meta->attrs.atime = tp; + } else { + meta->attrs.atime = times[0]; + } + } + if (times[1].tv_nsec != UTIME_OMIT) { + if (times[1].tv_nsec == UTIME_NOW) { + /* use current time */ + struct timespec tp = {0}; + clock_gettime(CLOCK_REALTIME, &tp); + meta->attrs.mtime = tp; + } else { + meta->attrs.mtime = times[1]; + } + } + + /* update the global meta data to reflect new permissions */ + unifyfs_file_attr_op_e op = UNIFYFS_FILE_ATTR_OP_UTIME; + int ret = unifyfs_set_global_file_meta_from_fid(posix_client, fid, op); + if (ret) { + //LOGERR("futimens: can't set global meta entry for %s (fid:%d)", + // path, fid); + errno = unifyfs_rc_errno(ret); + return -1; + } + + return 0; + } else { + MAP_OR_FAIL(futimens); + int ret = UNIFYFS_REAL(futimens)(fd, times); + return ret; + } +} diff --git a/client/src/unifyfs-sysio.h b/client/src/unifyfs-sysio.h index 1a9afa8e6..cc4174684 100644 --- a/client/src/unifyfs-sysio.h +++ b/client/src/unifyfs-sysio.h @@ -55,38 +55,55 @@ * POSIX wrappers: paths * --------------------------------------- */ +/* file and directory operations */ UNIFYFS_DECL(access, int, (const char* pathname, int mode)); -UNIFYFS_DECL(mkdir, int, (const char* path, mode_t mode)); -UNIFYFS_DECL(rmdir, int, (const char* path)); -UNIFYFS_DECL(chdir, int, (const char* path)); UNIFYFS_DECL(chmod, int, (const char* path, mode_t mode)); -UNIFYFS_DECL(__getcwd_chk, char*, (char* path, size_t, size_t)); -UNIFYFS_DECL(getcwd, char*, (char* path, size_t)); -UNIFYFS_DECL(getwd, char*, (char* path)); -UNIFYFS_DECL(get_current_dir_name, char*, (void)); -UNIFYFS_DECL(unlink, int, (const char* path)); +UNIFYFS_DECL(__lxstat, int, (int vers, const char* path, struct stat* buf)); UNIFYFS_DECL(remove, int, (const char* path)); UNIFYFS_DECL(rename, int, (const char* oldpath, const char* newpath)); -UNIFYFS_DECL(truncate, int, (const char* path, off_t length)); UNIFYFS_DECL(stat, int, (const char* path, struct stat* buf)); -UNIFYFS_DECL(__xstat, int, (int vers, const char* path, struct stat* buf)); -UNIFYFS_DECL(__lxstat, int, (int vers, const char* path, struct stat* buf)); UNIFYFS_DECL(statfs, int, (const char* path, struct statfs* fsbuf)); +UNIFYFS_DECL(__xstat, int, (int vers, const char* path, struct stat* buf)); +UNIFYFS_DECL(utimensat, int, (int dirfd, const char* pathname, + const struct timespec times[2], int flags)); +UNIFYFS_DECL(futimens, int, (int fd, const struct timespec times[2])); +/* directory operations */ +UNIFYFS_DECL(chdir, int, (const char* path)); +UNIFYFS_DECL(__getcwd_chk, char*, (char* path, size_t, size_t)); +UNIFYFS_DECL(get_current_dir_name, char*, (void)); +UNIFYFS_DECL(getcwd, char*, (char* path, size_t)); +UNIFYFS_DECL(getwd, char*, (char* path)); +UNIFYFS_DECL(mkdir, int, (const char* path, mode_t mode)); +UNIFYFS_DECL(rmdir, int, (const char* path)); -/* --------------------------------------- - * POSIX wrappers: file descriptors - * --------------------------------------- */ - +/* file operations */ UNIFYFS_DECL(creat, int, (const char* path, mode_t mode)); UNIFYFS_DECL(creat64, int, (const char* path, mode_t mode)); +UNIFYFS_DECL(__open_2, int, (const char* path, int flags, ...)); UNIFYFS_DECL(open, int, (const char* path, int flags, ...)); UNIFYFS_DECL(open64, int, (const char* path, int flags, ...)); -UNIFYFS_DECL(__open_2, int, (const char* path, int flags, ...)); -UNIFYFS_DECL(read, ssize_t, (int fd, void* buf, size_t count)); -UNIFYFS_DECL(write, ssize_t, (int fd, const void* buf, size_t count)); -UNIFYFS_DECL(readv, ssize_t, (int fd, const struct iovec* iov, int iovcnt)); -UNIFYFS_DECL(writev, ssize_t, (int fd, const struct iovec* iov, int iovcnt)); +UNIFYFS_DECL(truncate, int, (const char* path, off_t length)); +UNIFYFS_DECL(unlink, int, (const char* path)); + +/* --------------------------------------- + * POSIX wrappers: file descriptors + * --------------------------------------- */ + +/* I/O operations */ +UNIFYFS_DECL(fsync, int, (int fd)); +UNIFYFS_DECL(fdatasync, int, (int fd)); +UNIFYFS_DECL(ftruncate, int, (int fd, off_t length)); +UNIFYFS_DECL(lio_listio, int, (int mode, struct aiocb* const aiocb_list[], + int nitems, struct sigevent* sevp)); +UNIFYFS_DECL(lseek, off_t, (int fd, off_t offset, int whence)); +UNIFYFS_DECL(lseek64, off64_t, (int fd, off64_t offset, int whence)); +UNIFYFS_DECL(mmap, void*, (void* addr, size_t length, int prot, int flags, + int fd, off_t offset)); +UNIFYFS_DECL(mmap64, void*, (void* addr, size_t length, int prot, int flags, + int fd, off64_t offset)); +UNIFYFS_DECL(msync, int, (void* addr, size_t length, int flags)); +UNIFYFS_DECL(munmap, int, (void* addr, size_t length)); UNIFYFS_DECL(pread, ssize_t, (int fd, void* buf, size_t count, off_t offset)); UNIFYFS_DECL(pread64, ssize_t, (int fd, void* buf, size_t count, off64_t offset)); @@ -94,28 +111,22 @@ UNIFYFS_DECL(pwrite, ssize_t, (int fd, const void* buf, size_t count, off_t offset)); UNIFYFS_DECL(pwrite64, ssize_t, (int fd, const void* buf, size_t count, off64_t offset)); -UNIFYFS_DECL(posix_fadvise, int, (int fd, off_t offset, off_t len, int advice)); -UNIFYFS_DECL(lseek, off_t, (int fd, off_t offset, int whence)); -UNIFYFS_DECL(lseek64, off64_t, (int fd, off64_t offset, int whence)); +UNIFYFS_DECL(read, ssize_t, (int fd, void* buf, size_t count)); +UNIFYFS_DECL(readv, ssize_t, (int fd, const struct iovec* iov, int iovcnt)); +UNIFYFS_DECL(write, ssize_t, (int fd, const void* buf, size_t count)); +UNIFYFS_DECL(writev, ssize_t, (int fd, const struct iovec* iov, int iovcnt)); + +/* inspection/control operations */ +UNIFYFS_DECL(close, int, (int fd)); +UNIFYFS_DECL(dup, int, (int fd)); +UNIFYFS_DECL(dup2, int, (int fd, int desired_fd)); UNIFYFS_DECL(fchdir, int, (int fd)); UNIFYFS_DECL(fchmod, int, (int fd, mode_t mode)); -UNIFYFS_DECL(ftruncate, int, (int fd, off_t length)); +UNIFYFS_DECL(flock, int, (int fd, int operation)); UNIFYFS_DECL(fstat, int, (int fd, struct stat* buf)); -UNIFYFS_DECL(__fxstat, int, (int vers, int fd, struct stat* buf)); UNIFYFS_DECL(fstatfs, int, (int fd, struct statfs* fsbuf)); -UNIFYFS_DECL(fsync, int, (int fd)); -UNIFYFS_DECL(fdatasync, int, (int fd)); -UNIFYFS_DECL(flock, int, (int fd, int operation)); -UNIFYFS_DECL(mmap, void*, (void* addr, size_t length, int prot, int flags, - int fd, off_t offset)); -UNIFYFS_DECL(mmap64, void*, (void* addr, size_t length, int prot, int flags, - int fd, off64_t offset)); -UNIFYFS_DECL(munmap, int, (void* addr, size_t length)); -UNIFYFS_DECL(msync, int, (void* addr, size_t length, int flags)); UNIFYFS_DECL(__fxstat, int, (int vers, int fd, struct stat* buf)); -UNIFYFS_DECL(close, int, (int fd)); -UNIFYFS_DECL(lio_listio, int, (int mode, struct aiocb* const aiocb_list[], - int nitems, struct sigevent* sevp)); +UNIFYFS_DECL(posix_fadvise, int, (int fd, off_t offset, off_t len, int advice)); /* * Read 'count' bytes info 'buf' from file starting at offset 'pos'. diff --git a/client/unifyfs-config.in b/client/unifyfs-config.in index 07bc0d64f..e8652487e 100644 --- a/client/unifyfs-config.in +++ b/client/unifyfs-config.in @@ -7,11 +7,11 @@ -CP_WRAPPERS="@CP_WRAPPERS@" +LINK_WRAPPERS="@LINK_WRAPPERS@" UNIFYFS_LIB_PATH="@unifyfs_lib_path@" UNIFYFS_LD_FLAGS="@LDFLAGS@" -PRE_LD_FLAGS="-L$UNIFYFS_LIB_PATH $UNIFYFS_LD_FLAGS $CP_WRAPPERS" +PRE_LD_FLAGS="-L$UNIFYFS_LIB_PATH $UNIFYFS_LD_FLAGS $LINK_WRAPPERS" POST_LD_FLAGS="$UNIFYFS_LIB_PATH/libunifyfs.a -lcrypto -lm -lrt -lpthread -lz" diff --git a/common/src/unifyfs_keyval.c b/common/src/unifyfs_keyval.c index 61e086edb..d8b76d638 100644 --- a/common/src/unifyfs_keyval.c +++ b/common/src/unifyfs_keyval.c @@ -186,22 +186,13 @@ int unifyfs_pmi2_init(void) pmi2_has_nameserv = val; } - char pmi_jobid[64]; - memset(pmi_jobid, 0, sizeof(pmi_jobid)); - rc = PMI2_Job_GetId(pmi_jobid, sizeof(pmi_jobid)); - if (rc != PMI2_SUCCESS) { - unifyfs_pmi2_errstr(rc); - LOGERR("PMI2_Job_GetId() failed: %s", pmi2_errstr); - return (int)UNIFYFS_ERROR_PMI; - } - kv_myrank = pmi_world_rank; kv_nranks = pmi_world_nprocs; glb_pmi_rank = kv_myrank; glb_pmi_size = kv_nranks; - LOGDBG("PMI2 Job Id: %s, Rank: %d of %d, hasNameServer=%d", pmi_jobid, + LOGDBG("PMI2 Rank: %d of %d, hasNameServer=%d", kv_myrank, kv_nranks, pmi2_has_nameserv); pmi2_initialized = 1; diff --git a/common/src/unifyfs_meta.h b/common/src/unifyfs_meta.h index 5c71092b4..abe9d8bfe 100644 --- a/common/src/unifyfs_meta.h +++ b/common/src/unifyfs_meta.h @@ -140,7 +140,8 @@ typedef enum { UNIFYFS_FILE_ATTR_OP_CREATE, UNIFYFS_FILE_ATTR_OP_DATA, UNIFYFS_FILE_ATTR_OP_LAMINATE, - UNIFYFS_FILE_ATTR_OP_TRUNCATE + UNIFYFS_FILE_ATTR_OP_TRUNCATE, + UNIFYFS_FILE_ATTR_OP_UTIME, } unifyfs_file_attr_op_e; /* @@ -193,7 +194,8 @@ int unifyfs_file_attr_update(int attr_op, } if ((src->atime.tv_sec != 0) && - (attr_op == UNIFYFS_FILE_ATTR_OP_CREATE)) { + ((attr_op == UNIFYFS_FILE_ATTR_OP_CREATE) || + (attr_op == UNIFYFS_FILE_ATTR_OP_UTIME))) { LOGDBG("setting attr.atime to %d.%09ld", (int)src->atime.tv_sec, src->atime.tv_nsec); dst->atime = src->atime; @@ -201,6 +203,7 @@ int unifyfs_file_attr_update(int attr_op, if ((src->mtime.tv_sec != 0) && ((attr_op == UNIFYFS_FILE_ATTR_OP_CREATE) || + (attr_op == UNIFYFS_FILE_ATTR_OP_UTIME) || (attr_op == UNIFYFS_FILE_ATTR_OP_DATA) || (attr_op == UNIFYFS_FILE_ATTR_OP_LAMINATE) || (attr_op == UNIFYFS_FILE_ATTR_OP_TRUNCATE))) { diff --git a/configure.ac b/configure.ac index f45c8eecd..c441805e8 100755 --- a/configure.ac +++ b/configure.ac @@ -120,35 +120,13 @@ AC_ARG_WITH(pkgconfigdir, AC_SUBST(pkgconfigdir) ## unifyfs options -AC_ARG_ENABLE([cuserid],[AS_HELP_STRING([--disable-cuserid],[Disables attempted use of cuserid() at run time])],[ - AS_IF([test "x$enableval" = "xno"],[ - AC_DEFINE(CRUISE_DISABLE_CUSERID, 1, Define if cuserid() should be disabled),],[])] -,) - -AC_ARG_ENABLE(ld-preload,[AS_HELP_STRING([--disable-ld-preload],[Disables support for LD_PRELOAD library])],[ - AS_IF([test "x$enableval" = "xno"],[ - DISABLE_LDPRELOAD="1" - ],[]) - ] -,[]) - -AC_ARG_ENABLE(st-dev-workaround, - [AS_HELP_STRING([--enable-st-dev-workaround],[Gather device id from parent directory instead of file])],[ - AS_IF([test "x$enableval" = "xyes"],[ - AC_DEFINE(__CP_ST_DEV_WORKAROUND, 1, Define if device id should be taken from parent directory rather than file) - DISABLE_LDPRELOAD="1" - ],[]) - ] -,[]) - -# use mpi for bootstraping unifyfsd -AC_ARG_ENABLE(unifyfsd-mpi, - [AS_HELP_STRING([--enable-unifyfsd-mpi],[Use MPI for bootstrapping unifyfsd])],[ - AS_IF([test "x$enableval" = "xyes"],[ - AC_DEFINE(UNIFYFSD_USE_MPI, 1, Define if unifyfsd has to use mpi for bootstrapping)],[]) - ] -,[]) +AC_ARG_ENABLE(preload,[AS_HELP_STRING([--enable-preload],[Enables support for LD_PRELOAD library])]) +AS_IF([test "x$enable_preload" = "xyes"],[ + AM_CONDITIONAL([ENABLE_LD_PRELOAD],[true]) +],[ + AM_CONDITIONAL([ENABLE_LD_PRELOAD],[false]) +]) # look for MPI and set flags LX_FIND_MPI @@ -223,133 +201,143 @@ AM_CONDITIONAL([HAVE_HDF5], [test x$with_hdf5 = xyes]) # libc functions wrapped by unifyfs -CP_WRAPPERS+="-Wl,-wrap,access" -CP_WRAPPERS+=",-wrap,chmod" -CP_WRAPPERS+=",-wrap,fchmod" +LINK_WRAPPERS="-Wl" + +# path functions +LINK_WRAPPERS+=",-wrap,access" +LINK_WRAPPERS+=",-wrap,chmod" +LINK_WRAPPERS+=",-wrap,creat" +LINK_WRAPPERS+=",-wrap,creat64" +LINK_WRAPPERS+=",-wrap,__open_2" +LINK_WRAPPERS+=",-wrap,open" +AC_CHECK_FUNCS(open64, [ + LINK_WRAPPERS+=",-wrap,open64" +],[]) +LINK_WRAPPERS+=",-wrap,remove" +LINK_WRAPPERS+=",-wrap,rename" +LINK_WRAPPERS+=",-wrap,truncate" +LINK_WRAPPERS+=",-wrap,unlink" +LINK_WRAPPERS+=",-wrap,utimensat" +LINK_WRAPPERS+=",-wrap,futimens" + +# file descriptor functions +LINK_WRAPPERS+=",-wrap,close" +LINK_WRAPPERS+=",-wrap,dup" +LINK_WRAPPERS+=",-wrap,dup2" +LINK_WRAPPERS+=",-wrap,fchmod" +LINK_WRAPPERS+=",-wrap,fdatasync" +LINK_WRAPPERS+=",-wrap,flock" +LINK_WRAPPERS+=",-wrap,fsync" +LINK_WRAPPERS+=",-wrap,ftruncate" +LINK_WRAPPERS+=",-wrap,lseek" +LINK_WRAPPERS+=",-wrap,lseek64" +LINK_WRAPPERS+=",-wrap,pread" +LINK_WRAPPERS+=",-wrap,pread64" +LINK_WRAPPERS+=",-wrap,pwrite" +LINK_WRAPPERS+=",-wrap,pwrite64" +LINK_WRAPPERS+=",-wrap,read" +LINK_WRAPPERS+=",-wrap,readv" +LINK_WRAPPERS+=",-wrap,write" +LINK_WRAPPERS+=",-wrap,writev" OLD_LIBS=$LIBS LIBS+=" -lrt" AC_CHECK_FUNCS(lio_listio,[ - CP_WRAPPERS+=",-wrap,lio_listio" + LINK_WRAPPERS+=",-wrap,lio_listio" ], []) LIBS=$OLD_LIBS -CP_WRAPPERS+=",-wrap,mkdir" -CP_WRAPPERS+=",-wrap,rmdir" -CP_WRAPPERS+=",-wrap,chdir" -CP_WRAPPERS+=",-wrap,__getcwd_chk" -CP_WRAPPERS+=",-wrap,getcwd" -CP_WRAPPERS+=",-wrap,getwd" -CP_WRAPPERS+=",-wrap,get_current_dir_name" -CP_WRAPPERS+=",-wrap,unlink" -CP_WRAPPERS+=",-wrap,remove" -CP_WRAPPERS+=",-wrap,rename" -CP_WRAPPERS+=",-wrap,truncate" -CP_WRAPPERS+=",-wrap,stat" -CP_WRAPPERS+=",-wrap,fstat" - +# memory-mapped files +LINK_WRAPPERS+=",-wrap,mmap" +LINK_WRAPPERS+=",-wrap,mmap64" +LINK_WRAPPERS+=",-wrap,msync" +LINK_WRAPPERS+=",-wrap,munmap" +# status functions +LINK_WRAPPERS+=",-wrap,fstat" +LINK_WRAPPERS+=",-wrap,stat" AC_CHECK_FUNCS(statfs,[ - CP_WRAPPERS+=",-wrap,statfs" + LINK_WRAPPERS+=",-wrap,statfs" ],[]) AC_CHECK_FUNCS(fstatfs,[ - CP_WRAPPERS+=",-wrap,fstatfs" + LINK_WRAPPERS+=",-wrap,fstatfs" ],[]) AC_CHECK_FUNCS(__lxstat,[ - CP_WRAPPERS+=",-wrap,__lxstat" + LINK_WRAPPERS+=",-wrap,__lxstat" ],[]) AC_CHECK_FUNCS(__xstat,[ - CP_WRAPPERS+=",-wrap,__xstat" + LINK_WRAPPERS+=",-wrap,__xstat" ],[]) AC_CHECK_FUNCS(__fxstat,[ - CP_WRAPPERS+=",-wrap,__fxstat" + LINK_WRAPPERS+=",-wrap,__fxstat" ],[]) -CP_WRAPPERS+=",-wrap,creat" -CP_WRAPPERS+=",-wrap,creat64" -CP_WRAPPERS+=",-wrap,open" -AC_CHECK_FUNCS(open64, [ - CP_WRAPPERS+=",-wrap,open64" -],[]) -CP_WRAPPERS+=",-wrap,__open_2" -CP_WRAPPERS+=",-wrap,read" -CP_WRAPPERS+=",-wrap,write" -CP_WRAPPERS+=",-wrap,readv" -CP_WRAPPERS+=",-wrap,writev" -CP_WRAPPERS+=",-wrap,pread" -CP_WRAPPERS+=",-wrap,pread64" -CP_WRAPPERS+=",-wrap,pwrite" -CP_WRAPPERS+=",-wrap,pwrite64" AC_CHECK_FUNCS(posix_fadvise, [ - CP_WRAPPERS+=",-wrap,posix_fadvise" + LINK_WRAPPERS+=",-wrap,posix_fadvise" ],[]) -CP_WRAPPERS+=",-wrap,lseek" -CP_WRAPPERS+=",-wrap,lseek64" -CP_WRAPPERS+=",-wrap,fchdir" -CP_WRAPPERS+=",-wrap,ftruncate" -CP_WRAPPERS+=",-wrap,fsync" -CP_WRAPPERS+=",-wrap,fdatasync" -CP_WRAPPERS+=",-wrap,flock" -CP_WRAPPERS+=",-wrap,mmap" -CP_WRAPPERS+=",-wrap,mmap64" -CP_WRAPPERS+=",-wrap,munmap" -CP_WRAPPERS+=",-wrap,msync" -CP_WRAPPERS+=",-wrap,close" + +# directory functions +LINK_WRAPPERS+=",-wrap,chdir" +LINK_WRAPPERS+=",-wrap,fchdir" +LINK_WRAPPERS+=",-wrap,__getcwd_chk" +LINK_WRAPPERS+=",-wrap,getcwd" +LINK_WRAPPERS+=",-wrap,getwd" +LINK_WRAPPERS+=",-wrap,get_current_dir_name" +LINK_WRAPPERS+=",-wrap,mkdir" +LINK_WRAPPERS+=",-wrap,rmdir" # FILE* functions -CP_WRAPPERS+=",-wrap,fclose" -CP_WRAPPERS+=",-wrap,fflush" -CP_WRAPPERS+=",-wrap,fopen" -CP_WRAPPERS+=",-wrap,freopen" -CP_WRAPPERS+=",-wrap,setbuf" -CP_WRAPPERS+=",-wrap,setvbuf" - -CP_WRAPPERS+=",-wrap,fprintf" -CP_WRAPPERS+=",-wrap,fscanf" -CP_WRAPPERS+=",-wrap,vfprintf" -CP_WRAPPERS+=",-wrap,vfscanf" - -CP_WRAPPERS+=",-wrap,fgetc" -CP_WRAPPERS+=",-wrap,fgets" -CP_WRAPPERS+=",-wrap,fputc" -CP_WRAPPERS+=",-wrap,fputs" -CP_WRAPPERS+=",-wrap,getc" -CP_WRAPPERS+=",-wrap,putc" -CP_WRAPPERS+=",-wrap,ungetc" - -CP_WRAPPERS+=",-wrap,fread" -CP_WRAPPERS+=",-wrap,fwrite" - -CP_WRAPPERS+=",-wrap,fgetpos" -CP_WRAPPERS+=",-wrap,fseek" -CP_WRAPPERS+=",-wrap,fsetpos" -CP_WRAPPERS+=",-wrap,ftell" -CP_WRAPPERS+=",-wrap,rewind" - -CP_WRAPPERS+=",-wrap,clearerr" -CP_WRAPPERS+=",-wrap,feof" -CP_WRAPPERS+=",-wrap,ferror" - -CP_WRAPPERS+=",-wrap,fseeko" -CP_WRAPPERS+=",-wrap,ftello" -CP_WRAPPERS+=",-wrap,fileno" +LINK_WRAPPERS+=",-wrap,fclose" +LINK_WRAPPERS+=",-wrap,fflush" +LINK_WRAPPERS+=",-wrap,fopen" +LINK_WRAPPERS+=",-wrap,freopen" +LINK_WRAPPERS+=",-wrap,setbuf" +LINK_WRAPPERS+=",-wrap,setvbuf" + +LINK_WRAPPERS+=",-wrap,fprintf" +LINK_WRAPPERS+=",-wrap,fscanf" +LINK_WRAPPERS+=",-wrap,vfprintf" +LINK_WRAPPERS+=",-wrap,vfscanf" + +LINK_WRAPPERS+=",-wrap,fgetc" +LINK_WRAPPERS+=",-wrap,fgets" +LINK_WRAPPERS+=",-wrap,fputc" +LINK_WRAPPERS+=",-wrap,fputs" +LINK_WRAPPERS+=",-wrap,getc" +LINK_WRAPPERS+=",-wrap,putc" +LINK_WRAPPERS+=",-wrap,ungetc" + +LINK_WRAPPERS+=",-wrap,fread" +LINK_WRAPPERS+=",-wrap,fwrite" + +LINK_WRAPPERS+=",-wrap,fgetpos" +LINK_WRAPPERS+=",-wrap,fseek" +LINK_WRAPPERS+=",-wrap,fsetpos" +LINK_WRAPPERS+=",-wrap,ftell" +LINK_WRAPPERS+=",-wrap,rewind" + +LINK_WRAPPERS+=",-wrap,clearerr" +LINK_WRAPPERS+=",-wrap,feof" +LINK_WRAPPERS+=",-wrap,ferror" + +LINK_WRAPPERS+=",-wrap,fseeko" +LINK_WRAPPERS+=",-wrap,ftello" +LINK_WRAPPERS+=",-wrap,fileno" # wide character FILE* functions -CP_WRAPPERS+=",-wrap,fwprintf" -CP_WRAPPERS+=",-wrap,fwscanf" -CP_WRAPPERS+=",-wrap,vfwprintf" -CP_WRAPPERS+=",-wrap,vfwscanf" -CP_WRAPPERS+=",-wrap,fgetwc" -CP_WRAPPERS+=",-wrap,fgetws" -CP_WRAPPERS+=",-wrap,fputwc" -CP_WRAPPERS+=",-wrap,fputws" -CP_WRAPPERS+=",-wrap,fwide" -CP_WRAPPERS+=",-wrap,getwc" -CP_WRAPPERS+=",-wrap,putwc" -CP_WRAPPERS+=",-wrap,ungetwc" - -# ,-u,__wrap___fxstat64,-u,pthread_mutex_lock,-u,pthread_mutex_unlock +LINK_WRAPPERS+=",-wrap,fwprintf" +LINK_WRAPPERS+=",-wrap,fwscanf" +LINK_WRAPPERS+=",-wrap,vfwprintf" +LINK_WRAPPERS+=",-wrap,vfwscanf" +LINK_WRAPPERS+=",-wrap,fgetwc" +LINK_WRAPPERS+=",-wrap,fgetws" +LINK_WRAPPERS+=",-wrap,fputwc" +LINK_WRAPPERS+=",-wrap,fputws" +LINK_WRAPPERS+=",-wrap,fwide" +LINK_WRAPPERS+=",-wrap,getwc" +LINK_WRAPPERS+=",-wrap,putwc" +LINK_WRAPPERS+=",-wrap,ungetwc" # We need to know the value of the $libdir and $bindir variables so that # we can reference the correct path in the unifyfs compiler wrappers. @@ -377,10 +365,7 @@ fi AC_SUBST(unifyfs_lib_path) AC_SUBST(unifyfs_bin_path) -AC_SUBST(LDFLAGS) -AC_SUBST(__CP_LOG_PATH) -AC_SUBST(CP_WRAPPERS) -AC_SUBST(DISABLE_LDPRELOAD) +AC_SUBST(LINK_WRAPPERS) AC_CONFIG_FILES([Makefile meta/Makefile @@ -431,8 +416,8 @@ AC_MSG_RESULT([ CFLAGS ${CFLAGS} ========================== - Supported POSIX wrappers: + Supported I/O wrappers: - ${CP_WRAPPERS} + ${LINK_WRAPPERS} ]) diff --git a/docs/build.rst b/docs/build.rst index aac26a5a4..6ed9631a9 100644 --- a/docs/build.rst +++ b/docs/build.rst @@ -286,6 +286,44 @@ mounting capability. With transparent mounting, calls to ``unifyfs_mount()`` and the namespace mountpoint. To enable transparent mounting, use the ``--enable-mpi-mount`` configure option. +.. _preload-label: +Intercepting I/O Calls from Shell Commands +****************************************** + +An optional preload library can be used to intercept I/O function calls +made by shell commands, which allows one to run shell commands as a client +to interact with UnifyFS. +To build this library, use the ``--enable-preload`` configure option. +At run time, one should start the UnifyFS server as normal. +One must then set the ``LD_PRELOAD`` environment variable to point to +the installed library location within the shell. +For example, a bash user can set: + +.. code-block:: Bash + + $ export LD_PRELOAD=/path/to/install/lib/libunifyfs_preload_gotcha.so + +One can then interact with UnifyFS through subsequent shell commands, such as: + +.. code-block:: Bash + + $ touch /unifyfs/file1 + $ cp -pr /unifyfs/file1 /unifyfs/file2 + $ ls -l /unifyfs/file1 + $ stat /unifyfs/file1 + $ rm /unifyfs/file1 + +The default mountpoint used is ``/unifyfs``. +This can be changed by setting the ``UNIFYFS_PRELOAD_MOUNTPOINT`` +environment variable. + +.. note:: + + Due to the variety and variation of I/O functions that may be called by + different commands, there is no guarantee that a given invocation is + supported under UnifyFS semantics. + This feature is experimental, and it should be used at one's own risk. + --------------------------- .. explicit external hyperlink targets diff --git a/examples/src/Makefile.am b/examples/src/Makefile.am index 06f0f3db7..47bcfcb48 100644 --- a/examples/src/Makefile.am +++ b/examples/src/Makefile.am @@ -115,7 +115,7 @@ ex_posix_mpi_ldadd = $(ex_posix_ldadd) $(MPI_CLDFLAGS) ex_static_ldadd = $(ex_static_lib) -lrt -lm ex_static_mpi_ldadd = $(ex_static_ldadd) $(MPI_CLDFLAGS) -ex_static_ldflags = $(AM_LDFLAGS) -static $(CP_WRAPPERS) +ex_static_ldflags = $(AM_LDFLAGS) $(LINK_WRAPPERS) -static # Per-target flags begin here diff --git a/server/src/unifyfs_client_rpc.c b/server/src/unifyfs_client_rpc.c index f9333377a..28287b4d2 100644 --- a/server/src/unifyfs_client_rpc.c +++ b/server/src/unifyfs_client_rpc.c @@ -267,6 +267,7 @@ static void unifyfs_unmount_rpc(hg_handle_t handle) /* disconnect app client */ app_client* clnt = get_app_client(app_id, client_id); if (NULL != clnt) { + LOGDBG("disconnecting app client [%d:%d]", app_id, client_id); ret = disconnect_app_client(clnt); } else { LOGERR("application client not found"); diff --git a/t/Makefile.am b/t/Makefile.am index 2c8b31816..4c1294bfc 100644 --- a/t/Makefile.am +++ b/t/Makefile.am @@ -100,7 +100,7 @@ test_wrap_ldadd = \ test_wrap_ldflags = \ $(AM_LDFLAGS) \ - $(CP_WRAPPERS) \ + $(LINK_WRAPPERS) \ -static # Per-target flags begin here