2021-02-01 20:26:33 +03:00
|
|
|
/*
|
|
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
|
|
*
|
|
|
|
* This software may be used and distributed according to the terms of the
|
|
|
|
* GNU General Public License version 2.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "eden/fs/nfs/Mountd.h"
|
|
|
|
|
2021-02-04 04:52:36 +03:00
|
|
|
#include <memory>
|
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
#include <folly/Synchronized.h>
|
2021-02-04 23:32:02 +03:00
|
|
|
#include <folly/Utility.h>
|
2021-02-01 20:26:33 +03:00
|
|
|
#include <folly/futures/Future.h>
|
|
|
|
#include <folly/logging/xlog.h>
|
|
|
|
#include "eden/fs/nfs/MountdRpc.h"
|
|
|
|
|
|
|
|
namespace facebook::eden {
|
|
|
|
|
|
|
|
class MountdServerProcessor final : public RpcServerProcessor {
|
|
|
|
public:
|
|
|
|
MountdServerProcessor() = default;
|
|
|
|
|
|
|
|
MountdServerProcessor(const MountdServerProcessor&) = delete;
|
|
|
|
MountdServerProcessor(MountdServerProcessor&&) = delete;
|
|
|
|
MountdServerProcessor& operator=(const MountdServerProcessor&) = delete;
|
|
|
|
MountdServerProcessor& operator=(MountdServerProcessor&&) = delete;
|
|
|
|
|
|
|
|
folly::Future<folly::Unit> dispatchRpc(
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Cursor deser,
|
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid,
|
|
|
|
uint32_t progNumber,
|
|
|
|
uint32_t progVersion,
|
|
|
|
uint32_t procNumber) override;
|
|
|
|
|
|
|
|
folly::Future<folly::Unit>
|
2021-02-04 03:43:32 +03:00
|
|
|
null(folly::io::Cursor deser, folly::io::Appender ser, uint32_t xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
folly::Future<folly::Unit>
|
2021-02-04 03:43:32 +03:00
|
|
|
mount(folly::io::Cursor deser, folly::io::Appender ser, uint32_t xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
folly::Future<folly::Unit>
|
2021-02-04 03:43:32 +03:00
|
|
|
dump(folly::io::Cursor deser, folly::io::Appender ser, uint32_t xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
folly::Future<folly::Unit>
|
2021-02-04 03:43:32 +03:00
|
|
|
umount(folly::io::Cursor deser, folly::io::Appender ser, uint32_t xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
folly::Future<folly::Unit>
|
2021-02-04 03:43:32 +03:00
|
|
|
umountAll(folly::io::Cursor deser, folly::io::Appender ser, uint32_t xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
folly::Future<folly::Unit>
|
2021-02-04 03:43:32 +03:00
|
|
|
exprt(folly::io::Cursor deser, folly::io::Appender ser, uint32_t xid);
|
2021-02-04 04:52:36 +03:00
|
|
|
|
|
|
|
void registerMount(AbsolutePathPiece path, InodeNumber rootIno);
|
|
|
|
void unregisterMount(AbsolutePathPiece path);
|
|
|
|
|
|
|
|
private:
|
|
|
|
folly::Synchronized<std::unordered_map<AbsolutePath, InodeNumber>>
|
|
|
|
mountPoints_;
|
2021-02-01 20:26:33 +03:00
|
|
|
};
|
|
|
|
|
2021-02-04 23:32:02 +03:00
|
|
|
namespace {
|
|
|
|
|
2021-02-01 20:26:33 +03:00
|
|
|
using Handler = folly::Future<folly::Unit> (MountdServerProcessor::*)(
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Cursor deser,
|
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid);
|
|
|
|
|
|
|
|
struct HandlerEntry {
|
|
|
|
constexpr HandlerEntry() = default;
|
|
|
|
constexpr HandlerEntry(folly::StringPiece n, Handler h)
|
|
|
|
: name(n), handler(h) {}
|
|
|
|
|
|
|
|
folly::StringPiece name;
|
|
|
|
Handler handler = nullptr;
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr auto kMountHandlers = [] {
|
|
|
|
std::array<HandlerEntry, 6> handlers;
|
2021-02-04 23:32:02 +03:00
|
|
|
handlers[folly::to_underlying(mountProcs::null)] = {
|
|
|
|
"NULL", &MountdServerProcessor::null};
|
|
|
|
handlers[folly::to_underlying(mountProcs::mnt)] = {
|
|
|
|
"MNT", &MountdServerProcessor::mount};
|
|
|
|
handlers[folly::to_underlying(mountProcs::dump)] = {
|
|
|
|
"DUMP", &MountdServerProcessor::dump};
|
|
|
|
handlers[folly::to_underlying(mountProcs::umnt)] = {
|
|
|
|
"UMOUNT", &MountdServerProcessor::umount};
|
|
|
|
handlers[folly::to_underlying(mountProcs::umntAll)] = {
|
2021-02-01 20:26:33 +03:00
|
|
|
"UMOUNTALL", &MountdServerProcessor::umountAll};
|
2021-02-04 23:32:02 +03:00
|
|
|
handlers[folly::to_underlying(mountProcs::exprt)] = {
|
|
|
|
"EXPORT", &MountdServerProcessor::exprt};
|
2021-02-01 20:26:33 +03:00
|
|
|
|
|
|
|
return handlers;
|
|
|
|
}();
|
|
|
|
|
2021-02-04 23:32:02 +03:00
|
|
|
} // namespace
|
|
|
|
|
2021-02-01 20:26:33 +03:00
|
|
|
folly::Future<folly::Unit> MountdServerProcessor::null(
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Cursor /*deser*/,
|
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid) {
|
2021-02-04 03:43:32 +03:00
|
|
|
serializeReply(ser, accept_stat::SUCCESS, xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
folly::Future<folly::Unit> MountdServerProcessor::mount(
|
2021-02-04 04:52:36 +03:00
|
|
|
folly::io::Cursor deser,
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid) {
|
2021-02-04 03:43:32 +03:00
|
|
|
serializeReply(ser, accept_stat::SUCCESS, xid);
|
2021-02-04 04:52:36 +03:00
|
|
|
|
|
|
|
AbsolutePath path{XdrTrait<std::string>::deserialize(deser)};
|
|
|
|
XLOG(DBG7) << "Mounting: " << path;
|
|
|
|
|
|
|
|
auto mounts = mountPoints_.rlock();
|
|
|
|
auto found = mounts->find(path);
|
|
|
|
if (found != mounts->end()) {
|
|
|
|
XdrTrait<mountstat3>::serialize(ser, mountstat3::MNT3_OK);
|
|
|
|
XdrTrait<mountres3_ok>::serialize(
|
2021-02-04 23:32:02 +03:00
|
|
|
ser, mountres3_ok{{found->second}, {auth_flavor::AUTH_UNIX}});
|
2021-02-04 04:52:36 +03:00
|
|
|
} else {
|
|
|
|
XdrTrait<mountstat3>::serialize(ser, mountstat3::MNT3ERR_NOENT);
|
|
|
|
}
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
folly::Future<folly::Unit> MountdServerProcessor::dump(
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Cursor /*deser*/,
|
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid) {
|
2021-02-04 03:43:32 +03:00
|
|
|
serializeReply(ser, accept_stat::PROC_UNAVAIL, xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
folly::Future<folly::Unit> MountdServerProcessor::umount(
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Cursor /*deser*/,
|
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid) {
|
2021-02-04 03:43:32 +03:00
|
|
|
serializeReply(ser, accept_stat::PROC_UNAVAIL, xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
folly::Future<folly::Unit> MountdServerProcessor::umountAll(
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Cursor /*deser*/,
|
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid) {
|
2021-02-04 03:43:32 +03:00
|
|
|
serializeReply(ser, accept_stat::PROC_UNAVAIL, xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
folly::Future<folly::Unit> MountdServerProcessor::exprt(
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Cursor /*deser*/,
|
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid) {
|
2021-02-04 23:32:02 +03:00
|
|
|
serializeReply(ser, accept_stat::SUCCESS, xid);
|
|
|
|
/*
|
|
|
|
* In theory, we're supposed to return a list of exported FS, but since
|
|
|
|
* EdenFS is not intended to be exposed as a generic NFS server, properly
|
|
|
|
* answering with the list of exported FS isn't necessary. For now we can
|
|
|
|
* just pretend that we don't export anything.
|
|
|
|
*
|
|
|
|
* When using libnfs, this may be called during mount to recursively mount
|
|
|
|
* nested NFS mounts.
|
|
|
|
*/
|
|
|
|
XdrTrait<bool>::serialize(ser, false);
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
folly::Future<folly::Unit> MountdServerProcessor::dispatchRpc(
|
2021-02-04 03:43:32 +03:00
|
|
|
folly::io::Cursor deser,
|
|
|
|
folly::io::Appender ser,
|
2021-02-01 20:26:33 +03:00
|
|
|
uint32_t xid,
|
|
|
|
uint32_t progNumber,
|
|
|
|
uint32_t progVersion,
|
|
|
|
uint32_t procNumber) {
|
2021-02-04 03:43:32 +03:00
|
|
|
if (progNumber != kMountdProgNumber) {
|
|
|
|
serializeReply(ser, accept_stat::PROG_UNAVAIL, xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
2021-02-04 03:43:32 +03:00
|
|
|
if (progVersion != kMountdProgVersion) {
|
|
|
|
serializeReply(ser, accept_stat::PROG_MISMATCH, xid);
|
|
|
|
XdrTrait<mismatch_info>::serialize(
|
|
|
|
ser, mismatch_info{kMountdProgVersion, kMountdProgVersion});
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (procNumber >= kMountHandlers.size()) {
|
|
|
|
XLOG(ERR) << "Invalid procedure: " << procNumber;
|
2021-02-04 03:43:32 +03:00
|
|
|
serializeReply(ser, accept_stat::PROC_UNAVAIL, xid);
|
2021-02-01 20:26:33 +03:00
|
|
|
return folly::unit;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto handlerEntry = kMountHandlers[procNumber];
|
|
|
|
|
|
|
|
XLOG(DBG7) << handlerEntry.name;
|
|
|
|
return (this->*handlerEntry.handler)(std::move(deser), std::move(ser), xid);
|
|
|
|
}
|
|
|
|
|
2021-02-04 04:52:36 +03:00
|
|
|
void MountdServerProcessor::registerMount(
|
|
|
|
AbsolutePathPiece path,
|
|
|
|
InodeNumber ino) {
|
|
|
|
auto map = mountPoints_.wlock();
|
|
|
|
auto [iter, inserted] = map->emplace(path.copy(), ino);
|
|
|
|
XCHECK_EQ(inserted, true);
|
|
|
|
}
|
2021-02-01 20:26:33 +03:00
|
|
|
|
2021-02-04 04:52:36 +03:00
|
|
|
void MountdServerProcessor::unregisterMount(AbsolutePathPiece path) {
|
|
|
|
auto map = mountPoints_.wlock();
|
|
|
|
auto numRemoved = map->erase(path.copy());
|
|
|
|
XCHECK_EQ(numRemoved, 1u);
|
|
|
|
}
|
|
|
|
|
2021-02-04 04:52:36 +03:00
|
|
|
Mountd::Mountd(bool registerWithRpcbind)
|
2021-02-04 04:52:36 +03:00
|
|
|
: proc_(std::make_shared<MountdServerProcessor>()), server_(proc_) {
|
2021-02-04 04:52:36 +03:00
|
|
|
if (registerWithRpcbind) {
|
|
|
|
server_.registerService(kMountdProgNumber, kMountdProgVersion);
|
|
|
|
}
|
2021-02-01 20:26:33 +03:00
|
|
|
}
|
|
|
|
|
2021-02-04 04:52:36 +03:00
|
|
|
void Mountd::registerMount(AbsolutePathPiece path, InodeNumber ino) {
|
|
|
|
proc_->registerMount(path, ino);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Mountd::unregisterMount(AbsolutePathPiece path) {
|
|
|
|
proc_->unregisterMount(path);
|
|
|
|
}
|
|
|
|
|
2021-02-01 20:26:33 +03:00
|
|
|
} // namespace facebook::eden
|