]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
ECBackend::filter_read_op: clean up read state properly
authorSamuel Just <sam.just@inktank.com>
Fri, 21 Feb 2014 02:31:35 +0000 (18:31 -0800)
committerSamuel Just <sam.just@inktank.com>
Sat, 22 Feb 2014 20:35:40 +0000 (12:35 -0800)
Fixes: #7494
Signed-off-by: Samuel Just <sam.just@inktank.com>
src/osd/ECBackend.cc

index 9e2765e806781c8af5cc4b38499858efa77ad2bc..e4572ab6ec0b243c650680593bd405cdfdadfc33 100644 (file)
@@ -916,7 +916,10 @@ void ECBackend::handle_sub_read_reply(
        i != op.buffers_read.end();
        ++i) {
     assert(!op.errors.count(i->first));
-    assert(rop.to_read.count(i->first));
+    if (!rop.to_read.count(i->first)) {
+      // We canceled this read! @see filter_read_op
+      continue;
+    }
     list<pair<uint64_t, uint64_t> >::const_iterator req_iter =
       rop.to_read.find(i->first)->second.to_read.begin();
     list<
@@ -1004,36 +1007,61 @@ void ECBackend::filter_read_op(
   const OSDMapRef osdmap,
   ReadOp &op)
 {
+  set<hobject_t> to_cancel;
   for (map<pg_shard_t, set<hobject_t> >::iterator i = op.source_to_obj.begin();
        i != op.source_to_obj.end();
-       ) {
-    if (!osdmap->is_down(i->first.osd)) {
-      ++i;
+       ++i) {
+    if (osdmap->is_down(i->first.osd)) {
+      to_cancel.insert(i->second.begin(), i->second.end());
+      op.in_progress.erase(i->first);
       continue;
     }
+  }
+
+  if (to_cancel.empty())
+    return;
+
+  for (map<pg_shard_t, set<hobject_t> >::iterator i = op.source_to_obj.begin();
+       i != op.source_to_obj.end();
+       ) {
     for (set<hobject_t>::iterator j = i->second.begin();
         j != i->second.end();
-        ++j) {
-      get_parent()->cancel_pull(*j);
+        ) {
+      if (to_cancel.count(*j))
+       i->second.erase(j++);
+      else
+       ++j;
+    }
+    if (i->second.empty()) {
+      op.source_to_obj.erase(i++);
+    } else {
+      assert(!osdmap->is_down(i->first.osd));
+      ++i;
+    }
+  }
 
-      assert(op.to_read.count(*j));
-      read_request_t &req = op.to_read.find(*j)->second;
-      assert(req.cb);
-      delete req.cb;
-      req.cb = NULL;
+  for (set<hobject_t>::iterator i = to_cancel.begin();
+       i != to_cancel.end();
+       ++i) {
+    get_parent()->cancel_pull(*i);
 
-      op.to_read.erase(*j);
-      op.complete.erase(*j);
-      op.obj_to_source.erase(*j);
-      op.in_progress.erase(i->first);
-      recovery_ops.erase(*j);
-      if (op.in_progress.empty()) {
-       get_parent()->schedule_work(
-         get_parent()->bless_gencontext(
-           new FinishReadOp(this, op.tid)));
-      }
-    }
-    op.source_to_obj.erase(i++);
+    assert(op.to_read.count(*i));
+    read_request_t &req = op.to_read.find(*i)->second;
+    dout(10) << __func__ << ": canceling " << req
+            << "  for obj " << *i << dendl;
+    assert(req.cb);
+    delete req.cb;
+    req.cb = NULL;
+
+    op.to_read.erase(*i);
+    op.complete.erase(*i);
+    recovery_ops.erase(*i);
+  }
+
+  if (op.in_progress.empty()) {
+    get_parent()->schedule_work(
+      get_parent()->bless_gencontext(
+       new FinishReadOp(this, op.tid)));
   }
 };