]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd, pg: clean up watchers on pg deletion and shutdown
authorJosh Durgin <josh.durgin@dreamhost.com>
Fri, 29 Jul 2011 19:28:26 +0000 (12:28 -0700)
committerJosh Durgin <josh.durgin@dreamhost.com>
Tue, 2 Aug 2011 21:17:14 +0000 (14:17 -0700)
Watchers and their object contexts need to be cleaned up so
they aren't used after the pg is gone. This happened if the
pool was deleted and the connection to the watcher was reset.

Signed-off-by: Josh Durgin <josh.durgin@dreamhost.com>
src/osd/OSD.cc
src/osd/PG.h
src/osd/ReplicatedPG.cc
src/osd/ReplicatedPG.h

index 094e2bb3b345f4472b3bef145450184c7720b0d7..e0cf1a7d35bb1ac48ca1f610c42113723c5df293 100644 (file)
@@ -4487,7 +4487,9 @@ void OSD::_remove_pg(PG *pg)
     int tr = store->queue_transaction(NULL, rmt);
     assert(tr == 0);
   }
-  
+
+  pg->remove_watchers();
+
   // remove from map
   pg_map.erase(pgid);
   unreg_last_pg_scrub(pg->info.pgid, pg->info.history.last_scrub_stamp);
index 50969a6f946c3c87d592fcdccb710d79ddf012fa..e9b834b063a325514921bce6d2c7c527c5598ff8 100644 (file)
@@ -1639,6 +1639,7 @@ public:
   virtual void on_role_change() = 0;
   virtual void on_change() = 0;
   virtual void on_shutdown() = 0;
+  virtual void remove_watchers() = 0;
 };
 
 //WRITE_CLASS_ENCODER(PG::Info::History)
index 5cc2b58c8e29926ada531d28262f60f4326c1046..eb86dacc3386c92fbcd5b3108ee57435f3cb729d 100644 (file)
@@ -1075,6 +1075,39 @@ void ReplicatedPG::do_complete_notify(Watch::Notification *notif, ObjectContext
   osd->complete_notify((void *)notif, obc);
 }
 
+void ReplicatedPG::remove_watcher(ObjectContext *obc, entity_name_t entity)
+{
+  dout(10) << "remove_watcher " << *obc << " " << entity << dendl;
+  map<entity_name_t, OSD::Session *>::iterator iter = obc->watchers.find(entity);
+  assert(iter != obc->watchers.end());
+  OSD::Session *session = iter->second;
+  dout(10) << "remove_watcher removing session " << session << dendl;
+  obc->watchers.erase(iter);
+  session->watches.erase(obc);
+  put_object_context(obc);
+  session->put();
+}
+
+void ReplicatedPG::remove_watchers()
+{
+  assert_locked();
+
+  dout(10) << "remove_watchers" << dendl;
+
+  osd->watch_lock.Lock();
+  for (map<sobject_t, ObjectContext*>::iterator iter = object_contexts.begin();
+       iter != object_contexts.end();
+       ++iter) {
+    ObjectContext *obc = iter->second;
+    for (map<entity_name_t, OSD::Session *>::iterator witer = obc->watchers.begin();
+        witer != obc->watchers.end();
+        ++witer) {
+      remove_watcher(obc, witer->first);
+    }
+  }
+  osd->watch_lock.Unlock();
+}
+
 // ========================================================================
 // low level osd ops
 
@@ -2321,11 +2354,7 @@ void ReplicatedPG::do_osd_op_effects(OpContext *ctx)
     
     if (ctx->watch_disconnect) {
       if (iter != obc->watchers.end()) {
-       dout(10) << " disconnected session " << iter->second << dendl;
-       obc->watchers.erase(iter);
-       session->watches.erase(obc);
-       put_object_context(obc);
-       iter->second->put();
+       remove_watcher(obc, entity);
       } else {
        assert(obc->unconnected_watchers.count(entity));
        obc->unconnected_watchers.erase(entity);
@@ -4320,6 +4349,7 @@ void ReplicatedPG::on_shutdown()
 {
   dout(10) << "on_shutdown" << dendl;
   apply_and_flush_repops(false);
+  remove_watchers();
 }
 
 void ReplicatedPG::on_change()
index 4bc6231770e90c79741d1f854ad3eaefe2d2bf91..d139d9839285c5e9d03195e076d1a9884500e6ff 100644 (file)
@@ -603,7 +603,9 @@ protected:
   int recover_replicas(int max);
 
   void dump_watchers(ObjectContext *obc);
+  void remove_watcher(ObjectContext *obc, entity_name_t entity);
   void do_complete_notify(Watch::Notification *notif, ObjectContext *obc);
+  void remove_watchers();
 
   struct RepModify {
     ReplicatedPG *pg;