diff --git a/eden/fs/inodes/EdenMount.cpp b/eden/fs/inodes/EdenMount.cpp index f2fa0e794a..4ee2fe3688 100644 --- a/eden/fs/inodes/EdenMount.cpp +++ b/eden/fs/inodes/EdenMount.cpp @@ -1192,66 +1192,30 @@ folly::Future EdenMount::getChannelCompletionFuture() { return channelCompletionPromise_.getFuture(); } -folly::Future EdenMount::startChannel(bool readOnly) { - return folly::makeFutureWith([&]() { - transitionState( - /*expected=*/State::INITIALIZED, /*newState=*/State::STARTING); - - // Just in case the mount point directory doesn't exist, - // automatically create it. - boost::filesystem::path boostMountPath{getPath().value()}; - boost::filesystem::create_directories(boostMountPath); - -#ifdef _WIN32 - fsChannel_ = std::make_unique(this); - fsChannel_->start(getPath(), readOnly); - createRepoConfig( - getPath(), - serverState_->getSocketPath(), - config_->getClientDirectory()); - XLOGF( - INFO, "Started EdenMount (0x{:x})", reinterpret_cast(this)); - transitionState(State::STARTING, State::RUNNING); - - return folly::makeFuture(); -#else - return fuseMount(readOnly) - .thenValue([this](folly::File&& fuseDevice) { - createFuseChannel(std::move(fuseDevice)); - return channel_->initialize().thenValue( - [this](FuseChannel::StopFuture&& fuseCompleteFuture) { - fuseInitSuccessful(std::move(fuseCompleteFuture)); - }); - }) - .thenError([this](folly::exception_wrapper&& ew) { - transitionToFuseInitializationErrorState(); - return makeFuture(std::move(ew)); - }); -#endif - }); -} - -#ifndef _WIN32 -void EdenMount::takeoverFuse(FuseChannelData takeoverData) { - transitionState(State::INITIALIZED, State::STARTING); - - try { - beginMount().setValue(); - - createFuseChannel(std::move(takeoverData.fd)); - auto fuseCompleteFuture = - channel_->initializeFromTakeover(takeoverData.connInfo); - fuseInitSuccessful(std::move(fuseCompleteFuture)); - } catch (const std::exception&) { - transitionToFuseInitializationErrorState(); - throw; - } -} - -folly::Future EdenMount::fuseMount(bool readOnly) { +folly::Future EdenMount::channelMount(bool readOnly) { return folly::makeFutureWith([&] { return &beginMount(); }) .thenValue([this, readOnly](folly::Promise* mountPromise) { AbsolutePath mountPath = getPath(); +#ifdef _WIN32 + return folly::makeFutureWith( + [mountPath, readOnly, this]() -> folly::Future { + auto channel = new PrjfsChannel(this); + channel->start(mountPath, readOnly); + return channel; + }) + .thenTry([mountPromise, this](Try&& channel) { + if (channel.hasException()) { + mountPromise->setException(channel.exception()); + return makeFuture(channel.exception()); + } + + // TODO(xavierd): similarly to the non-Windows code below, we + // need to handle the case where mount was cancelled. + + mountPromise->setValue(); + return makeFuture(channel); + }); +#else return serverState_->getPrivHelper() ->fuseMount(mountPath.stringPiece(), readOnly) .thenTry( @@ -1289,9 +1253,62 @@ folly::Future EdenMount::fuseMount(bool readOnly) { mountPromise->setValue(); return folly::makeFuture(std::move(fuseDevice).value()); }); +#endif }); } +void EdenMount::createChannel(EdenMount::channelType channel) { +#if _WIN32 + fsChannel_.reset(channel); +#else + channel_.reset(new FuseChannel( + std::move(channel), + getPath(), + FLAGS_fuseNumThreads, + dispatcher_.get(), + serverState_->getProcessNameCache(), + std::chrono::duration_cast( + serverState_->getReloadableConfig() + .getEdenConfig() + ->fuseRequestTimeout.getValue()), + serverState_->getNotifications())); +#endif +} + +folly::Future EdenMount::startChannel(bool readOnly) { + return folly::makeFutureWith([&]() { + transitionState( + /*expected=*/State::INITIALIZED, /*newState=*/State::STARTING); + + // Just in case the mount point directory doesn't exist, + // automatically create it. + boost::filesystem::path boostMountPath{getPath().value()}; + boost::filesystem::create_directories(boostMountPath); + + return channelMount(readOnly) + .thenValue([this](EdenMount::channelType&& channel) { + createChannel(std::move(channel)); +#ifdef _WIN32 + createRepoConfig( + getPath(), + serverState_->getSocketPath(), + config_->getClientDirectory()); + + transitionState(State::STARTING, State::RUNNING); +#else + return channel_->initialize().thenValue( + [this](FuseChannel::StopFuture&& fuseCompleteFuture) { + fuseInitSuccessful(std::move(fuseCompleteFuture)); + }); +#endif + }) + .thenError([this](folly::exception_wrapper&& ew) { + transitionToFuseInitializationErrorState(); + return makeFuture(std::move(ew)); + }); + }); +} + folly::Promise& EdenMount::beginMount() { auto mountingUnmountingState = mountingUnmountingState_.wlock(); if (mountingUnmountingState->channelMountPromise.has_value()) { @@ -1313,18 +1330,21 @@ folly::Promise& EdenMount::beginMount() { return *mountingUnmountingState->channelMountPromise; } -void EdenMount::createFuseChannel(folly::File fuseDevice) { - channel_.reset(new FuseChannel( - std::move(fuseDevice), - getPath(), - FLAGS_fuseNumThreads, - dispatcher_.get(), - serverState_->getProcessNameCache(), - std::chrono::duration_cast( - serverState_->getReloadableConfig() - .getEdenConfig() - ->fuseRequestTimeout.getValue()), - serverState_->getNotifications())); +#ifndef _WIN32 +void EdenMount::takeoverFuse(FuseChannelData takeoverData) { + transitionState(State::INITIALIZED, State::STARTING); + + try { + beginMount().setValue(); + + createChannel(std::move(takeoverData.fd)); + auto fuseCompleteFuture = + channel_->initializeFromTakeover(takeoverData.connInfo); + fuseInitSuccessful(std::move(fuseCompleteFuture)); + } catch (const std::exception&) { + transitionToFuseInitializationErrorState(); + throw; + } } void EdenMount::fuseInitSuccessful( diff --git a/eden/fs/inodes/EdenMount.h b/eden/fs/inodes/EdenMount.h index b065b4a4cd..9a813306b2 100644 --- a/eden/fs/inodes/EdenMount.h +++ b/eden/fs/inodes/EdenMount.h @@ -834,12 +834,6 @@ class EdenMount { bool enforceCurrentParent, apache::thrift::ResponseChannelRequest* FOLLY_NULLABLE request) const; -#ifndef _WIN32 - /** - * Open the FUSE device and mount it using the mount(2) syscall. - */ - folly::Future fuseMount(bool readOnly); - /** * Signal to unmount() that fuseMount() or takeoverFuse() has started. * @@ -856,10 +850,23 @@ class EdenMount { */ FOLLY_NODISCARD folly::Promise& beginMount(); +#ifdef _WIN32 + using channelType = FsChannel*; +#else + using channelType = folly::File; +#endif + + /** + * Open the platform specific device and mount it. + */ + folly::Future channelMount(bool readOnly); + /** * Construct the channel_ member variable. */ - void createFuseChannel(folly::File fuseDevice); + void createChannel(channelType fuseDevice); + +#ifndef _WIN32 /** * Once the FuseChannel has been initialized, set up callbacks to clean up