sapling/eden/fs/service/main.cpp
Wez Furlong 467c417ccb re-organize the fuse Channel and Session code
Summary:
The higher level goal is to make it easier to deal
with the graceful restart scenario.

This diff removes the SessionDeleter class and effectively renames
the Channel class to FuseChannel.  The FuseChannel represents
the channel to the kernel; it can be constructed from a fuse
device descriptor that has been obtained either from the privhelper
at mount time, or from the graceful restart procedure.  Importantly
for graceful restart, it is possible to move the fuse device
descriptor out of the FuseChannel so that it can be transferred
to a new eden process.

The graceful restart procedure requires a bit more control over
the lifecycle of the fuse event loop so this diff also takes over
managing the thread pool for the worker threads.  The threads
are owned by the MountPoint class which continues to be responsible
for starting and stopping the fuse session and notifying EdenServer
when it has finished.  A nice side effect of this change is that
we can remove a couple of inelegant aspects of the integration;
the stack size env var stuff and the redundant extra thread
to wait for the loop to finish.

I opted to expose the dispatcher ops struct via an `extern` to
simplify the code in the MountPoint class and avoid adding special
interfaces for passing the ops around; they're constant anyway
so this doesn't feel especially egregious.

Reviewed By: bolinfest

Differential Revision: D5751521

fbshipit-source-id: 5ba4fff48f3efb31a809adfc7787555711f649c9
2017-09-08 19:25:34 -07:00

106 lines
3.7 KiB
C++

/*
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#include <folly/Conv.h>
#include <folly/experimental/FunctionScheduler.h>
#include <folly/experimental/logging/Init.h>
#include <folly/experimental/logging/xlog.h>
#include <folly/init/Init.h>
#include <gflags/gflags.h>
#include <pwd.h>
#include <sysexits.h>
#include "EdenServer.h"
#include "eden/fs/fuse/privhelper/PrivHelper.h"
#include "eden/fs/fuse/privhelper/UserInfo.h"
DEFINE_bool(allowRoot, false, "Allow running eden directly as root");
DEFINE_string(edenDir, "", "The path to the .eden directory");
DEFINE_string(
etcEdenDir,
"/etc/eden",
"The directory holding all system configuration files");
DEFINE_string(configPath, "", "The path of the ~/.edenrc config file");
DEFINE_string(rocksPath, "", "The path to the local RocksDB store");
// The logging configuration parameter. We default to DBG2 for everything in
// eden, and WARNING for all other categories.
DEFINE_string(logging, ".=WARNING,eden=DBG2", "Logging configuration");
using namespace facebook::eden::fusell;
using namespace facebook::eden;
int main(int argc, char **argv) {
// Make sure to run this before any flag values are read.
folly::init(&argc, &argv);
// Determine the desired user and group ID.
if (geteuid() != 0) {
fprintf(stderr, "error: edenfs must be started as root\n");
return EX_NOPERM;
}
auto identity = UserInfo::lookup();
if (identity.getUid() == 0 && !FLAGS_allowRoot) {
fprintf(
stderr,
"error: you appear to be running eden as root, "
"rather than using\n"
"sudo or a setuid binary. This is normally undesirable.\n"
"Pass in the --allowRoot flag if you really mean to run "
"eden as root.\n");
return EX_USAGE;
}
// Set some default glog settings, to be applied unless overridden on the
// command line
gflags::SetCommandLineOptionWithMode(
"logtostderr", "1", gflags::SET_FLAGS_DEFAULT);
gflags::SetCommandLineOptionWithMode(
"minloglevel", "0", gflags::SET_FLAGS_DEFAULT);
// Fork the privhelper process, then drop privileges in the main process.
// This should be done as early as possible, so that everything else we do
// runs only with normal user privileges.
//
// (It might be better to do this even before calling folly::init() and
// parsing command line arguments. The downside would be that we then
// shouldn't really use glog in the privhelper process, since it won't have
// been set up and configured based on the command line flags.)
fusell::startPrivHelper(identity);
identity.dropPrivileges();
folly::initLoggingGlogStyle(FLAGS_logging, folly::LogLevel::WARNING);
XLOG(INFO) << "Starting edenfs. UID=" << identity.getUid()
<< ", GID=" << identity.getGid() << ", PID=" << getpid();
if (FLAGS_edenDir.empty()) {
fprintf(stderr, "error: the --edenDir argument is required\n");
return EX_USAGE;
}
auto edenDir = canonicalPath(FLAGS_edenDir);
auto etcEdenDir = canonicalPath(FLAGS_etcEdenDir);
auto rocksPath = FLAGS_rocksPath.empty()
? edenDir + RelativePathPiece{"storage/rocks-db"}
: canonicalPath(FLAGS_rocksPath);
AbsolutePath configPath;
std::string configPathStr = FLAGS_configPath;
if (configPathStr.empty()) {
configPath = identity.getHomeDirectory() + PathComponentPiece{".edenrc"};
} else {
configPath = canonicalPath(configPathStr);
}
EdenServer server(edenDir, etcEdenDir, configPath, rocksPath);
server.run();
return EX_OK;
}