]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
librbd: handle diff from clone
authorSage Weil <sage@inktank.com>
Thu, 28 Mar 2013 16:26:11 +0000 (09:26 -0700)
committerJosh Durgin <josh.durgin@inktank.com>
Mon, 1 Apr 2013 06:32:41 +0000 (23:32 -0700)
If we have a parent image, and the reference is from snap 0 (beginning of
time) we need to look at the diff on the parent from the beginning of time
and report that when we get an ENOENT.

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

index b1d30452f5edbd94fc5d6c2495b10868aeb93714..1340ba26f9424bb4d55e70cd1562578415ff74f8 100644 (file)
@@ -2256,6 +2256,14 @@ reprotect_and_return_err:
     return total_read;
   }
 
+  int simple_diff_cb(uint64_t off, size_t len, bool exists, void *arg)
+  {
+    interval_set<uint64_t> *diff = static_cast<interval_set<uint64_t> *>(arg);
+    diff->insert(off, len);
+    return 0;
+  }
+
+
   int64_t diff_iterate(ImageCtx *ictx, const char *fromsnapname,
                       uint64_t off, size_t len,
                       int (*cb)(uint64_t, size_t, bool, void *),
@@ -2307,6 +2315,22 @@ reprotect_and_return_err:
     // FIXME: if end_size > from_size, we could read_iterate for the
     // final part, and skip the listsnaps op.
 
+    // check parent overlap only if we are comparing to the beginning of time
+    interval_set<uint64_t> parent_diff;
+    if (from_snap_id == 0) {
+      ictx->parent_lock.get_read();
+      uint64_t overlap = end_size;
+      ictx->get_parent_overlap(from_snap_id, &overlap);
+      r = 0;
+      if (ictx->parent && overlap > 0) {
+       ldout(ictx->cct, 10) << " first getting parent diff" << dendl;
+       r = diff_iterate(ictx->parent, NULL, 0, overlap, simple_diff_cb, &parent_diff);
+      }
+      ictx->parent_lock.put_read();
+      if (r < 0)
+       return r;
+    }
+
     int64_t total_read = 0;
     uint64_t period = ictx->get_stripe_period();
     uint64_t left = mylen;
@@ -2334,8 +2358,25 @@ reprotect_and_return_err:
        op.stat(&size, NULL, NULL);
        op.list_snaps(&snap_set, NULL);
        int r = head_ctx.operate(p->first.name, &op, NULL);
-       if (r == -ENOENT)
+       if (r == -ENOENT) {
+         if (from_snap_id == 0 && !parent_diff.empty()) {
+           // report parent diff instead
+           for (vector<ObjectExtent>::iterator q = p->second.begin(); q != p->second.end(); ++q) {
+             for (vector<pair<uint64_t,uint64_t> >::iterator r = q->buffer_extents.begin();
+                  r != q->buffer_extents.end();
+                  ++r) {
+               interval_set<uint64_t> o;
+               o.insert(off + r->first, r->second);
+               o.intersection_of(parent_diff);
+               ldout(ictx->cct, 20) << " reporting parent overlap " << o << dendl;
+               for (interval_set<uint64_t>::iterator s = o.begin(); s != o.end(); ++s) {
+                 cb(s.get_start(), s.get_len(), false, arg);
+               }
+             }
+           }
+         }
          continue;
+       }
        if (r < 0)
          return r;