]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
osd: track byte range diffs between clones
authorSage Weil <sage@newdream.net>
Mon, 18 Aug 2008 20:57:04 +0000 (13:57 -0700)
committerSage Weil <sage@newdream.net>
Mon, 18 Aug 2008 21:07:20 +0000 (14:07 -0700)
src/TODO
src/include/interval_set.h
src/osd/ReplicatedPG.cc
src/osd/osd_types.h

index b1e3da75f091d06c21e7f07a3f35fd7c62438c8e..4890b81ec2a0eba1bcbf544fff3b292edfbf7ba2 100644 (file)
--- a/src/TODO
+++ b/src/TODO
@@ -34,8 +34,7 @@ snaps on mds
 
 snaps on osd
 - garbage collection
-- efficient recovery of clones
-  - include inter-clone diff intervals in SnapSet.
+- efficient recovery of clones using the clone diff info
 
 userspace client
 - handle session STALE
index 2b536020f391fb5256686f1698520313f34a09a7..436074cb55f8b10627db867e5f4d1caa81fbbf81 100644 (file)
@@ -199,6 +199,13 @@ class interval_set {
       }
     }
   }
+
+  void swap(interval_set<T>& other) {
+    m.swap(other.m);
+    int t = _size;
+    _size = other._size;
+    other._size = t;
+  }    
   
   void erase(T val) {
     erase(val, 1);
@@ -264,6 +271,11 @@ class interval_set {
         pa++; 
     }
   }
+  void intersection_of(const interval_set& b) {
+    interval_set a;
+    a.m.swap(m);
+    intersection_of(a, b);
+  }
 
   void union_of(const interval_set &a, const interval_set &b) {
     assert(&a != this);
index d4f4e219135bd66edc6b83dd1a1b6af20b44603a..a4f0ccbc93fc95f2a410ea98aa5a5b385fe8c64d 100644 (file)
@@ -745,6 +745,7 @@ void ReplicatedPG::prepare_transaction(ObjectStore::Transaction& t, osd_reqid_t
       }
 
       snapset.clones.push_back(coid.oid.snap);
+      snapset.clone_diffs[coid.oid.snap].swap(snapset.head_diffs);
       
       at_version.version++;
     }
@@ -813,7 +814,9 @@ void ReplicatedPG::prepare_transaction(ObjectStore::Transaction& t, osd_reqid_t
       t.write(info.pgid.to_coll(), poid, offset, length, nbl);
       if (inc_lock) t.setattr(info.pgid.to_coll(), poid, "inc_lock", &inc_lock, sizeof(inc_lock));
       snapset.head_exists = true;
-      snapset.head_diffs.insert(offset, length);
+      interval_set<__u64> ch;
+      ch.insert(offset, length);
+      snapset.head_diffs.union_of(ch);
     }
     break;
     
@@ -821,6 +824,9 @@ void ReplicatedPG::prepare_transaction(ObjectStore::Transaction& t, osd_reqid_t
     { // zero
       t.zero(info.pgid.to_coll(), poid, offset, length);
       if (inc_lock) t.setattr(info.pgid.to_coll(), poid, "inc_lock", &inc_lock, sizeof(inc_lock));
+      interval_set<__u64> ch;
+      ch.insert(offset, length);
+      snapset.head_diffs.union_of(ch);
     }
     break;
 
@@ -828,12 +834,16 @@ void ReplicatedPG::prepare_transaction(ObjectStore::Transaction& t, osd_reqid_t
     { // truncate
       t.truncate(info.pgid.to_coll(), poid, length);
       if (inc_lock) t.setattr(info.pgid.to_coll(), poid, "inc_lock", &inc_lock, sizeof(inc_lock));
+      interval_set<__u64> keep;
+      keep.insert(0, length);
+      snapset.head_diffs.intersection_of(keep);
     }
     break;
     
   case CEPH_OSD_OP_DELETE:
     { // delete
       t.remove(info.pgid.to_coll(), poid);
+      snapset.head_diffs.clear();
     }
     break;
     
index 1797b74135b491edce898e6dd7d17b5f19d6d311..c915e9721caf66a1bf3567e5001b4a6b4e795fd2 100644 (file)
@@ -18,6 +18,7 @@
 #include "msg/msg_types.h"
 #include "include/types.h"
 #include "include/pobject.h"
+#include "include/interval_set.h"
 
 /* osdreqid_t - caller name + incarnation# + tid to unique identify this request
  * use for metadata and osd ops.
@@ -424,6 +425,13 @@ inline ostream& operator<<(ostream& out, OSDSuperblock& sb)
 
 // -------
 
+inline void encode(const interval_set<__u64>& s, bufferlist& bl) {
+  ::encode(s.m, bl);
+}
+inline void decode(interval_set<__u64>& s, bufferlist::iterator& bl) {
+  ::decode(s.m, bl);
+}
+
 /*
  * attached to object head.  describes most recent snap context, and
  * set of existing clones.
@@ -433,6 +441,8 @@ struct SnapSet {
   bool head_exists;
   vector<snapid_t> snaps;
   vector<snapid_t> clones;
+  interval_set<__u64> head_diffs;                   // subset of data that is "new"
+  map<snapid_t, interval_set<__u64> > clone_diffs;  // diff to previous
 
   SnapSet() : head_exists(false) {}
 
@@ -441,12 +451,16 @@ struct SnapSet {
     ::encode(head_exists, bl);
     ::encode(snaps, bl);
     ::encode(clones, bl);
+    ::encode(head_diffs, bl);
+    ::encode(clone_diffs, bl);
   }
   void decode(bufferlist::iterator& bl) {
     ::decode(seq, bl);
     ::decode(head_exists, bl);
     ::decode(snaps, bl);
     ::decode(clones, bl);
+    ::decode(head_diffs, bl);
+    ::decode(clone_diffs, bl);
   }
 };
 WRITE_CLASS_ENCODER(SnapSet)