return 0;
}
+
template <int LogLevelV>
void _dump_extent_map(CephContext *cct, const BlueStore::ExtentMap &em)
{
#undef dout_prefix
#define dout_prefix *_dout << "bluestore.onode(" << this << ")." << __func__ << " "
+const std::string& BlueStore::Onode::calc_omap_prefix(uint8_t flags)
+{
+ if (bluestore_onode_t::is_pgmeta_omap(flags)) {
+ return PREFIX_PGMETA_OMAP;
+ }
+ if (bluestore_onode_t::is_perpg_omap(flags)) {
+ return PREFIX_PERPG_OMAP;
+ }
+ if (bluestore_onode_t::is_perpool_omap(flags)) {
+ return PREFIX_PERPOOL_OMAP;
+ }
+ return PREFIX_OMAP;
+}
+
+// '-' < '.' < '~'
+void BlueStore::Onode::calc_omap_header(
+ uint8_t flags,
+ const Onode* o,
+ std::string* out)
+{
+ if (!bluestore_onode_t::is_pgmeta_omap(flags)) {
+ if (bluestore_onode_t::is_perpg_omap(flags)) {
+ _key_encode_u64(o->c->pool(), out);
+ _key_encode_u32(o->oid.hobj.get_bitwise_key_u32(), out);
+ } else if (bluestore_onode_t::is_perpool_omap(flags)) {
+ _key_encode_u64(o->c->pool(), out);
+ }
+ }
+ _key_encode_u64(o->onode.nid, out);
+ out->push_back('-');
+}
+
+void BlueStore::Onode::calc_omap_key(uint8_t flags,
+ const Onode* o,
+ const std::string& key,
+ std::string* out)
+{
+ if (!bluestore_onode_t::is_pgmeta_omap(flags)) {
+ if (bluestore_onode_t::is_perpg_omap(flags)) {
+ _key_encode_u64(o->c->pool(), out);
+ _key_encode_u32(o->oid.hobj.get_bitwise_key_u32(), out);
+ } else if (bluestore_onode_t::is_perpool_omap(flags)) {
+ _key_encode_u64(o->c->pool(), out);
+ }
+ }
+ _key_encode_u64(o->onode.nid, out);
+ out->push_back('.');
+ out->append(key);
+}
+
+void BlueStore::Onode::calc_omap_tail(
+ uint8_t flags,
+ const Onode* o,
+ std::string* out)
+{
+ if (!bluestore_onode_t::is_pgmeta_omap(flags)) {
+ if (bluestore_onode_t::is_perpg_omap(flags)) {
+ _key_encode_u64(o->c->pool(), out);
+ _key_encode_u32(o->oid.hobj.get_bitwise_key_u32(), out);
+ } else if (bluestore_onode_t::is_perpool_omap(flags)) {
+ _key_encode_u64(o->c->pool(), out);
+ }
+ }
+ _key_encode_u64(o->onode.nid, out);
+ out->push_back('~');
+}
//
// A tricky thing about Onode's ref counter is that we do an additional
// increment when newly pinned instance is detected. And -1 on unpin.
extent_map.dump(f);
}
-
-const string& BlueStore::Onode::get_omap_prefix()
-{
- if (onode.is_pgmeta_omap()) {
- return PREFIX_PGMETA_OMAP;
- }
- if (onode.is_perpg_omap()) {
- return PREFIX_PERPG_OMAP;
- }
- if (onode.is_perpool_omap()) {
- return PREFIX_PERPOOL_OMAP;
- }
- return PREFIX_OMAP;
-}
-
-// '-' < '.' < '~'
-
-void BlueStore::Onode::get_omap_header(string *out)
-{
- if (!onode.is_pgmeta_omap()) {
- if (onode.is_perpg_omap()) {
- _key_encode_u64(c->pool(), out);
- _key_encode_u32(oid.hobj.get_bitwise_key_u32(), out);
- } else if (onode.is_perpool_omap()) {
- _key_encode_u64(c->pool(), out);
- }
- }
- _key_encode_u64(onode.nid, out);
- out->push_back('-');
-}
-
-void BlueStore::Onode::get_omap_key(const string& key, string *out)
-{
- if (!onode.is_pgmeta_omap()) {
- if (onode.is_perpg_omap()) {
- _key_encode_u64(c->pool(), out);
- _key_encode_u32(oid.hobj.get_bitwise_key_u32(), out);
- } else if (onode.is_perpool_omap()) {
- _key_encode_u64(c->pool(), out);
- }
- }
- _key_encode_u64(onode.nid, out);
- out->push_back('.');
- out->append(key);
-}
-
void BlueStore::Onode::rewrite_omap_key(const string& old, string *out)
{
if (!onode.is_pgmeta_omap()) {
out->append(old.c_str() + out->length(), old.size() - out->length());
}
-void BlueStore::Onode::get_omap_tail(string *out)
-{
- if (!onode.is_pgmeta_omap()) {
- if (onode.is_perpg_omap()) {
- _key_encode_u64(c->pool(), out);
- _key_encode_u32(oid.hobj.get_bitwise_key_u32(), out);
- } else if (onode.is_perpool_omap()) {
- _key_encode_u64(c->pool(), out);
- }
- }
- _key_encode_u64(onode.nid, out);
- out->push_back('~');
-}
-
void BlueStore::Onode::decode_omap_key(const string& key, string *user_key)
{
size_t pos = sizeof(uint64_t) + 1;
*user_key = key.substr(pos);
}
-
// =======================================================
// WriteContext
!o->onode.is_perpg_omap() &&
!o->onode.is_pgmeta_omap()) {
dout(10) << "fsck converting " << o->oid << " omap to per-pg" << dendl;
- bufferlist h;
+ bufferlist header;
map<string, bufferlist> kv;
- int r = _onode_omap_get(o, &h, &kv);
- if (r < 0) {
- derr << " got " << r << " " << cpp_strerror(r) << dendl;
- } else {
+ {
+ KeyValueDB::Transaction txn = db->get_transaction();
+ uint64_t txn_cost = 0;
+ const string& prefix = Onode::calc_omap_prefix(o->onode.flags);
+ uint8_t new_flags = o->onode.flags |
+ bluestore_onode_t::FLAG_PERPOOL_OMAP |
+ bluestore_onode_t::FLAG_PERPG_OMAP;
+ const string& new_omap_prefix = Onode::calc_omap_prefix(new_flags);
+
+ KeyValueDB::Iterator it = db->get_iterator(prefix);
+ string head, tail;
+ o->get_omap_header(&head);
+ o->get_omap_tail(&tail);
+ it->lower_bound(head);
+ // head
+ if (it->valid() && it->key() == head) {
+ dout(30) << __func__ << " got header" << dendl;
+ header = it->value();
+ if (header.length()) {
+ string new_head;
+ Onode::calc_omap_header(new_flags, o.get(), &new_head);
+ txn->set(new_omap_prefix, new_head, header);
+ txn_cost += new_head.length() + header.length();
+ }
+ }
+ // tail
+ {
+ string new_tail;
+ Onode::calc_omap_tail(new_flags, o.get(), &new_tail);
+ bufferlist empty;
+ txn->set(new_omap_prefix, new_tail, empty);
+ txn_cost += new_tail.length() + new_tail.length();
+ }
+ // values
+ string final_key;
+ Onode::calc_omap_key(new_flags, o.get(), string(), &final_key);
+ size_t base_key_len = final_key.size();
+ while (it->valid() && it->key() < tail) {
+ string user_key;
+ o->decode_omap_key(it->key(), &user_key);
+ dout(20) << __func__ << " got " << pretty_binary_string(it->key())
+ << " -> " << user_key << dendl;
+
+ final_key.resize(base_key_len);
+ final_key += it->key();
+ auto v = it->value();
+ txn->set(new_omap_prefix, final_key, v);
+ txn_cost += final_key.length() + v.length();
+
+ // submit a portion if cost exceeds 16MB
+ if (txn_cost >= 16 * (1 << 20) ) {
+ db->submit_transaction_sync(txn);
+ txn = db->get_transaction();
+ txn_cost = 0;
+ }
+ it->next();
+ }
+ if (txn_cost > 0) {
+ db->submit_transaction_sync(txn);
+ }
+ }
+ // finalize: remove legacy data
+ {
KeyValueDB::Transaction txn = db->get_transaction();
// remove old keys
const string& old_omap_prefix = o->get_omap_prefix();
// set flag
o->onode.set_flag(bluestore_onode_t::FLAG_PERPOOL_OMAP | bluestore_onode_t::FLAG_PERPG_OMAP);
_record_onode(o, txn);
- const string& new_omap_prefix = o->get_omap_prefix();
- // head
- if (h.length()) {
- string new_head;
- o->get_omap_header(&new_head);
- txn->set(new_omap_prefix, new_head, h);
- }
- // tail
- string new_tail;
- o->get_omap_tail(&new_tail);
- bufferlist empty;
- txn->set(new_omap_prefix, new_tail, empty);
- // values
- string final_key;
- o->get_omap_key(string(), &final_key);
- size_t base_key_len = final_key.size();
- for (auto& i : kv) {
- final_key.resize(base_key_len);
- final_key += i.first;
- txn->set(new_omap_prefix, final_key, i.second);
- }
db->submit_transaction_sync(txn);
repairer->inc_repaired();
repairer->request_compaction();
if (o->oid.is_pgmeta()) {
o->onode.set_omap_flags_pgmeta();
} else {
- o->onode.set_omap_flags();
+ o->onode.set_omap_flags(per_pool_omap == OMAP_BULK);
}
txc->write_onode(o);
if (o->oid.is_pgmeta()) {
o->onode.set_omap_flags_pgmeta();
} else {
- o->onode.set_omap_flags();
+ o->onode.set_omap_flags(per_pool_omap == OMAP_BULK);
}
txc->write_onode(o);
if (newo->oid.is_pgmeta()) {
newo->onode.set_omap_flags_pgmeta();
} else {
- newo->onode.set_omap_flags();
+ newo->onode.set_omap_flags(per_pool_omap == OMAP_BULK);
}
const string& prefix = newo->get_omap_prefix();
KeyValueDB::Iterator it = db->get_iterator(prefix);