#include <iostream>
#include <string>
-using namespace std;
#include "include/ceph_features.h"
#include "include/compat.h"
+#include "include/random.h"
#include "common/config.h"
#include "common/strtol.h"
#include "common/Timer.h"
#include "common/ceph_argparse.h"
#include "common/pick_address.h"
+#include "common/Preforker.h"
#include "global/global_init.h"
#include "global/signal_handler.h"
#include "perfglue/heap_profiler.h"
-#include "include/assert.h"
+#include "include/ceph_assert.h"
#define dout_context g_ceph_context
#define dout_subsys ceph_subsys_mds
static void usage()
{
- cout << "usage: ceph-mds -i <ID> [flags] [[--hot-standby][rank]]\n"
+ cout << "usage: ceph-mds -i <ID> [flags]\n"
<< " -m monitorip:port\n"
<< " connect to monitor at given address\n"
<< " --debug_mds n\n"
<< " debug MDS level (e.g. 10)\n"
- << " --hot-standby rank\n"
- << " start up as a hot standby for rank\n"
<< std::endl;
generic_server_usage();
}
-static int parse_rank(const char *opt_name, const std::string &val)
-{
- std::string err;
- int ret = strict_strtol(val.c_str(), 10, &err);
- if (!err.empty()) {
- derr << "error parsing " << opt_name << ": failed to parse rank. "
- << "It must be an int." << "\n" << dendl;
- usage();
- }
- return ret;
-}
-
-
-
MDSDaemon *mds = NULL;
vector<const char*> args;
argv_to_vec(argc, argv, args);
- env_to_vec(args);
+ if (args.empty()) {
+ cerr << argv[0] << ": -h or --help for usage" << std::endl;
+ exit(1);
+ }
+ if (ceph_argparse_need_usage(args)) {
+ usage();
+ exit(0);
+ }
auto cct = global_init(NULL, args,
CEPH_ENTITY_TYPE_MDS, CODE_ENVIRONMENT_DAEMON,
if (ceph_argparse_double_dash(args, i)) {
break;
}
- else if (ceph_argparse_flag(args, i, "--help", "-h", (char*)NULL)) {
- // exit(1) will be called in the usage()
- usage();
- }
else if (ceph_argparse_witharg(args, i, &val, "--hot-standby", (char*)NULL)) {
- int r = parse_rank("hot-standby", val);
- dout(0) << "requesting standby_replay for mds." << r << dendl;
- char rb[32];
- snprintf(rb, sizeof(rb), "%d", r);
- g_conf->set_val("mds_standby_for_rank", rb);
- g_conf->set_val("mds_standby_replay", "true");
- g_conf->apply_changes(NULL);
+ dout(0) << "--hot-standby is obsolete and has no effect" << dendl;
}
else {
derr << "Error: can't understand argument: " << *i << "\n" << dendl;
- usage();
+ exit(1);
}
}
- pick_addresses(g_ceph_context, CEPH_PICK_ADDRESS_PUBLIC);
+ Preforker forker;
+
+ entity_addrvec_t addrs;
+ pick_addresses(g_ceph_context, CEPH_PICK_ADDRESS_PUBLIC, &addrs);
// Normal startup
- if (g_conf->name.has_default_id()) {
+ if (g_conf()->name.has_default_id()) {
derr << "must specify '-i name' with the ceph-mds instance name" << dendl;
- usage();
+ exit(1);
}
- if (g_conf->name.get_id().empty() ||
- (g_conf->name.get_id()[0] >= '0' && g_conf->name.get_id()[0] <= '9')) {
- derr << "deprecation warning: MDS id '" << g_conf->name
- << "' is invalid and will be forbidden in a future version. "
+ if (g_conf()->name.get_id().empty() ||
+ (g_conf()->name.get_id()[0] >= '0' && g_conf()->name.get_id()[0] <= '9')) {
+ derr << "MDS id '" << g_conf()->name << "' is invalid. "
"MDS names may not start with a numeric digit." << dendl;
+ exit(1);
+ }
+
+ if (global_init_prefork(g_ceph_context) >= 0) {
+ std::string err;
+ int r = forker.prefork(err);
+ if (r < 0) {
+ cerr << err << std::endl;
+ return r;
+ }
+ if (forker.is_parent()) {
+ if (forker.parent_wait(err) != 0) {
+ return -ENXIO;
+ }
+ return 0;
+ }
+ global_init_postfork_start(g_ceph_context);
}
+ common_init_finish(g_ceph_context);
+ global_init_chdir(g_ceph_context);
- uint64_t nonce = 0;
- get_random_bytes((char*)&nonce, sizeof(nonce));
+ auto nonce = ceph::util::generate_random_number<uint64_t>();
- std::string public_msgr_type = g_conf->ms_public_type.empty() ? g_conf->get_val<std::string>("ms_type") : g_conf->ms_public_type;
+ std::string public_msgr_type = g_conf()->ms_public_type.empty() ? g_conf().get_val<std::string>("ms_type") : g_conf()->ms_public_type;
Messenger *msgr = Messenger::create(g_ceph_context, public_msgr_type,
entity_name_t::MDS(-1), "mds",
nonce, Messenger::HAS_MANY_CONNECTIONS);
if (!msgr)
- exit(1);
+ forker.exit(1);
msgr->set_cluster_protocol(CEPH_MDS_PROTOCOL);
- cout << "starting " << g_conf->name << " at " << msgr->get_myaddr()
+ cout << "starting " << g_conf()->name << " at " << msgr->get_myaddrs()
<< std::endl;
uint64_t required =
CEPH_FEATURE_OSDREPLYMUX;
msgr->set_policy(entity_name_t::TYPE_CLIENT,
Messenger::Policy::stateful_server(0));
- int r = msgr->bind(g_conf->public_addr);
+ int r = msgr->bindv(addrs);
if (r < 0)
- exit(1);
-
- global_init_daemonize(g_ceph_context);
- common_init_finish(g_ceph_context);
+ forker.exit(1);
+ // set up signal handlers, now that we've daemonized/forked.
+ init_async_signal_handler();
+ register_async_signal_handler(SIGHUP, sighup_handler);
+
// get monmap
MonClient mc(g_ceph_context);
if (mc.build_initial_monmap() < 0)
- return -1;
+ forker.exit(1);
global_init_chdir(g_ceph_context);
msgr->start();
// start mds
- mds = new MDSDaemon(g_conf->name.get_id().c_str(), msgr, &mc);
+ mds = new MDSDaemon(g_conf()->name.get_id().c_str(), msgr, &mc);
// in case we have to respawn...
mds->orig_argc = argc;
mds->orig_argv = argv;
+ if (g_conf()->daemonize) {
+ global_init_postfork_finish(g_ceph_context);
+ forker.daemonize();
+ }
+
r = mds->init();
if (r < 0) {
msgr->wait();
goto shutdown;
}
- // set up signal handlers, now that we've daemonized/forked.
- init_async_signal_handler();
- register_async_signal_handler(SIGHUP, sighup_handler);
register_async_signal_handler_oneshot(SIGINT, handle_mds_signal);
register_async_signal_handler_oneshot(SIGTERM, handle_mds_signal);
- if (g_conf->inject_early_sigterm)
+ if (g_conf()->inject_early_sigterm)
kill(getpid(), SIGTERM);
msgr->wait();