mirror of
https://github.com/ceph/ceph
synced 2025-01-20 10:01:45 +00:00
Merge PR #28456 into master
* refs/pull/28456/head: mds: ignore sessionmap version mismatch if mds_wipe_sessions is set mds: fix corner case of replaying open sessions Reviewed-by: Patrick Donnelly <pdonnell@redhat.com>
This commit is contained in:
commit
c735b901da
@ -3221,7 +3221,7 @@ void Server::apply_allocated_inos(MDRequestRef& mdr, Session *session)
|
||||
ceph_assert(session);
|
||||
session->pending_prealloc_inos.subtract(mdr->prealloc_inos);
|
||||
session->info.prealloc_inos.insert(mdr->prealloc_inos);
|
||||
mds->sessionmap.mark_dirty(session);
|
||||
mds->sessionmap.mark_dirty(session, !mdr->used_prealloc_ino);
|
||||
mds->inotable->apply_alloc_ids(mdr->prealloc_inos);
|
||||
}
|
||||
if (mdr->used_prealloc_ino) {
|
||||
|
@ -669,12 +669,13 @@ void SessionMap::touch_session(Session *session)
|
||||
session->last_cap_renew = clock::now();
|
||||
}
|
||||
|
||||
void SessionMap::_mark_dirty(Session *s)
|
||||
void SessionMap::_mark_dirty(Session *s, bool may_save)
|
||||
{
|
||||
if (dirty_sessions.count(s->info.inst.name))
|
||||
return;
|
||||
|
||||
if (dirty_sessions.size() >= g_conf()->mds_sessionmap_keys_per_op) {
|
||||
if (may_save &&
|
||||
dirty_sessions.size() >= g_conf()->mds_sessionmap_keys_per_op) {
|
||||
// Pre-empt the usual save() call from journal segment trim, in
|
||||
// order to avoid building up an oversized OMAP update operation
|
||||
// from too many sessions modified at once
|
||||
@ -685,12 +686,12 @@ void SessionMap::_mark_dirty(Session *s)
|
||||
dirty_sessions.insert(s->info.inst.name);
|
||||
}
|
||||
|
||||
void SessionMap::mark_dirty(Session *s)
|
||||
void SessionMap::mark_dirty(Session *s, bool may_save)
|
||||
{
|
||||
dout(20) << __func__ << " s=" << s << " name=" << s->info.inst.name
|
||||
<< " v=" << version << dendl;
|
||||
|
||||
_mark_dirty(s);
|
||||
_mark_dirty(s, may_save);
|
||||
version++;
|
||||
s->pop_pv(version);
|
||||
}
|
||||
@ -700,7 +701,7 @@ void SessionMap::replay_dirty_session(Session *s)
|
||||
dout(20) << __func__ << " s=" << s << " name=" << s->info.inst.name
|
||||
<< " v=" << version << dendl;
|
||||
|
||||
_mark_dirty(s);
|
||||
_mark_dirty(s, false);
|
||||
|
||||
replay_advance_version();
|
||||
}
|
||||
@ -711,6 +712,46 @@ void SessionMap::replay_advance_version()
|
||||
projected = version;
|
||||
}
|
||||
|
||||
void SessionMap::replay_open_sessions(version_t event_cmapv,
|
||||
map<client_t,entity_inst_t>& client_map,
|
||||
map<client_t,client_metadata_t>& client_metadata_map)
|
||||
{
|
||||
unsigned already_saved;
|
||||
|
||||
if (version + client_map.size() < event_cmapv)
|
||||
goto bad;
|
||||
|
||||
// Server::finish_force_open_sessions() marks sessions dirty one by one.
|
||||
// Marking a session dirty may flush all existing dirty sessions. So it's
|
||||
// possible that some sessions are already saved in sessionmap.
|
||||
already_saved = client_map.size() - (event_cmapv - version);
|
||||
for (const auto& p : client_map) {
|
||||
Session *s = get_or_add_session(p.second);
|
||||
auto q = client_metadata_map.find(p.first);
|
||||
if (q != client_metadata_map.end())
|
||||
s->info.client_metadata.merge(q->second);
|
||||
|
||||
if (already_saved > 0) {
|
||||
if (s->is_closed())
|
||||
goto bad;
|
||||
|
||||
--already_saved;
|
||||
continue;
|
||||
}
|
||||
|
||||
set_state(s, Session::STATE_OPEN);
|
||||
replay_dirty_session(s);
|
||||
}
|
||||
return;
|
||||
|
||||
bad:
|
||||
mds->clog->error() << "error replaying open sessions(" << client_map.size()
|
||||
<< ") sessionmap v " << event_cmapv << " table " << version;
|
||||
ceph_assert(g_conf()->mds_wipe_sessions);
|
||||
mds->sessionmap.wipe();
|
||||
mds->sessionmap.set_version(event_cmapv);
|
||||
}
|
||||
|
||||
version_t SessionMap::mark_projected(Session *s)
|
||||
{
|
||||
dout(20) << __func__ << " s=" << s << " name=" << s->info.inst.name
|
||||
|
@ -662,21 +662,6 @@ public:
|
||||
get_client_sessions(f);
|
||||
}
|
||||
|
||||
void replay_open_sessions(map<client_t,entity_inst_t>& client_map,
|
||||
map<client_t,client_metadata_t>& client_metadata_map) {
|
||||
for (map<client_t,entity_inst_t>::iterator p = client_map.begin();
|
||||
p != client_map.end();
|
||||
++p) {
|
||||
Session *s = get_or_add_session(p->second);
|
||||
auto q = client_metadata_map.find(p->first);
|
||||
if (q != client_metadata_map.end())
|
||||
s->info.client_metadata.merge(q->second);
|
||||
|
||||
set_state(s, Session::STATE_OPEN);
|
||||
replay_dirty_session(s);
|
||||
}
|
||||
}
|
||||
|
||||
// helpers
|
||||
entity_inst_t& get_inst(entity_name_t w) {
|
||||
ceph_assert(session_map.count(w));
|
||||
@ -724,7 +709,7 @@ protected:
|
||||
std::set<entity_name_t> dirty_sessions;
|
||||
std::set<entity_name_t> null_sessions;
|
||||
bool loaded_legacy = false;
|
||||
void _mark_dirty(Session *session);
|
||||
void _mark_dirty(Session *session, bool may_save);
|
||||
public:
|
||||
|
||||
/**
|
||||
@ -735,7 +720,7 @@ public:
|
||||
* to the backing store. Must have called
|
||||
* mark_projected previously for this session.
|
||||
*/
|
||||
void mark_dirty(Session *session);
|
||||
void mark_dirty(Session *session, bool may_save=true);
|
||||
|
||||
/**
|
||||
* Advance the projected version, and mark this
|
||||
@ -763,6 +748,14 @@ public:
|
||||
*/
|
||||
void replay_advance_version();
|
||||
|
||||
/**
|
||||
* During replay, open sessions, advance versions and
|
||||
* mark these sessions as dirty.
|
||||
*/
|
||||
void replay_open_sessions(version_t event_cmapv,
|
||||
map<client_t,entity_inst_t>& client_map,
|
||||
map<client_t,client_metadata_t>& client_metadata_map);
|
||||
|
||||
/**
|
||||
* For these session IDs, if a session exists with this ID, and it has
|
||||
* dirty completed_requests, then persist it immediately
|
||||
|
@ -1481,12 +1481,13 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup)
|
||||
}
|
||||
}
|
||||
if (sessionmapv) {
|
||||
unsigned diff = (used_preallocated_ino && !preallocated_inos.empty()) ? 2 : 1;
|
||||
if (mds->sessionmap.get_version() >= sessionmapv) {
|
||||
dout(10) << "EMetaBlob.replay sessionmap v " << sessionmapv
|
||||
<< " <= table " << mds->sessionmap.get_version() << dendl;
|
||||
} else if (mds->sessionmap.get_version() + 2 >= sessionmapv) {
|
||||
} else if (mds->sessionmap.get_version() + diff == sessionmapv) {
|
||||
dout(10) << "EMetaBlob.replay sessionmap v " << sessionmapv
|
||||
<< " -(1|2) == table " << mds->sessionmap.get_version()
|
||||
<< " - " << diff << " == table " << mds->sessionmap.get_version()
|
||||
<< " prealloc " << preallocated_inos
|
||||
<< " used " << used_preallocated_ino
|
||||
<< dendl;
|
||||
@ -1512,16 +1513,16 @@ void EMetaBlob::replay(MDSRank *mds, LogSegment *logseg, MDSlaveUpdate *slaveup)
|
||||
|
||||
} else {
|
||||
dout(10) << "EMetaBlob.replay no session for " << client_name << dendl;
|
||||
if (used_preallocated_ino) {
|
||||
if (used_preallocated_ino)
|
||||
mds->sessionmap.replay_advance_version();
|
||||
}
|
||||
|
||||
if (!preallocated_inos.empty())
|
||||
mds->sessionmap.replay_advance_version();
|
||||
}
|
||||
ceph_assert(sessionmapv == mds->sessionmap.get_version());
|
||||
} else {
|
||||
mds->clog->error() << "journal replay sessionmap v " << sessionmapv
|
||||
<< " -(1|2) > table " << mds->sessionmap.get_version();
|
||||
mds->clog->error() << "EMetaBlob.replay sessionmap v " << sessionmapv
|
||||
<< " - " << diff << " > table " << mds->sessionmap.get_version();
|
||||
ceph_assert(g_conf()->mds_wipe_sessions);
|
||||
mds->sessionmap.wipe();
|
||||
mds->sessionmap.set_version(sessionmapv);
|
||||
@ -1615,7 +1616,7 @@ void ESession::replay(MDSRank *mds)
|
||||
if (mds->sessionmap.get_version() >= cmapv) {
|
||||
dout(10) << "ESession.replay sessionmap " << mds->sessionmap.get_version()
|
||||
<< " >= " << cmapv << ", noop" << dendl;
|
||||
} else {
|
||||
} else if (mds->sessionmap.get_version() + 1 == cmapv) {
|
||||
dout(10) << "ESession.replay sessionmap " << mds->sessionmap.get_version()
|
||||
<< " < " << cmapv << " " << (open ? "open":"close") << " " << client_inst << dendl;
|
||||
Session *session;
|
||||
@ -1646,6 +1647,12 @@ void ESession::replay(MDSRank *mds)
|
||||
mds->sessionmap.replay_advance_version();
|
||||
}
|
||||
ceph_assert(mds->sessionmap.get_version() == cmapv);
|
||||
} else {
|
||||
mds->clog->error() << "ESession.replay sessionmap v " << cmapv
|
||||
<< " - 1 > table " << mds->sessionmap.get_version();
|
||||
ceph_assert(g_conf()->mds_wipe_sessions);
|
||||
mds->sessionmap.wipe();
|
||||
mds->sessionmap.set_version(cmapv);
|
||||
}
|
||||
|
||||
if (inos.size() && inotablev) {
|
||||
@ -1778,8 +1785,7 @@ void ESessions::replay(MDSRank *mds)
|
||||
} else {
|
||||
dout(10) << "ESessions.replay sessionmap " << mds->sessionmap.get_version()
|
||||
<< " < " << cmapv << dendl;
|
||||
mds->sessionmap.replay_open_sessions(client_map, client_metadata_map);
|
||||
ceph_assert(mds->sessionmap.get_version() == cmapv);
|
||||
mds->sessionmap.replay_open_sessions(cmapv, client_map, client_metadata_map);
|
||||
}
|
||||
update_segment();
|
||||
}
|
||||
@ -2062,9 +2068,7 @@ void EUpdate::replay(MDSRank *mds)
|
||||
decode(cm, blp);
|
||||
if (!blp.end())
|
||||
decode(cmm, blp);
|
||||
mds->sessionmap.replay_open_sessions(cm, cmm);
|
||||
|
||||
ceph_assert(mds->sessionmap.get_version() == cmapv);
|
||||
mds->sessionmap.replay_open_sessions(cmapv, cm, cmm);
|
||||
}
|
||||
}
|
||||
update_segment();
|
||||
@ -2910,15 +2914,7 @@ void EImportStart::replay(MDSRank *mds)
|
||||
decode(cm, blp);
|
||||
if (!blp.end())
|
||||
decode(cmm, blp);
|
||||
mds->sessionmap.replay_open_sessions(cm, cmm);
|
||||
|
||||
if (mds->sessionmap.get_version() != cmapv) {
|
||||
derr << "sessionmap version " << mds->sessionmap.get_version()
|
||||
<< " != cmapv " << cmapv << dendl;
|
||||
mds->clog->error() << "failure replaying journal (EImportStart)";
|
||||
mds->damaged();
|
||||
ceph_abort(); // Should be unreachable because damaged() calls respawn()
|
||||
}
|
||||
mds->sessionmap.replay_open_sessions(cmapv, cm, cmm);
|
||||
}
|
||||
update_segment();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user