From: Igor Fedotov Date: Wed, 11 Jan 2017 17:47:11 +0000 (+0300) Subject: os/bluestore: raise ExtentMap/Blob encoding version to handle migration from ref_map... X-Git-Tag: v12.0.0~30^2~6 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c761c1bfec71b84cabde75a62fdc690b484a62e6;p=ceph.git os/bluestore: raise ExtentMap/Blob encoding version to handle migration from ref_map to ref counting properly. Signed-off-by: Igor Fedotov --- diff --git a/src/os/bluestore/BlueStore.cc b/src/os/bluestore/BlueStore.cc index bd7ece3b881..8b7ea2d6dc6 100644 --- a/src/os/bluestore/BlueStore.cc +++ b/src/os/bluestore/BlueStore.cc @@ -1683,6 +1683,36 @@ void BlueStore::Blob::split(Collection *coll, uint32_t blob_offset, Blob *r) << " and " << *r << dendl; } +#ifndef CACHE_BLOB_BL +void BlueStore::Blob::decode( + Collection *coll, + bufferptr::iterator& p, + uint64_t struct_v, + uint64_t* sbid, + bool include_ref_map) +{ + denc(blob, p, struct_v); + if (blob.is_shared()) { + denc(*sbid, p); + } + if (include_ref_map) { + if (struct_v > 1) { + used_in_blob.decode(p); + } else { + used_in_blob.clear(); + bluestore_extent_ref_map_t legacy_ref_map; + legacy_ref_map.decode(p); + for (auto r : legacy_ref_map.ref_map) { + get_ref( + coll, + r.first, + r.second.refs * r.second.length); + } + } + } +} +#endif + // Extent ostream& operator<<(ostream& out, const BlueStore::Extent& e) @@ -1956,7 +1986,9 @@ bool BlueStore::ExtentMap::encode_some( auto start = extent_map.lower_bound(dummy); uint32_t end = offset + length; - __u8 struct_v = 1; + __u8 struct_v = 2; // Version 2 differs from v1 in blob's ref_map + // serialization only. Hence there is no specific + // handling at ExtentMap level. unsigned n = 0; size_t bound = 0; @@ -2057,7 +2089,11 @@ void BlueStore::ExtentMap::decode_some(bufferlist& bl) auto p = bl.front().begin_deep(); __u8 struct_v; denc(struct_v, p); - assert(struct_v == 1); + // Version 2 differs from v1 in blob's ref_map + // serialization only. Hence there is no specific + // handling at ExtentMap level below. + assert(struct_v == 1 || struct_v == 2); + uint32_t num; denc_varint(num, p); vector blobs(num); @@ -2095,7 +2131,7 @@ void BlueStore::ExtentMap::decode_some(bufferlist& bl) } else { Blob *b = new Blob(); uint64_t sbid = 0; - b->decode(p, struct_v, &sbid, false); + b->decode(onode->c, p, struct_v, &sbid, false); blobs[n] = b; onode->c->open_shared_blob(sbid, b); le->assign_blob(b); @@ -2116,7 +2152,11 @@ void BlueStore::ExtentMap::decode_some(bufferlist& bl) void BlueStore::ExtentMap::bound_encode_spanning_blobs(size_t& p) { - __u8 struct_v = 1; + // Version 2 differs from v1 in blob's ref_map + // serialization only. Hence there is no specific + // handling at ExtentMap level. + __u8 struct_v = 2; + denc(struct_v, p); denc_varint((uint32_t)0, p); size_t key_size = 0; @@ -2130,7 +2170,11 @@ void BlueStore::ExtentMap::bound_encode_spanning_blobs(size_t& p) void BlueStore::ExtentMap::encode_spanning_blobs( bufferlist::contiguous_appender& p) { - __u8 struct_v = 1; + // Version 2 differs from v1 in blob's ref_map + // serialization only. Hence there is no specific + // handling at ExtentMap level. + __u8 struct_v = 2; + denc(struct_v, p); denc_varint(spanning_blob_map.size(), p); for (auto& i : spanning_blob_map) { @@ -2144,7 +2188,11 @@ void BlueStore::ExtentMap::decode_spanning_blobs( { __u8 struct_v; denc(struct_v, p); - assert(struct_v == 1); + // Version 2 differs from v1 in blob's ref_map + // serialization only. Hence there is no specific + // handling at ExtentMap level. + assert(struct_v == 1 || struct_v == 2); + unsigned n; denc_varint(n, p); while (n--) { @@ -2152,7 +2200,7 @@ void BlueStore::ExtentMap::decode_spanning_blobs( denc_varint(b->id, p); spanning_blob_map[b->id] = b; uint64_t sbid = 0; - b->decode(p, struct_v, &sbid, true); + b->decode(onode->c, p, struct_v, &sbid, true); onode->c->open_shared_blob(sbid, b); } } diff --git a/src/os/bluestore/BlueStore.h b/src/os/bluestore/BlueStore.h index 47f551e62b7..d7161b6a8bc 100644 --- a/src/os/bluestore/BlueStore.h +++ b/src/os/bluestore/BlueStore.h @@ -525,6 +525,7 @@ public: } } void decode( + Collection */*coll*/, bufferptr::iterator& p, bool include_ref_map) { const char *start = p.get_pos(); @@ -564,18 +565,11 @@ public: } } void decode( + Collection *coll, bufferptr::iterator& p, uint64_t struct_v, uint64_t* sbid, - bool include_ref_map) { - denc(blob, p, struct_v); - if (blob.is_shared()) { - denc(*sbid, p); - } - if (include_ref_map) { - used_in_blob.decode(p); - } - } + bool include_ref_map); #endif }; typedef boost::intrusive_ptr BlobRef; diff --git a/src/os/bluestore/bluestore_types.h b/src/os/bluestore/bluestore_types.h index 80990f1ebfd..610f1fe29b2 100644 --- a/src/os/bluestore/bluestore_types.h +++ b/src/os/bluestore/bluestore_types.h @@ -456,7 +456,7 @@ struct bluestore_blob_t { DENC_HELPERS; void bound_encode(size_t& p, uint64_t struct_v) const { - assert(struct_v == 1); + assert(struct_v == 1 || struct_v == 2); denc(extents, p); denc_varint(flags, p); denc_varint_lowz(compressed_length_orig, p); @@ -469,7 +469,7 @@ struct bluestore_blob_t { } void encode(bufferlist::contiguous_appender& p, uint64_t struct_v) const { - assert(struct_v == 1); + assert(struct_v == 1 || struct_v == 2); denc(extents, p); denc_varint(flags, p); if (is_compressed()) { @@ -489,7 +489,7 @@ struct bluestore_blob_t { } void decode(bufferptr::iterator& p, uint64_t struct_v) { - assert(struct_v == 1); + assert(struct_v == 1 || struct_v == 2); denc(extents, p); denc_varint(flags, p); if (is_compressed()) { diff --git a/src/test/objectstore/test_bluestore_types.cc b/src/test/objectstore/test_bluestore_types.cc index 87d16cd67c0..4bb7e360a26 100644 --- a/src/test/objectstore/test_bluestore_types.cc +++ b/src/test/objectstore/test_bluestore_types.cc @@ -938,6 +938,82 @@ TEST(Blob, split) } } +TEST(Blob, legacy_decode) +{ + BlueStore store(g_ceph_context, "", 4096); + BlueStore::Cache *cache = BlueStore::Cache::create( + g_ceph_context, "lru", NULL); + BlueStore::Collection coll(&store, cache, coll_t()); + bufferlist bl, bl2; + { + BlueStore::Blob B; + B.shared_blob = new BlueStore::SharedBlob(&coll); + B.dirty_blob().extents.emplace_back(bluestore_pextent_t(0x1, 0x2000)); + B.dirty_blob().init_csum(Checksummer::CSUM_CRC32C, 12, 0x2000); + B.get_ref(&coll, 0, 0xff0); + B.get_ref(&coll, 0x1fff, 1); + + bluestore_extent_ref_map_t fake_ref_map; + fake_ref_map.get(0, 0xff0); + fake_ref_map.get(0x1fff, 1); + + size_t bound = 0, bound2 = 0; + + B.bound_encode( + bound, + 1, /*struct_v*/ + 0, /*sbid*/ + false); + fake_ref_map.bound_encode(bound); + + B.bound_encode( + bound2, + 2, /*struct_v*/ + 0, /*sbid*/ + true); + + { + auto app = bl.get_contiguous_appender(bound); + auto app2 = bl2.get_contiguous_appender(bound2); + B.encode( + app, + 1, /*struct_v*/ + 0, /*sbid*/ + false); + fake_ref_map.encode(app); + + B.encode( + app2, + 2, /*struct_v*/ + 0, /*sbid*/ + true); + } + + auto p = bl.front().begin_deep(); + auto p2 = bl2.front().begin_deep(); + BlueStore::Blob Bres, Bres2; + Bres.shared_blob = new BlueStore::SharedBlob(&coll); + Bres2.shared_blob = new BlueStore::SharedBlob(&coll); + + uint64_t sbid, sbid2; + Bres.decode( + &coll, + p, + 1, /*struct_v*/ + &sbid, + true); + Bres2.decode( + &coll, + p2, + 2, /*struct_v*/ + &sbid2, + true); + + ASSERT_EQ(0xff0u + 1u, Bres.get_blob_use_tracker().get_referenced_bytes()); + ASSERT_EQ(0xff0u + 1u, Bres2.get_blob_use_tracker().get_referenced_bytes()); + ASSERT_TRUE(Bres.get_blob_use_tracker().equal(Bres2.get_blob_use_tracker())); + } +} TEST(ExtentMap, find_lextent) { BlueStore store(g_ceph_context, "", 4096);