From 5512d7c09f226cc4b587e655fcf9bb7846c59c1a Mon Sep 17 00:00:00 2001 From: Xavier Deguillard Date: Wed, 16 Sep 2020 18:55:52 -0700 Subject: [PATCH] win: make the getPlaceholder callback asynchronous Summary: Similarly to the other callback, this will make it possible to interrupt. Reviewed By: fanzeyi Differential Revision: D23643101 fbshipit-source-id: 9f9a48e752a850c63255b8867b980163cb6a92c9 --- eden/fs/telemetry/EdenStats.h | 1 + eden/fs/win/mount/EdenDispatcher.cpp | 11 ++-- eden/fs/win/mount/EdenDispatcher.h | 4 +- eden/fs/win/mount/PrjfsChannel.cpp | 86 ++++++++++++++++--------- eden/fs/win/mount/PrjfsRequestContext.h | 2 +- 5 files changed, 64 insertions(+), 40 deletions(-) diff --git a/eden/fs/telemetry/EdenStats.h b/eden/fs/telemetry/EdenStats.h index 5d3774cbfa..448e650bae 100644 --- a/eden/fs/telemetry/EdenStats.h +++ b/eden/fs/telemetry/EdenStats.h @@ -156,6 +156,7 @@ class ChannelThreadStats : public EdenThreadStatsBase { Histogram preSetHardlink{createHistogram("prjfs.preSetHardlink_us")}; Histogram openDir{createHistogram("prjfs.opendir_us")}; + Histogram lookup{createHistogram("prjfs.lookup_us")}; #endif // Since we can potentially finish a request in a different diff --git a/eden/fs/win/mount/EdenDispatcher.cpp b/eden/fs/win/mount/EdenDispatcher.cpp index 103f923273..48b0ff1379 100644 --- a/eden/fs/win/mount/EdenDispatcher.cpp +++ b/eden/fs/win/mount/EdenDispatcher.cpp @@ -177,16 +177,15 @@ HRESULT EdenDispatcher::getEnumerationData( } folly::Future> EdenDispatcher::lookup( - RelativePath path) { + RelativePath path, + ObjectFetchContext& context) { FB_LOGF(mount_->getStraceLogger(), DBG7, "lookup({})", path); - static auto context = ObjectFetchContext::getNullContextWithCauseDetail( - "win::EdenDispatcher::lookup"); return mount_->getInode(path) .thenValue( - [](const InodePtr inode) - -> folly::Future> { - return inode->stat(*context).thenValue( + [&context](const InodePtr inode) mutable + -> folly::Future> { + return inode->stat(context).thenValue( [inode = std::move(inode)](struct stat&& stat) { // Ensure that the OS has a record of the canonical // file name, and not just whatever case was used to diff --git a/eden/fs/win/mount/EdenDispatcher.h b/eden/fs/win/mount/EdenDispatcher.h index 726689a9fb..1e248d6fd3 100644 --- a/eden/fs/win/mount/EdenDispatcher.h +++ b/eden/fs/win/mount/EdenDispatcher.h @@ -52,7 +52,9 @@ class EdenDispatcher { HRESULT endEnumeration(const GUID& enumerationId) noexcept; - folly::Future> lookup(RelativePath path); + folly::Future> lookup( + RelativePath path, + ObjectFetchContext& context); folly::Future access(RelativePath path); diff --git a/eden/fs/win/mount/PrjfsChannel.cpp b/eden/fs/win/mount/PrjfsChannel.cpp index f3e67b2059..59cb7a60b7 100644 --- a/eden/fs/win/mount/PrjfsChannel.cpp +++ b/eden/fs/win/mount/PrjfsChannel.cpp @@ -24,6 +24,7 @@ using facebook::eden::EdenDispatcher; using facebook::eden::exceptionToHResult; using facebook::eden::Guid; using facebook::eden::InodeMetadata; +using facebook::eden::makeHResultErrorExplicit; using facebook::eden::ObjectFetchContext; using facebook::eden::PrjfsChannel; using facebook::eden::PrjfsRequestContext; @@ -113,43 +114,64 @@ HRESULT getPlaceholderInfo(const PRJ_CALLBACK_DATA* callbackData) noexcept { BAIL_ON_RECURSIVE_CALL(callbackData); try { + auto channel = getChannel(callbackData); + auto dispatcher = channel->getDispatcher(); + auto context = + std::make_unique(channel, *callbackData); + auto path = RelativePath(callbackData->FilePathName); - return getChannel(callbackData) - ->getDispatcher() - ->lookup(std::move(path)) - .thenValue([context = callbackData->NamespaceVirtualizationContext]( - const std::optional&& optMetadata) { - if (!optMetadata) { - return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND); - } - auto metadata = std::move(optMetadata).value(); + auto virtualizationContext = callbackData->NamespaceVirtualizationContext; - PRJ_PLACEHOLDER_INFO placeholderInfo{}; - placeholderInfo.FileBasicInfo.IsDirectory = metadata.isDir; - placeholderInfo.FileBasicInfo.FileSize = metadata.size; - auto inodeName = metadata.path.wide(); + context + ->catchErrors(folly::makeFutureWith([context = context.get(), + dispatcher = dispatcher, + path = std::move(path), + virtualizationContext = + virtualizationContext] { + auto requestWatch = + std::shared_ptr( + nullptr); + auto histogram = &ChannelThreadStats::lookup; + context->startRequest( + dispatcher->getStats(), histogram, requestWatch); - HRESULT result = PrjWritePlaceholderInfo( - context, - inodeName.c_str(), - &placeholderInfo, - sizeof(placeholderInfo)); + return dispatcher->lookup(std::move(path), *context) + .thenValue([context = context, + virtualizationContext = virtualizationContext]( + const std::optional&& optMetadata) { + if (!optMetadata) { + context->sendError(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)); + return folly::makeFuture(folly::unit); + } + auto metadata = std::move(optMetadata).value(); - if (FAILED(result)) { - XLOGF( - DBG6, - "{}: {:x} ({})", - metadata.path, - result, - win32ErrorToString(result)); - } + PRJ_PLACEHOLDER_INFO placeholderInfo{}; + placeholderInfo.FileBasicInfo.IsDirectory = metadata.isDir; + placeholderInfo.FileBasicInfo.FileSize = metadata.size; + auto inodeName = metadata.path.wide(); - return result; - }) - .thenError( - folly::tag_t{}, - [](const std::exception& ex) { return exceptionToHResult(ex); }) - .get(); + HRESULT result = PrjWritePlaceholderInfo( + virtualizationContext, + inodeName.c_str(), + &placeholderInfo, + sizeof(placeholderInfo)); + + if (FAILED(result)) { + return folly::makeFuture( + makeHResultErrorExplicit( + result, + fmt::format( + FMT_STRING("Writing placeholder for {}"), + metadata.path))); + } + + context->sendSuccess(); + return folly::makeFuture(folly::unit); + }); + })) + .ensure([context = std::move(context)] {}); + + return HRESULT_FROM_WIN32(ERROR_IO_PENDING); } catch (const std::exception& ex) { return exceptionToHResult(ex); } diff --git a/eden/fs/win/mount/PrjfsRequestContext.h b/eden/fs/win/mount/PrjfsRequestContext.h index 3d89dd7b65..fa5044ca18 100644 --- a/eden/fs/win/mount/PrjfsRequestContext.h +++ b/eden/fs/win/mount/PrjfsRequestContext.h @@ -52,11 +52,11 @@ class PrjfsRequestContext : public RequestContext { return channel_->sendSuccess(commandId_, &extra); } - private: void sendError(HRESULT result) const { return channel_->sendError(commandId_, result); } + private: PrjfsChannel* channel_; int32_t commandId_; };