]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
osdc/ObjectCacher: do read completions after assimilating read result
authorSage Weil <sage@inktank.com>
Wed, 24 Oct 2012 19:44:25 +0000 (12:44 -0700)
committerSage Weil <sage@inktank.com>
Fri, 26 Oct 2012 18:31:45 +0000 (11:31 -0700)
Wait until we have applied the entire read result to the cache before we
trigger any read completion events.  This is a cleaner and safer approach
since we can be sure that the callback won't get blocked again on data we
have but haven't applied yet.  It also fixes a crash I just observed where
the completion did a read, called trim(), and invalidated/destroyed the
iterator/bh p was referencing.

Signed-off-by: Sage Weil <sage@inktank.com>
src/osdc/ObjectCacher.cc

index 8463657083cfd3be466c8ad2cd16ad54158b07be..803bb4c652d6e57d082ec184bd15a2514e87b07a 100644 (file)
@@ -553,7 +553,10 @@ void ObjectCacher::bh_read_finish(int64_t poolid, sobject_t oid, loff_t start,
            << " with " << bp.length() << " bytes of zeroes" << dendl;
     bl.push_back(bp);
   }
-  
+
+  list<Context*> ls;
+  int err = 0;
+
   if (objects[poolid].count(oid) == 0) {
     ldout(cct, 7) << "bh_read_finish no object cache" << dendl;
   } else {
@@ -603,19 +606,20 @@ void ObjectCacher::bh_read_finish(int64_t poolid, sobject_t oid, loff_t start,
       p++;
 
       // finishers?
-      // called with lock held.
-      list<Context*> ls;
       for (map<loff_t, list<Context*> >::iterator p = bh->waitfor_read.begin();
            p != bh->waitfor_read.end();
            p++)
         ls.splice(ls.end(), p->second);
       bh->waitfor_read.clear();
-      finish_contexts(cct, ls, bh->error);
+      if (bh->error < 0)
+       err = bh->error;
 
-      // clean up?
       ob->try_merge_bh(bh);
     }
   }
+
+  // called with lock held.
+  finish_contexts(cct, ls, err);
 }