From 53c2255f204f2a38a70ea853c7f8cf0752f40641 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Wed, 6 Apr 2016 21:11:46 +0800 Subject: [PATCH] client: mount non-default filesystem by name To mount non-default filesytem, user needs to provide mds namespace ID. This is inconvenience. This patch makes user be able to mount filesystem by name. To do this, client first subscribes to FSMapUser. Subscribe to mdsmap. after knowning ID of the filesystem. Signed-off-by: Yan, Zheng --- src/client/Client.cc | 117 ++++++++++++++++++++++++++------------- src/client/Client.h | 4 ++ src/common/config_opts.h | 2 +- 3 files changed, 84 insertions(+), 39 deletions(-) diff --git a/src/client/Client.cc b/src/client/Client.cc index c632f12683c06..66794b7027011 100644 --- a/src/client/Client.cc +++ b/src/client/Client.cc @@ -59,6 +59,7 @@ #include "messages/MClientCapRelease.h" #include "messages/MMDSMap.h" #include "messages/MFSMap.h" +#include "messages/MFSMapUser.h" #include "mon/MonClient.h" @@ -244,7 +245,7 @@ Client::Client(Messenger *m, MonClient *mc) objecter_finisher(m->cct), tick_event(NULL), monclient(mc), messenger(m), whoami(m->get_myname().num()), - cap_epoch_barrier(0), fsmap(nullptr), + cap_epoch_barrier(0), fsmap(nullptr), fsmap_user(nullptr), last_tid(0), oldest_tid(0), last_flush_tid(1), initialized(false), authenticated(false), mounted(false), unmounting(false), @@ -489,18 +490,6 @@ int Client::init() monclient->set_want_keys(CEPH_ENTITY_TYPE_MDS | CEPH_ENTITY_TYPE_OSD); - std::string want = "mdsmap"; - const auto &want_ns = cct->_conf->client_mds_namespace; - if (want_ns != FS_CLUSTER_ID_NONE) { - std::ostringstream oss; - oss << want << "." << want_ns; - want = oss.str(); - } - ldout(cct, 10) << "Subscribing to map '" << want << "'" << dendl; - - monclient->sub_want(want, 0, 0); - monclient->renew_subs(); - // logger PerfCountersBuilder plb(cct, "client", l_c_first, l_c_last); plb.add_time_avg(l_c_reply, "reply", "Latency of receiving a reply on metadata request"); @@ -2378,6 +2367,9 @@ bool Client::ms_dispatch(Message *m) case CEPH_MSG_FS_MAP: handle_fs_map(static_cast(m)); break; + case CEPH_MSG_FS_MAP_USER: + handle_fs_map_user(static_cast(m)); + break; case CEPH_MSG_CLIENT_SESSION: handle_client_session(static_cast(m)); break; @@ -2448,6 +2440,17 @@ void Client::handle_fs_map(MFSMap *m) monclient->sub_got("fsmap", fsmap->get_epoch()); } +void Client::handle_fs_map_user(MFSMapUser *m) +{ + delete fsmap_user; + fsmap_user = new FSMapUser; + *fsmap_user = m->get_fsmap(); + m->put(); + + monclient->sub_got("fsmap.user", fsmap_user->get_epoch()); + signal_cond_list(waiting_for_fsmap); +} + void Client::handle_mds_map(MMDSMap* m) { if (m->get_epoch() < mdsmap->get_epoch()) { @@ -5292,6 +5295,49 @@ int Client::authenticate() return 0; } +int Client::fetch_fsmap(bool user) +{ + int r; + // Retrieve FSMap to enable looking up daemon addresses. We need FSMap + // rather than MDSMap because no one MDSMap contains all the daemons, and + // a `tell` can address any daemon. + version_t fsmap_latest; + do { + C_SaferCond cond; + monclient->get_version("fsmap", &fsmap_latest, NULL, &cond); + client_lock.Unlock(); + r = cond.wait(); + client_lock.Lock(); + } while (r == -EAGAIN); + + if (r < 0) { + lderr(cct) << "Failed to learn FSMap version: " << cpp_strerror(r) << dendl; + return r; + } + + ldout(cct, 10) << __func__ << " learned FSMap version " << fsmap_latest << dendl; + + if (user) { + if (fsmap_user == nullptr || fsmap_user->get_epoch() < fsmap_latest) { + monclient->sub_want("fsmap.user", fsmap_latest, CEPH_SUBSCRIBE_ONETIME); + monclient->renew_subs(); + wait_on_list(waiting_for_fsmap); + } + assert(fsmap_user != nullptr); + assert(fsmap_user->get_epoch() >= fsmap_latest); + } else { + if (fsmap == nullptr || fsmap->get_epoch() < fsmap_latest) { + monclient->sub_want("fsmap", fsmap_latest, CEPH_SUBSCRIBE_ONETIME); + monclient->renew_subs(); + wait_on_list(waiting_for_fsmap); + } + assert(fsmap != nullptr); + assert(fsmap->get_epoch() >= fsmap_latest); + } + ldout(cct, 10) << __func__ << " finished waiting for FSMap version " + << fsmap_latest << dendl; + return 0; +} /** * @@ -5316,34 +5362,11 @@ int Client::mds_command( return r; } - // Retrieve FSMap to enable looking up daemon addresses. We need FSMap - // rather than MDSMap because no one MDSMap contains all the daemons, and - // a `tell` can address any daemon. - version_t fsmap_latest; - do { - C_SaferCond cond; - monclient->get_version("fsmap", &fsmap_latest, NULL, &cond); - client_lock.Unlock(); - r = cond.wait(); - client_lock.Lock(); - } while (r == -EAGAIN); - ldout(cct, 20) << "Learned FSMap version " << fsmap_latest << dendl; - + r = fetch_fsmap(false); if (r < 0) { - lderr(cct) << "Failed to learn FSMap version: " << cpp_strerror(r) << dendl; return r; } - if (fsmap == nullptr || fsmap->get_epoch() < fsmap_latest) { - monclient->sub_want("fsmap", fsmap_latest, CEPH_SUBSCRIBE_ONETIME); - monclient->renew_subs(); - wait_on_list(waiting_for_fsmap); - } - assert(fsmap != nullptr); - assert(fsmap->get_epoch() >= fsmap_latest); - ldout(cct, 20) << "Finished waiting for FSMap version " << fsmap_latest - << dendl; - // Look up MDS target(s) of the command std::vector targets; r = resolve_mds(mds_spec, &targets); @@ -5445,9 +5468,27 @@ int Client::mount(const std::string &mount_root, bool require_mds) return r; } + std::string want = "mdsmap"; + const auto &mds_ns = cct->_conf->client_mds_namespace; + if (!mds_ns.empty()) { + r = fetch_fsmap(true); + if (r < 0) + return r; + fs_cluster_id_t cid = fsmap_user->get_fs_cid(mds_ns); + if (cid == FS_CLUSTER_ID_NONE) + return -ENOENT; + + std::ostringstream oss; + oss << want << "." << cid; + want = oss.str(); + } + ldout(cct, 10) << "Subscribing to map '" << want << "'" << dendl; + + monclient->sub_want(want, 0, 0); + monclient->renew_subs(); + tick(); // start tick - ldout(cct, 2) << "mounted: have mdsmap " << mdsmap->get_epoch() << dendl; if (require_mds) { while (1) { auto availability = mdsmap->is_cluster_available(); diff --git a/src/client/Client.h b/src/client/Client.h index da604f546e894..9a41b909e16ef 100644 --- a/src/client/Client.h +++ b/src/client/Client.h @@ -49,6 +49,7 @@ using std::fstream; #include "UserGroups.h" class FSMap; +class FSMapUser; class MonClient; class CephContext; @@ -289,10 +290,12 @@ protected: // FSMap, for when using mds_command list waiting_for_fsmap; FSMap *fsmap; + FSMapUser *fsmap_user; // MDS command state std::map commands; void handle_command_reply(MCommandReply *m); + int fetch_fsmap(bool user); int resolve_mds( const std::string &mds_spec, std::vector *targets); @@ -569,6 +572,7 @@ protected: // messaging void handle_mds_map(class MMDSMap *m); void handle_fs_map(class MFSMap *m); + void handle_fs_map_user(class MFSMapUser *m); void handle_osd_map(class MOSDMap *m); void handle_lease(MClientLease *m); diff --git a/src/common/config_opts.h b/src/common/config_opts.h index fe8353d846650..6c1d86d25462e 100644 --- a/src/common/config_opts.h +++ b/src/common/config_opts.h @@ -416,7 +416,7 @@ OPTION(client_try_dentry_invalidate, OPT_BOOL, true) // the client should try to OPTION(client_die_on_failed_remount, OPT_BOOL, true) OPTION(client_check_pool_perm, OPT_BOOL, true) OPTION(client_use_faked_inos, OPT_BOOL, false) -OPTION(client_mds_namespace, OPT_INT, -1) +OPTION(client_mds_namespace, OPT_STR, "") OPTION(crush_location, OPT_STR, "") // whitespace-separated list of key=value pairs describing crush location OPTION(crush_location_hook, OPT_STR, "") -- 2.39.5