diff --git a/CHANGELOG.md b/CHANGELOG.md index 3fe49a59e307d16625908e70eba06256ee5ad822..6e31396daa1471a3b086f06fc7d5139536b32093 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,6 +34,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - Optimized and fixed fuse ([!293](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/293)) - New optimization options - Less contention with threading using sharding + - Fork support in the client library ([!299](https://storage.bsc.es/gitlab/hpc/gekkofs/-/merge_requests/299)) + - Use LIBGKFS_ENABLE_FORK=1 to enable fork support in the client library. + - This is used for example in DLIO. diff --git a/README.md b/README.md index 597b0a043cf1eb93ba1614fac70a8ec9d40d1ce8..51b50b6105abe5a0374437d34ed66189ef36d3d0 100644 --- a/README.md +++ b/README.md @@ -608,6 +608,7 @@ The GekkoFS daemon, client, and proxy support a number of environment variables - `LIBGKFS_CREATE_CHECK_PARENTS` - Enable checking parent directory for existence before creating children. - `LIBGKFS_SYMLINK_SUPPORT` - Enable support for symbolic links. - `LIBGKFS_RENAME_SUPPORT` - Enable support for rename. +- `LIBGKFS_ENABLE_FORK` - Enable fork support in the client library, used for example in DLIO. #### Logging - `LIBGKFS_LOG` - Log module of the client. Available modules are: `none`, `syscalls`, `syscalls_at_entry`, `info`, `critical`, `errors`, `warnings`, `mercury`, `debug`, `most`, `all`, `trace_reads`, `help`. diff --git a/include/client/env.hpp b/include/client/env.hpp index 279640976eff3c77ac138e824a879d0564f4b848..7dc9fa5393abe4c5a8257c99215f8cee591fcfe7 100644 --- a/include/client/env.hpp +++ b/include/client/env.hpp @@ -94,6 +94,7 @@ static constexpr auto USE_INLINE_DATA = ADD_PREFIX("USE_INLINE_DATA"); static constexpr auto CREATE_WRITE_OPTIMIZATION = ADD_PREFIX("CREATE_WRITE_OPTIMIZATION"); static constexpr auto READ_INLINE_PREFETCH = ADD_PREFIX("READ_INLINE_PREFETCH"); +static constexpr auto ENABLE_FORK = ADD_PREFIX("ENABLE_FORK"); } // namespace gkfs::env diff --git a/src/client/preload.cpp b/src/client/preload.cpp index c08388ec41b7fd1ebe74be8a08f43b02a5f11243..ca3b1742f3118d5912a8956957ca72247603597a 100644 --- a/src/client/preload.cpp +++ b/src/client/preload.cpp @@ -609,11 +609,42 @@ at_parent() { void at_child() { - // In the child, we should not touch the rpc_engine because it is inherited - // and points to shared resources (Ref count > 0). - // If we destroy it (by overwriting it), we finalize the network stack, - // which might close sockets shared with the parent. - // If we use it, we race with the parent. - // Best is to disable interception so we don't use GekkoFS until exec(). - CTX->disable_interception(); + if(gkfs::env::var_is_set(gkfs::env::ENABLE_FORK)) { + LOG(WARNING, + "Fork interception enabled. Re-initializing GekkoFS client..."); + + // We must intentionally leak the old RPC/IPC engine to prevent + // finalizing the parent's network connections + auto* leaked_rpc_engine = + new std::shared_ptr(CTX->rpc_engine()); + auto* leaked_ipc_engine = + new std::shared_ptr(CTX->ipc_engine()); + (void) leaked_rpc_engine; + (void) leaked_ipc_engine; + + CTX->clear_hosts(); + CTX->rpc_engine(nullptr); + if(CTX->use_proxy()) { + CTX->clear_proxy_host(); + CTX->ipc_engine(nullptr); + } + + // Disable interception temporarily + CTX->disable_interception(); + + // Re-initialize the environment and Margo engines + gkfs::preload::init_environment(); + + // Re-enable interception + CTX->enable_interception(); + LOG(INFO, "GekkoFS client successfully re-initialized in child."); + } else { + // In the child, we should not touch the rpc_engine because it is + // inherited and points to shared resources (Ref count > 0). If we + // destroy it (by overwriting it), we finalize the network stack, which + // might close sockets shared with the parent. If we use it, we race + // with the parent. Best is to disable interception so we don't use + // GekkoFS until exec(). + CTX->disable_interception(); + } }