From: Samuel Just Date: Thu, 7 Nov 2013 20:48:27 +0000 (-0800) Subject: OSDService: add osdmap reservation mechanism X-Git-Tag: v0.81~57^2~37 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=5abbbfeb372ac100977a71b8127490ede7ddc80c;p=ceph.git OSDService: add osdmap reservation mechanism The goal here is to be able to get "reserved" refs to next_map, and ensure that pgs won't see a newer map until the ref is "released". I haven't done a cute RAII trick here yet...probably not worth the effort. Signed-off-by: Samuel Just Reviewed-by: Greg Farnum Conflicts: src/osd/OSD.h Signed-off-by: Greg Farnum --- diff --git a/src/osd/OSD.cc b/src/osd/OSD.cc index 413ec50780fa..5f186acd56cd 100644 --- a/src/osd/OSD.cc +++ b/src/osd/OSD.cc @@ -5885,6 +5885,7 @@ void OSD::consume_map() service.expand_pg_num(service.get_osdmap(), osdmap); service.pre_publish_map(osdmap); + service.await_reserved_maps(); service.publish_map(osdmap); // scan pg's diff --git a/src/osd/OSD.h b/src/osd/OSD.h index 4f45f016ba13..10762dc664c4 100644 --- a/src/osd/OSD.h +++ b/src/osd/OSD.h @@ -372,12 +372,52 @@ public: * working from old maps. */ OSDMapRef next_osdmap; + Cond pre_publish_cond; void pre_publish_map(OSDMapRef map) { Mutex::Locker l(pre_publish_lock); next_osdmap = map; } void activate_map(); + /// map epochs reserved below + map map_reservations; + + /// gets ref to next_osdmap and registers the epoch as reserved + OSDMapRef get_nextmap_reserved() { + Mutex::Locker l(pre_publish_lock); + if (!next_osdmap) + return OSDMapRef(); + epoch_t e = next_osdmap->get_epoch(); + map::iterator i = + map_reservations.insert(make_pair(e, 0)).first; + i->second++; + return next_osdmap; + } + /// releases reservation on map + void release_map(OSDMapRef osdmap) { + Mutex::Locker l(pre_publish_lock); + map::iterator i = + map_reservations.find(osdmap->get_epoch()); + assert(i != map_reservations.end()); + assert(i->second > 0); + if (--(i->second) == 0) { + map_reservations.erase(i); + } + pre_publish_cond.Signal(); + } + /// blocks until there are no reserved maps prior to next_osdmap + void await_reserved_maps() { + Mutex::Locker l(pre_publish_lock); + assert(next_osdmap); + while (true) { + map::iterator i = map_reservations.begin(); + if (i == map_reservations.end() || i->first >= next_osdmap->get_epoch()) { + break; + } else { + pre_publish_cond.Wait(pre_publish_lock); + } + } + } ConnectionRef get_con_osd_cluster(int peer, epoch_t from_epoch); pair get_con_osd_hb(int peer, epoch_t from_epoch); // (back, front)