sapling/eden/fs/service/EdenStateDir.h
Xavier Deguillard f2e7099799 nfs: allow mountd and nfsd to bind to a unix socket on macOS
Summary:
Due to NFS being designed as a network filesystem, it default to binding on a
TCP socket. For EdenFS, since we're not expecting to mount an actual remote
filesystem, we bind these sockets to localhost. Unfortunately, TCP sockets have
some inherent overhead due to being designed to be reliable over a non-reliable
medium.

On macOS, Apple provides a way to mount an NFS server that is listening on a
unix domain socket. Thanks for unix socket being reliable, the TCP overhead
goes away leading to some higher throughput and lower latency for the NFS
server. For EdenFS, timing `rg foobar` over a directory containing 27k files gives:

NFS over TCP:
rg foobar > /dev/null  0.80s user 5.44s system 567% cpu 1.100 total

NFS over UDS:
rg foobar > /dev/null  0.77s user 5.27s system 679% cpu 0.888 total

osxfuse:
rg foobar > /dev/null  0.87s user 5.59s system 662% cpu 0.975 total

The main drawback of going through a unix socket is that D27717945 (bcf6aa465c) appears to
no longer be effective due to
8f02f2a044/bsd/nfs/nfs_vfsops.c (L3739)

Reviewed By: kmancini

Differential Revision: D28261422

fbshipit-source-id: 25dc1dc78cdb50d6c6550a86ef01ea2c894c110f
2021-05-12 13:06:57 -07:00

118 lines
3.0 KiB
C++

/*
* 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.
*/
#pragma once
#include <folly/File.h>
#include <folly/Range.h>
#include <folly/portability/SysStat.h>
#include "eden/fs/utils/PathFuncs.h"
namespace folly {
class File;
}
namespace facebook {
namespace eden {
/**
* EdenStateDir exists for managing access to the user's .eden directory.
*
* Note that this refers to the user's main .eden directory where Eden stores
* its state, and not the virtual .eden directories that appear in all mounted
* Eden checkouts.
*/
class EdenStateDir {
public:
explicit EdenStateDir(AbsolutePathPiece path);
~EdenStateDir();
/**
* Acquire the main on-disk edenfs lock.
*
* Callers should acquire the on-disk lock before performing any other
* operations on the EdenStateDir, to ensure that only one process can use the
* state directory at a time.
*
* Returns true if the lock was acquired successfully, or false if we failed
* to acquire the lock (likely due to another process holding it).
* May throw an exception on other errors (e.g., insufficient permissions to
* create the lock file, out of disk space, etc).
*/
FOLLY_NODISCARD bool acquireLock();
/**
* Take over the lock file from another process.
*/
void takeoverLock(folly::File lockFile);
/**
* Extract the lock file without releasing it.
*
* This is primarily intended to be used to transfer the lock to another
* process. This file descriptor can be transferred to the other process,
* which will then pass it to the takeoverLock() method of their EdenStateDir
* object.
*/
folly::File extractLock();
/**
* Returns true if the Eden state directory lock is currently held by this
* EdenStateDir object.
*/
bool isLocked() const;
/**
* Returns true if the on-disk lock file is still valid. Returns false if the
* lock file file has been renamed or deleted.
*/
bool isLockValid() const;
/**
* Get the path to the state directory.
*/
AbsolutePathPiece getPath() const {
return path_;
}
/**
* Get the path to Eden's thrift socket.
*/
AbsolutePath getThriftSocketPath() const;
/**
* Get the path to Eden's takeover socket.
*/
AbsolutePath getTakeoverSocketPath() const;
/**
* Get the path to Eden's NFS mountd socket.
*/
AbsolutePath getMountdSocketPath() const;
/**
* Get the path to the directory where state for a specific checkout is
* stored.
*
* Note that the checkoutID string must meet the requirements of
* PathComponent: it must not contain internal directory separators and must
* not be "." or "..".
*/
AbsolutePath getCheckoutStateDir(folly::StringPiece checkoutID) const;
private:
static void writePidToLockFile(folly::File& lockFile);
AbsolutePath path_;
AbsolutePath lockPath_;
folly::File lockFile_;
struct stat lockFileStat_ = {};
};
} // namespace eden
} // namespace facebook