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) {
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
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);
}
dout(20) << __func__ << " s=" << s << " name=" << s->info.inst.name
<< " v=" << version << dendl;
- _mark_dirty(s);
+ _mark_dirty(s, false);
replay_advance_version();
}
get_client_sessions(f);
}
- void replay_open_sessions(map<client_t,entity_inst_t>& client_map,
+ 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) {
+ // 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.
+ ceph_assert(version + client_map.size() >= event_cmapv);
+ unsigned already_saved = client_map.size() - (event_cmapv - version);
for (map<client_t,entity_inst_t>::iterator p = client_map.begin();
p != client_map.end();
++p) {
if (q != client_metadata_map.end())
s->info.client_metadata.merge(q->second);
+ if (already_saved > 0) {
+ ceph_assert(s->is_open());
+ --already_saved;
+ continue;
+ }
+
set_state(s, Session::STATE_OPEN);
replay_dirty_session(s);
}
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:
/**
* 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
} 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();
}
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();
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();
}