]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: prepend missing objects to pgls results
authorSage Weil <sage.weil@dreamhost.com>
Wed, 11 May 2011 23:27:18 +0000 (16:27 -0700)
committerSage Weil <sage.weil@dreamhost.com>
Wed, 11 May 2011 23:27:18 +0000 (16:27 -0700)
This will prepend any missing objects to the set of objects returned by
a sequence of PGLS operations.  Because recovery can progress in parallel,
we may get some objects returned twice (first as a missing item, later
because it is on disk).  This is better than not getting it at all.  The
client will need to uniq the results as needed.

Because the missing set is guaranteed not to grow over a given mapping
interval only, the client should restart the whole PGLS sequence if the
pg primary changes.

Signed-off-by: Sage Weil <sage.weil@dreamhost.com>
src/os/FileStore.cc
src/osd/ReplicatedPG.cc

index 219b79a890ddc46831e74705a2fd7890238d3782..967eec98e9e266e0109ffc4084aaf63c87ade4f1 100644 (file)
@@ -3696,7 +3696,8 @@ int FileStore::collection_list_partial(coll_t c, snapid_t seq, vector<sobject_t>
   }
 
   if (handle && *handle) {
-    seekdir(dir, *(off_t *)handle);
+    dout(10) << "collection_list_partial seeking to " << *handle << dendl;
+    seekdir(dir, *handle);
     *handle = 0;
   }
 
@@ -3733,8 +3734,10 @@ int FileStore::collection_list_partial(coll_t c, snapid_t seq, vector<sobject_t>
     }
   }
 
-  if (handle && !end)
+  if (handle && !end) {
     *handle = (collection_list_handle_t)telldir(dir);
+    dout(10) << "collection_list_partial finished at " << *handle << dendl;
+  }
 
   ::closedir(dir);
 
index e9c71c8d838cea45ea69833be720f6c95a215304..16278df336e4e75af9266ae80f1619634c886d50 100644 (file)
@@ -257,14 +257,40 @@ void ReplicatedPG::do_pg_op(MOSDOp *op)
         dout(10) << " pgls pg=" << op->get_pg() << " != " << info.pgid << dendl;
        result = 0; // hmm?
       } else {
-        dout(10) << " pgls pg=" << op->get_pg() << dendl;
+        dout(10) << " pgls pg=" << op->get_pg() << " count " << p->op.pgls.count << dendl;
        // read into a buffer
+        vector<sobject_t> sentries;
         PGLSResponse response;
         response.handle = (collection_list_handle_t)(uint64_t)(p->op.pgls.cookie);
-        vector<sobject_t> sentries;
-       result = osd->store->collection_list_partial(coll, snapid,
-                                                    sentries, p->op.pgls.count,
-                                                    &response.handle);
+
+       uint64_t high_bit = 1ull << 63;
+       if ((response.handle & high_bit) == 0) {
+         // it's an offset into the missing set
+         version_t v = response.handle;
+         dout(10) << " handle low/missing " << v << dendl;
+         map<version_t, sobject_t>::iterator mp = missing.rmissing.lower_bound(v);
+         result = 0;
+         while (sentries.size() < p->op.pgls.count) {
+           if (mp == missing.rmissing.end()) {
+             dout(10) << " handle finished low/missing, moving to high/ondisk" << dendl;
+             response.handle = high_bit;
+             break;
+           }
+           sentries.push_back(mp->second);
+           response.handle = mp->first + 1;
+         }
+       }
+       if (sentries.size() < p->op.pgls.count &&
+           (response.handle & high_bit)) {
+         // it's a readdir cookie
+         response.handle &= high_bit - 1ull;
+         dout(10) << " handle high/missing " << response.handle << dendl;
+         result = osd->store->collection_list_partial(coll, snapid,
+                                                      sentries, p->op.pgls.count - sentries.size(),
+                                                      &response.handle);
+         response.handle |= high_bit;
+       }
+
        if (result == 0) {
           vector<sobject_t>::iterator iter;
           for (iter = sentries.begin(); iter != sentries.end(); ++iter) {