]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
os/bluestore: migrate to refcounting for Blob class instances
authorIgor Fedotov <ifedotov@mirantis.com>
Thu, 7 Jul 2016 17:26:14 +0000 (20:26 +0300)
committerIgor Fedotov <ifedotov@mirantis.com>
Thu, 11 Aug 2016 11:28:02 +0000 (14:28 +0300)
Signed-off-by: Igor Fedotov <ifedotov@mirantis.com>
src/os/bluestore/BlueStore.cc
src/os/bluestore/BlueStore.h

index 2ddc7c6583401c14aa979e44a39c224832d30d10..2ffbbf189cb0819c0e2477c3bc443410536a8037 100644 (file)
@@ -1193,6 +1193,7 @@ void BlueStore::BlobMap::decode(bufferlist::iterator& p, Cache *c)
     ::decode(id, p);
     Blob *b = new Blob(id, c);
     ::decode(b->blob, p);
+    b->get();
     blob_map.insert(*b);
   }
 }
@@ -3582,8 +3583,13 @@ struct region_t {
       << r.blob_xoffset << "~" << r.length << std::dec;
   }
 };
+
+bool less(const BlueStore::BlobRef& a, const BlueStore::BlobRef& b)
+{
+  return *a < *b;
+}
 typedef list<region_t> regions2read_t;
-typedef map<Blob*, regions2read_t> blobs2read_t;
+typedef map<BlueStore::BlobRef, regions2read_t> blobs2read_t;
 
 int BlueStore::_do_read(
   Collection *c,
@@ -3643,7 +3649,7 @@ int BlueStore::_do_read(
       pos += hole;
       left -= hole;
     }
-    Blob *bptr = c->get_blob(o, lp->second.blob);
+    BlobRef bptr = c->get_blob(o, lp->second.blob);
     if (bptr == nullptr) {
       dout(20) << __func__ << "  missed blob " << lp->second.blob << dendl;
       assert(bptr != nullptr);
@@ -3691,7 +3697,7 @@ int BlueStore::_do_read(
   //enumerate and read/decompress desired blobs
   blobs2read_t::iterator b2r_it = blobs2read.begin();
   while (b2r_it != blobs2read.end()) {
-    Blob* bptr = b2r_it->first;
+    BlobRef bptr = b2r_it->first;
     dout(20) << __func__ << "  blob " << *bptr << std::hex
             << " need 0x" << b2r_it->second << std::dec << dendl;
     if (bptr->blob.has_flag(bluestore_blob_t::FLAG_COMPRESSED)) {
@@ -5297,7 +5303,7 @@ int BlueStore::queue_transactions(
 
   // delayed csum calculation?
   for (auto& d : txc->deferred_csum) {
-    Blob *b = d.onode->get_blob(d.blob);
+    BlobRef b = d.onode->get_blob(d.blob);
     dout(20) << __func__ << "  deferred csum calc blob " << d.blob
             << " b_off 0x" << std::hex << d.b_off << std::dec
             << " on " << d.onode->oid << dendl;
@@ -5861,7 +5867,7 @@ void BlueStore::_do_write_small(
   blp.copy(length, bl);
 
   // look for an existing mutable blob we can use
-  Blob *b = 0;
+  BlobRef b = 0;
   map<uint64_t,bluestore_lextent_t>::iterator ep = o->onode.seek_lextent(offset);
   if (ep != o->onode.extent_map.begin()) {
     --ep;
@@ -6061,7 +6067,7 @@ void BlueStore::_do_write_big(
           << " compress " << (int)wctx->compress
           << std::dec << dendl;
   while (length > 0) {
-    Blob *b = o->blob_map.new_blob(c->cache);
+    BlobRef b = o->blob_map.new_blob(c->cache);
     auto l = MIN(max_blob_len, length);
     bufferlist t;
     blp.copy(l, t);
@@ -6099,7 +6105,7 @@ int BlueStore::_do_alloc_write(
 
   uint64_t hint = 0;
   for (auto& wi : wctx->writes) {
-    Blob *b = wi.b;
+    BlobRef b = wi.b;
     uint64_t b_off = wi.b_off;
     bufferlist *l = &wi.bl;
     uint64_t final_length = wi.blob_length;
@@ -6222,10 +6228,10 @@ void BlueStore::_wctx_finish(
   WriteContext *wctx)
 {
   dout(10) << __func__ << " lex_old " << wctx->lex_old << dendl;
-  set<pair<bool, Blob*> > blobs2remove;
+  set<pair<bool, BlobRef> > blobs2remove;
   for (auto &lo : wctx->lex_old) {
     bluestore_lextent_t& l = lo.second;
-    Blob *b = c->get_blob(o, l.blob);
+    BlobRef b = c->get_blob(o, l.blob);
     vector<bluestore_pextent_t> r;
     bool compressed = b->blob.is_compressed();
     if (o->onode.deref_lextent(lo.first, l, &b->blob, min_alloc_size, &r)) {
@@ -6255,13 +6261,12 @@ void BlueStore::_wctx_finish(
     }
   }
   for (auto br : blobs2remove) {
-    Blob* b = br.second;
-    dout(20) << __func__ << " rm blob " << *b << dendl;
-    txc->statfs_delta.compressed() -= b->blob.get_compressed_payload_length();
+    dout(20) << __func__ << " rm blob " << *br.second << dendl;
+    txc->statfs_delta.compressed() -= br.second->blob.get_compressed_payload_length();
     if (br.first) {
-      o->blob_map.erase(b);
+      o->blob_map.erase(br.second);
     } else {
-      o->bnode->blob_map.erase(b);
+      o->bnode->blob_map.erase(br.second);
     }
   }
 
@@ -6807,7 +6812,7 @@ int BlueStore::_clone(TransContext *txc,
       map<int64_t,int64_t> moved_blobs;
       for (auto& p : oldo->onode.extent_map) {
         if (!p.second.is_shared()) {
-          Blob *b;
+          BlobRef b;
           if (moved_blobs.count(p.second.blob) == 0) {
             b = oldo->blob_map.get(p.second.blob);
             oldo->blob_map.erase(b);
index 7213c6c1db6f56b18bd88235f1b34ff912691a83..c51f29b6d42d18ec92e8df728d9f0d23abcf3c93 100644 (file)
@@ -80,7 +80,6 @@ public:
   void _set_compression();
 
   class TransContext;
-  class Blob;
 
   typedef map<uint64_t, bufferlist> ready_regions_t;
 
@@ -279,15 +278,19 @@ public:
 
   /// in-memory blob metadata and associated cached buffers (if any)
   struct Blob : public boost::intrusive::set_base_hook<> {
+    std::atomic_int nref;  ///< reference count
     int64_t id = 0;          ///< id
     bluestore_blob_t blob;   ///< blob metadata
     BufferSpace bc;          ///< buffer cache
 
-    Blob(int64_t i, Cache *c) : id(i), bc(c) {}
+    Blob(int64_t i, Cache *c) : nref(0), id(i), bc(c) {}
     ~Blob() {
       assert(bc.empty());
     }
 
+    friend void intrusive_ptr_add_ref(Blob *b) { b->get(); }
+    friend void intrusive_ptr_release(Blob *b) { b->put(); }
+
     // comparators for intrusive_set
     friend bool operator<(const Blob &a, const Blob &b) {
       return a.id < b.id;
@@ -305,7 +308,16 @@ public:
 
     /// discard buffers for unallocated regions
     void discard_unallocated();
+
+    void get() {
+      ++nref;
+    }
+    void put() {
+      if (--nref == 0)
+       delete this;
+    }
   };
+  typedef boost::intrusive_ptr<Blob> BlobRef;
 
   /// a map of blobs, indexed by int64_t
   struct BlobMap {
@@ -320,7 +332,7 @@ public:
       return blob_map.empty();
     }
 
-    Blob *get(int64_t id) {
+    BlobRef get(int64_t id) {
       Blob dummy(id, nullptr);
       auto p = blob_map.find(dummy);
       if (p != blob_map.end()) {
@@ -329,22 +341,25 @@ public:
       return nullptr;
     }
 
-    Blob *new_blob(Cache *c) {
+    BlobRef new_blob(Cache *c) {
       int64_t id = get_new_id();
       Blob *b = new Blob(id, c);
+      b->get();
       blob_map.insert(*b);
       return b;
     }
 
-    void claim(Blob *b) {
+    void claim(BlobRef b) {
       assert(b->id == 0);
       b->id = get_new_id();
+      b->get();
       blob_map.insert(*b);
     }
 
-    void erase(Blob *b) {
+    void erase(BlobRef b) {
       blob_map.erase(*b);
       b->id = 0;
+      b->put();
     }
 
     int64_t get_new_id() {
@@ -357,7 +372,6 @@ public:
        Blob *b = &*blob_map.begin();
        b->bc._clear();
        erase(b);
-       delete b;
       }
     }
 
@@ -475,7 +489,7 @@ public:
        exists(false) {
     }
 
-    Blob *get_blob(int64_t id) {
+    BlobRef get_blob(int64_t id) {
       if (id < 0) {
        assert(bnode);
        return bnode->blob_map.get(-id);
@@ -703,7 +717,7 @@ public:
     OnodeRef get_onode(const ghobject_t& oid, bool create);
     BnodeRef get_bnode(uint32_t hash);
 
-    Blob *get_blob(OnodeRef& o, int64_t blob) {
+    BlobRef get_blob(OnodeRef& o, int64_t blob) {
       if (blob < 0) {
        if (!o->bnode) {
          o->bnode = get_bnode(o->oid.hobj.get_hash());
@@ -1484,18 +1498,18 @@ private:
     vector<std::pair<uint64_t, bluestore_lextent_t> > lex_old; ///< must deref blobs
 
     struct write_item {
-      Blob *b;
+      BlobRef b;
       uint64_t blob_length;
       uint64_t b_off;
       bufferlist bl;
       bool mark_unused;
 
-      write_item(Blob *b, uint64_t blob_len, uint64_t o, bufferlist& bl, bool _mark_unused)
+      write_item(BlobRef b, uint64_t blob_len, uint64_t o, bufferlist& bl, bool _mark_unused)
        : b(b), blob_length(blob_len), b_off(o), bl(bl), mark_unused(_mark_unused) {}
     };
     vector<write_item> writes;                 ///< blobs we're writing
 
-    void write(Blob *b, uint64_t blob_len, uint64_t o, bufferlist& bl, bool _mark_unused) {
+    void write(BlobRef b, uint64_t blob_len, uint64_t o, bufferlist& bl, bool _mark_unused) {
       writes.emplace_back(write_item(b, blob_len, o, bl, _mark_unused));
     }
   };