From 22075c115940ad62823b09714e7e200a67ac7514 Mon Sep 17 00:00:00 2001 From: Xavier Deguillard Date: Wed, 3 Feb 2021 17:52:36 -0800 Subject: [PATCH] inodes: start plumbing Mountd in the mount code. Summary: Once everything is plugged in, EdenFS will first register the mount point with Mountd, and then execute the mount.nfs CLI against itself to mount the repository with the OS. For now, this does the first part by simply informing Mountd of a new mount point during mount. Reviewed By: kmancini Differential Revision: D26139990 fbshipit-source-id: e5097b8e90c032c8c7bdd2cd03b69695074d7874 --- eden/fs/inodes/CMakeLists.txt | 2 + eden/fs/inodes/EdenMount.cpp | 97 +++++++++++++++++++++-------------- eden/fs/nfs/CMakeLists.txt | 2 + eden/fs/nfs/Mountd.cpp | 39 ++++++++++++-- eden/fs/nfs/Mountd.h | 18 +++++++ 5 files changed, 115 insertions(+), 43 deletions(-) diff --git a/eden/fs/inodes/CMakeLists.txt b/eden/fs/inodes/CMakeLists.txt index 481e2c1b9c..9e0aaa1694 100644 --- a/eden/fs/inodes/CMakeLists.txt +++ b/eden/fs/inodes/CMakeLists.txt @@ -53,6 +53,8 @@ target_link_libraries( eden_telemetry eden_utils Folly::folly + PRIVATE + eden_nfs_mountd ) if (WIN32) diff --git a/eden/fs/inodes/EdenMount.cpp b/eden/fs/inodes/EdenMount.cpp index d9613fd9c5..ddf02205d1 100644 --- a/eden/fs/inodes/EdenMount.cpp +++ b/eden/fs/inodes/EdenMount.cpp @@ -34,6 +34,7 @@ #include "eden/fs/model/Tree.h" #include "eden/fs/model/git/GitIgnoreStack.h" #include "eden/fs/model/git/TopLevelIgnores.h" +#include "eden/fs/nfs/Mountd.h" #include "eden/fs/service/PrettyPrinters.h" #include "eden/fs/service/gen-cpp2/eden_types.h" #include "eden/fs/store/BlobAccess.h" @@ -636,8 +637,17 @@ folly::Future EdenMount::unmount() { .via(serverState_->getThreadPool().get()) .ensure([this] { channel_.reset(); }); #else - return serverState_->getPrivHelper()->fuseUnmount( - getPath().stringPiece()); + if (serverState_->getReloadableConfig() + .getEdenConfig() + ->enableNfsServer.getValue() && + getConfig()->getMountProtocol() == MountProtocol::NFS) { + // TODO(xavierd): We need to actually do the unmount here. + serverState_->getMountd()->unregisterMount(getPath()); + return folly::makeFuture(); + } else { + return serverState_->getPrivHelper()->fuseUnmount( + getPath().stringPiece()); + } #endif }) .thenTry([this](Try&& result) noexcept -> folly::Future { @@ -1252,43 +1262,54 @@ folly::Future EdenMount::channelMount(bool readOnly) { return makeFuture(channel); }); #else - return serverState_->getPrivHelper() - ->fuseMount(mountPath.stringPiece(), readOnly) - .thenTry( - [mountPath, mountPromise, this](Try&& fuseDevice) - -> folly::Future { - if (fuseDevice.hasException()) { - mountPromise->setException(fuseDevice.exception()); - return folly::makeFuture( - fuseDevice.exception()); - } - if (mountingUnmountingState_.rlock() - ->channelUnmountStarted()) { - fuseDevice->close(); - return serverState_->getPrivHelper() - ->fuseUnmount(mountPath.stringPiece()) - .thenError( - folly::tag, - [](std::exception&& unmountError) { - // TODO(strager): Should we make - // EdenMount::unmount() also fail with the same - // exception? - XLOG(ERR) - << "fuseMount was cancelled, but rollback (fuseUnmount) failed: " - << unmountError.what(); - throw std::move(unmountError); - }) - .thenValue([mountPath, mountPromise](folly::Unit&&) { - auto error = FuseDeviceUnmountedDuringInitialization{ - mountPath}; - mountPromise->setException(error); - return folly::makeFuture(error); - }); - } + if (serverState_->getReloadableConfig() + .getEdenConfig() + ->enableNfsServer.getValue() && + getConfig()->getMountProtocol() == MountProtocol::NFS) { + auto mountd = serverState_->getMountd(); + mountd->registerMount(mountPath, getRootInode()->getNodeId()); + // TODO(xavierd): We need to actually do a mount here. + return makeFuture(folly::File()); + } else { + return serverState_->getPrivHelper() + ->fuseMount(mountPath.stringPiece(), readOnly) + .thenTry( + [mountPath, mountPromise, this](Try&& fuseDevice) + -> folly::Future { + if (fuseDevice.hasException()) { + mountPromise->setException(fuseDevice.exception()); + return folly::makeFuture( + fuseDevice.exception()); + } + if (mountingUnmountingState_.rlock() + ->channelUnmountStarted()) { + fuseDevice->close(); + return serverState_->getPrivHelper() + ->fuseUnmount(mountPath.stringPiece()) + .thenError( + folly::tag, + [](std::exception&& unmountError) { + // TODO(strager): Should we make + // EdenMount::unmount() also fail with the same + // exception? + XLOG(ERR) + << "fuseMount was cancelled, but rollback (fuseUnmount) failed: " + << unmountError.what(); + throw std::move(unmountError); + }) + .thenValue([mountPath, mountPromise](folly::Unit&&) { + auto error = + FuseDeviceUnmountedDuringInitialization{ + mountPath}; + mountPromise->setException(error); + return folly::makeFuture(error); + }); + } - mountPromise->setValue(); - return folly::makeFuture(std::move(fuseDevice).value()); - }); + mountPromise->setValue(); + return folly::makeFuture(std::move(fuseDevice).value()); + }); + } #endif }); } diff --git a/eden/fs/nfs/CMakeLists.txt b/eden/fs/nfs/CMakeLists.txt index 2509ee6af0..3780804e68 100644 --- a/eden/fs/nfs/CMakeLists.txt +++ b/eden/fs/nfs/CMakeLists.txt @@ -11,7 +11,9 @@ add_library( target_link_libraries( eden_nfs_mountd PUBLIC + eden_inodes_inodenumber eden_nfs_rpc_server + eden_utils PRIVATE eden_nfs_mountd_rpc Folly::folly diff --git a/eden/fs/nfs/Mountd.cpp b/eden/fs/nfs/Mountd.cpp index ff9b8b7824..d1c82faf77 100644 --- a/eden/fs/nfs/Mountd.cpp +++ b/eden/fs/nfs/Mountd.cpp @@ -7,15 +7,16 @@ #include "eden/fs/nfs/Mountd.h" +#include +#include + +#include #include #include -#include #include "eden/fs/nfs/MountdRpc.h" namespace facebook::eden { -namespace { - class MountdServerProcessor final : public RpcServerProcessor { public: MountdServerProcessor() = default; @@ -45,6 +46,13 @@ class MountdServerProcessor final : public RpcServerProcessor { umountAll(folly::io::Cursor deser, folly::io::Appender ser, uint32_t xid); folly::Future exprt(folly::io::Cursor deser, folly::io::Appender ser, uint32_t xid); + + void registerMount(AbsolutePathPiece path, InodeNumber rootIno); + void unregisterMount(AbsolutePathPiece path); + + private: + folly::Synchronized> + mountPoints_; }; using Handler = folly::Future (MountdServerProcessor::*)( @@ -174,10 +182,31 @@ folly::Future MountdServerProcessor::dispatchRpc( return (this->*handlerEntry.handler)(std::move(deser), std::move(ser), xid); } -} // namespace +void MountdServerProcessor::registerMount( + AbsolutePathPiece path, + InodeNumber ino) { + auto map = mountPoints_.wlock(); + auto [iter, inserted] = map->emplace(path.copy(), ino); + XCHECK_EQ(inserted, true); +} -Mountd::Mountd() : server_(std::make_shared()) { +void MountdServerProcessor::unregisterMount(AbsolutePathPiece path) { + auto map = mountPoints_.wlock(); + auto numRemoved = map->erase(path.copy()); + XCHECK_EQ(numRemoved, 1u); +} + +Mountd::Mountd() + : proc_(std::make_shared()), server_(proc_) { server_.registerService(kMountdProgNumber, kMountdProgVersion); } +void Mountd::registerMount(AbsolutePathPiece path, InodeNumber ino) { + proc_->registerMount(path, ino); +} + +void Mountd::unregisterMount(AbsolutePathPiece path) { + proc_->unregisterMount(path); +} + } // namespace facebook::eden diff --git a/eden/fs/nfs/Mountd.h b/eden/fs/nfs/Mountd.h index 89cb8a575e..856d79ec45 100644 --- a/eden/fs/nfs/Mountd.h +++ b/eden/fs/nfs/Mountd.h @@ -10,20 +10,38 @@ // Implementation of the mount protocol as described in: // https://tools.ietf.org/html/rfc1813#page-106 +#include "eden/fs/inodes/InodeNumber.h" #include "eden/fs/nfs/rpc/Server.h" +#include "eden/fs/utils/PathFuncs.h" namespace facebook::eden { +class MountdServerProcessor; + class Mountd { public: Mountd(); + /** + * Register a path as the root of a mount point. + * + * Once registered, the mount RPC request for that specific path will answer + * positively with the passed in InodeNumber. + */ + void registerMount(AbsolutePathPiece path, InodeNumber rootIno); + + /** + * Unregister the mount point matching the path. + */ + void unregisterMount(AbsolutePathPiece path); + Mountd(const Mountd&) = delete; Mountd(Mountd&&) = delete; Mountd& operator=(const Mountd&) = delete; Mountd& operator=(Mountd&&) = delete; private: + std::shared_ptr proc_; RpcServer server_; };