2016-05-12 23:43:17 +03:00
|
|
|
/*
|
2019-06-20 02:58:25 +03:00
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
2016-05-12 23:43:17 +03:00
|
|
|
*
|
2019-06-20 02:58:25 +03:00
|
|
|
* This software may be used and distributed according to the terms of the
|
|
|
|
* GNU General Public License version 2.
|
2016-05-12 23:43:17 +03:00
|
|
|
*/
|
2019-10-11 15:26:59 +03:00
|
|
|
|
2018-03-16 22:08:02 +03:00
|
|
|
#include "eden/fs/fuse/RequestData.h"
|
2016-05-12 23:43:17 +03:00
|
|
|
|
2018-05-01 07:20:51 +03:00
|
|
|
#include <folly/logging/xlog.h>
|
2016-06-10 21:26:35 +03:00
|
|
|
|
2018-03-16 22:08:02 +03:00
|
|
|
#include "eden/fs/fuse/Dispatcher.h"
|
2018-03-20 23:31:14 +03:00
|
|
|
#include "eden/fs/utils/SystemError.h"
|
2018-03-16 22:08:02 +03:00
|
|
|
|
2016-05-12 23:43:17 +03:00
|
|
|
using namespace folly;
|
2016-06-10 21:26:35 +03:00
|
|
|
using namespace std::chrono;
|
2016-05-12 23:43:17 +03:00
|
|
|
|
|
|
|
namespace facebook {
|
|
|
|
namespace eden {
|
|
|
|
|
2018-03-20 03:01:15 +03:00
|
|
|
const std::string RequestData::kKey("fuse");
|
2016-05-12 23:43:17 +03:00
|
|
|
|
2018-01-03 03:25:03 +03:00
|
|
|
RequestData::RequestData(
|
|
|
|
FuseChannel* channel,
|
|
|
|
const fuse_in_header& fuseHeader,
|
|
|
|
Dispatcher* dispatcher)
|
2018-01-26 22:17:36 +03:00
|
|
|
: channel_(channel), fuseHeader_(fuseHeader), dispatcher_(dispatcher) {}
|
2017-09-09 05:15:25 +03:00
|
|
|
|
2017-01-24 20:37:48 +03:00
|
|
|
bool RequestData::isFuseRequest() {
|
|
|
|
return folly::RequestContext::get()->getContextData(kKey) != nullptr;
|
|
|
|
}
|
|
|
|
|
2016-05-12 23:43:17 +03:00
|
|
|
RequestData& RequestData::get() {
|
2018-01-18 00:29:59 +03:00
|
|
|
const auto data = folly::RequestContext::get()->getContextData(kKey);
|
2016-05-12 23:43:17 +03:00
|
|
|
if (UNLIKELY(!data)) {
|
2017-06-22 23:39:57 +03:00
|
|
|
XLOG(FATAL) << "boom for missing RequestData";
|
2016-05-12 23:43:17 +03:00
|
|
|
throw std::runtime_error("no fuse request data set in this context!");
|
|
|
|
}
|
|
|
|
return *dynamic_cast<RequestData*>(data);
|
|
|
|
}
|
|
|
|
|
2018-01-03 03:25:03 +03:00
|
|
|
RequestData& RequestData::create(
|
|
|
|
FuseChannel* channel,
|
|
|
|
const fuse_in_header& fuseHeader,
|
|
|
|
Dispatcher* dispatcher) {
|
2016-05-12 23:43:17 +03:00
|
|
|
folly::RequestContext::get()->setContextData(
|
2018-01-03 03:25:03 +03:00
|
|
|
RequestData::kKey,
|
|
|
|
std::make_unique<RequestData>(channel, fuseHeader, dispatcher));
|
2016-05-12 23:43:17 +03:00
|
|
|
return get();
|
|
|
|
}
|
|
|
|
|
2018-09-06 01:05:50 +03:00
|
|
|
void RequestData::startRequest(
|
2019-04-15 06:42:26 +03:00
|
|
|
EdenStats* stats,
|
2019-05-30 04:08:03 +03:00
|
|
|
FuseThreadStats::HistogramPtr histogram) {
|
2016-06-10 21:26:35 +03:00
|
|
|
startTime_ = steady_clock::now();
|
|
|
|
DCHECK(latencyHistogram_ == nullptr);
|
2017-03-31 21:23:02 +03:00
|
|
|
latencyHistogram_ = histogram;
|
|
|
|
stats_ = stats;
|
2016-06-10 21:26:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void RequestData::finishRequest() {
|
2018-01-18 00:29:59 +03:00
|
|
|
const auto now = steady_clock::now();
|
|
|
|
const auto now_since_epoch = duration_cast<seconds>(now.time_since_epoch());
|
2019-08-02 19:40:15 +03:00
|
|
|
|
|
|
|
const auto diff = now - startTime_;
|
|
|
|
const auto diff_us = duration_cast<microseconds>(diff);
|
|
|
|
const auto diff_ns = duration_cast<nanoseconds>(diff);
|
|
|
|
|
2019-05-30 04:08:03 +03:00
|
|
|
stats_->getFuseStatsForCurrentThread().recordLatency(
|
2019-08-02 19:40:15 +03:00
|
|
|
latencyHistogram_, diff_us, now_since_epoch);
|
2016-06-10 21:26:35 +03:00
|
|
|
latencyHistogram_ = nullptr;
|
2017-03-31 21:23:02 +03:00
|
|
|
stats_ = nullptr;
|
2019-08-01 23:34:28 +03:00
|
|
|
|
|
|
|
auto& pal = channel_->getProcessAccessLog();
|
|
|
|
if (getEdenTopStats().didImportFromBackingStore()) {
|
|
|
|
auto type = ProcessAccessLog::AccessType::FuseBackingStoreImport;
|
|
|
|
pal.recordAccess(examineReq().pid, type);
|
|
|
|
}
|
2019-08-02 19:40:15 +03:00
|
|
|
pal.recordDuration(examineReq().pid, diff_ns);
|
2016-06-10 21:26:35 +03:00
|
|
|
}
|
|
|
|
|
2018-01-03 03:25:03 +03:00
|
|
|
fuse_in_header RequestData::stealReq() {
|
|
|
|
if (fuseHeader_.opcode == 0) {
|
2016-05-12 23:43:17 +03:00
|
|
|
throw std::runtime_error("req_ has been released");
|
|
|
|
}
|
2018-01-03 03:25:03 +03:00
|
|
|
fuse_in_header res = fuseHeader_;
|
|
|
|
fuseHeader_.opcode = 0;
|
2016-05-12 23:43:17 +03:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2018-01-03 03:25:03 +03:00
|
|
|
const fuse_in_header& RequestData::getReq() const {
|
|
|
|
if (fuseHeader_.opcode == 0) {
|
2016-05-12 23:43:17 +03:00
|
|
|
throw std::runtime_error("req_ has been released");
|
|
|
|
}
|
2018-01-03 03:25:03 +03:00
|
|
|
return fuseHeader_;
|
2016-05-12 23:43:17 +03:00
|
|
|
}
|
|
|
|
|
2018-03-20 20:18:29 +03:00
|
|
|
const fuse_in_header& RequestData::examineReq() const {
|
|
|
|
// Will just return the fuseHeader_ and not throw(unlike getReq)
|
|
|
|
// The caller is responsible to check the opcode and ignore if zero
|
|
|
|
return fuseHeader_;
|
|
|
|
}
|
|
|
|
|
2016-05-12 23:43:17 +03:00
|
|
|
Dispatcher* RequestData::getDispatcher() const {
|
2017-09-09 05:15:25 +03:00
|
|
|
return dispatcher_;
|
2016-05-12 23:43:17 +03:00
|
|
|
}
|
|
|
|
|
2019-08-01 23:34:28 +03:00
|
|
|
RequestData::EdenTopStats& RequestData::getEdenTopStats() {
|
|
|
|
return edenTopStats_;
|
|
|
|
}
|
|
|
|
|
2016-05-12 23:43:17 +03:00
|
|
|
void RequestData::replyError(int err) {
|
2018-01-03 03:25:03 +03:00
|
|
|
channel_->replyError(stealReq(), err);
|
2016-05-12 23:43:17 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void RequestData::replyNone() {
|
2018-01-03 03:25:03 +03:00
|
|
|
stealReq();
|
2016-05-12 23:43:17 +03:00
|
|
|
}
|
2017-06-22 23:39:57 +03:00
|
|
|
|
|
|
|
void RequestData::systemErrorHandler(const std::system_error& err) {
|
|
|
|
int errnum = EIO;
|
2018-03-20 23:31:14 +03:00
|
|
|
if (isErrnoError(err)) {
|
2017-06-22 23:39:57 +03:00
|
|
|
errnum = err.code().value();
|
|
|
|
}
|
|
|
|
XLOG(DBG5) << folly::exceptionStr(err);
|
|
|
|
RequestData::get().replyError(errnum);
|
|
|
|
}
|
|
|
|
|
|
|
|
void RequestData::genericErrorHandler(const std::exception& err) {
|
|
|
|
XLOG(DBG5) << folly::exceptionStr(err);
|
|
|
|
RequestData::get().replyError(EIO);
|
|
|
|
}
|
2018-03-20 03:01:15 +03:00
|
|
|
|
2019-08-28 19:40:34 +03:00
|
|
|
void RequestData::timeoutErrorHandler(const folly::FutureTimeout& err) {
|
2019-09-23 20:43:42 +03:00
|
|
|
XLOG_EVERY_MS(WARN, 1000)
|
|
|
|
<< "FUSE request timed out: " << folly::exceptionStr(err);
|
2019-08-28 19:40:34 +03:00
|
|
|
RequestData::get().replyError(ETIMEDOUT);
|
|
|
|
}
|
|
|
|
|
2017-11-04 01:58:04 +03:00
|
|
|
} // namespace eden
|
|
|
|
} // namespace facebook
|