From 8494a9943b0af0c3429ec569109ea11399ba9b0e Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 17:15:06 -0400 Subject: [PATCH 01/10] ceph-objectstore-tool: create 'dup' command Signed-off-by: Sage Weil --- src/tools/ceph_objectstore_tool.cc | 207 ++++++++++++++++++++++++++++- 1 file changed, 205 insertions(+), 2 deletions(-) diff --git a/src/tools/ceph_objectstore_tool.cc b/src/tools/ceph_objectstore_tool.cc index 0f62313817d..19a885edb11 100644 --- a/src/tools/ceph_objectstore_tool.cc +++ b/src/tools/ceph_objectstore_tool.cc @@ -2184,6 +2184,166 @@ int remove_clone(ObjectStore *store, coll_t coll, ghobject_t &ghobj, snapid_t cl return 0; } +int dup(string srcpath, ObjectStore *src, string dstpath, ObjectStore *dst) +{ + cout << "dup from " << src->get_type() << ": " << srcpath << "\n" + << " to " << dst->get_type() << ": " << dstpath + << std::endl; + ObjectStore::Sequencer osr("dup"); + int num, i; + vector collections; + int r; + + r = src->mount(); + if (r < 0) { + cerr << "failed to mount src: " << cpp_strerror(r) << std::endl; + return r; + } + r = dst->mount(); + if (r < 0) { + cerr << "failed to mount dst: " << cpp_strerror(r) << std::endl; + goto out_src; + } + + if (src->get_fsid() != dst->get_fsid()) { + cerr << "src fsid " << src->get_fsid() << " != dest " << dst->get_fsid() + << std::endl; + goto out; + } + cout << "fsid " << src->get_fsid() << std::endl; + + // make sure dst is empty + r = dst->list_collections(collections); + if (r < 0) { + cerr << "error listing collections on dst: " << cpp_strerror(r) << std::endl; + goto out; + } + if (!collections.empty()) { + cerr << "destination store is not empty" << std::endl; + goto out; + } + + r = src->list_collections(collections); + if (r < 0) { + cerr << "error listing collections on src: " << cpp_strerror(r) << std::endl; + goto out; + } + + num = collections.size(); + cout << num << " collections" << std::endl; + i = 1; + for (auto cid : collections) { + cout << i++ << "/" << num << " " << cid << std::endl; + { + ObjectStore::Transaction t; + int bits = src->collection_bits(cid); + if (bits < 0) { + cerr << "cannot get bit count for collection " << cid << ": " + << cpp_strerror(bits) << std::endl; + goto out; + } + t.create_collection(cid, bits); + dst->apply_transaction(&osr, std::move(t)); + } + + ghobject_t pos; + uint64_t n = 0; + uint64_t bytes = 0, keys = 0; + while (true) { + vector ls; + r = src->collection_list(cid, pos, ghobject_t::get_max(), 1000, &ls, &pos); + if (r < 0) { + cerr << "collection_list on " << cid << " from " << pos << " got: " + << cpp_strerror(r) << std::endl; + goto out; + } + if (ls.empty()) { + break; + } + + for (auto& oid : ls) { + //cout << " " << cid << " " << oid << std::endl; + if (n % 100 == 0) { + cout << " " << std::setw(16) << n << " objects, " + << std::setw(16) << bytes << " bytes, " + << std::setw(16) << keys << " keys" + << std::setw(1) << "\r" << std::flush; + } + n++; + + ObjectStore::Transaction t; + t.touch(cid, oid); + + map attrs; + src->getattrs(cid, oid, attrs); + if (!attrs.empty()) { + t.setattrs(cid, oid, attrs); + } + + bufferlist bl; + src->read(cid, oid, 0, 0, bl); + if (bl.length()) { + t.write(cid, oid, 0, bl.length(), bl); + bytes += bl.length(); + } + + bufferlist header; + map omap; + src->omap_get(cid, oid, &header, &omap); + if (header.length()) { + t.omap_setheader(cid, oid, header); + ++keys; + } + if (!omap.empty()) { + keys += omap.size(); + t.omap_setkeys(cid, oid, omap); + } + + dst->apply_transaction(&osr, std::move(t)); + } + } + cout << " " << std::setw(16) << n << " objects, " + << std::setw(16) << bytes << " bytes, " + << std::setw(16) << keys << " keys" + << std::setw(1) << std::endl; + } + + // keyring + cout << "keyring" << std::endl; + { + bufferlist bl; + string s = srcpath + "/keyring"; + string err; + r = bl.read_file(s.c_str(), &err); + if (r < 0) { + cerr << "failed to copy " << s << ": " << err << std::endl; + } else { + string d = dstpath + "/keyring"; + bl.write_file(d.c_str(), 0600); + } + } + + // osd metadata + cout << "duping osd metadata" << std::endl; + { + for (auto k : {"magic", "whoami", "ceph_fsid", "fsid"}) { + string val; + src->read_meta(k, &val); + dst->write_meta(k, val); + } + } + + dst->write_meta("ready", "ready"); + + cout << "done." << std::endl; + r = 0; + out: + dst->umount(); + out_src: + src->umount(); + return r; +} + void usage(po::options_description &desc) { cerr << std::endl; @@ -2301,6 +2461,7 @@ int apply_layout_settings(ObjectStore *os, const OSDSuperblock &superblock, int main(int argc, char **argv) { string dpath, jpath, pgidstr, op, file, mountpoint, mon_store_path, object; + string target_data_path, fsid; string objcmd, arg1, arg2, type, format, argnspace, pool; boost::optional nspace; spg_t pgid; @@ -2315,7 +2476,7 @@ int main(int argc, char **argv) desc.add_options() ("help", "produce help message") ("type", po::value(&type), - "Arg is one of [filestore (default), memstore]") + "Arg is one of [bluestore, filestore (default), memstore]") ("data-path", po::value(&dpath), "path to object store, mandatory") ("journal-path", po::value(&jpath), @@ -2325,7 +2486,7 @@ int main(int argc, char **argv) ("pool", po::value(&pool), "Pool name, mandatory for apply-layout-settings if --pgid is not specified") ("op", po::value(&op), - "Arg is one of [info, log, remove, mkfs, fsck, fuse, export, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, " + "Arg is one of [info, log, remove, mkfs, fsck, fuse, dup, export, import, list, fix-lost, list-pgs, rm-past-intervals, dump-journal, dump-super, meta-list, " "get-osdmap, set-osdmap, get-inc-osdmap, set-inc-osdmap, mark-complete, apply-layout-settings, update-mon-db]") ("epoch", po::value(&epoch), "epoch# for get-osdmap and get-inc-osdmap, the current epoch in use if not specified") @@ -2333,6 +2494,10 @@ int main(int argc, char **argv) "path of file to export, import, get-osdmap, set-osdmap, get-inc-osdmap or set-inc-osdmap") ("mon-store-path", po::value(&mon_store_path), "path of monstore to update-mon-db") + ("fsid", po::value(&fsid), + "fsid for new store created by mkfs") + ("target-data-path", po::value(&target_data_path), + "path of target object store (for --op dup)") ("mountpoint", po::value(&mountpoint), "fuse mountpoint") ("format", po::value(&format)->default_value("json-pretty"), @@ -2580,6 +2745,15 @@ int main(int argc, char **argv) return 0; } if (op == "mkfs") { + if (fsid.length()) { + uuid_d f; + bool r = f.parse(fsid.c_str()); + if (!r) { + cerr << "failed to parse uuid '" << fsid << "'" << std::endl; + return 1; + } + fs->set_fsid(f); + } int r = fs->mkfs(); if (r < 0) { cerr << "fsck failed: " << cpp_strerror(r) << std::endl; @@ -2587,6 +2761,35 @@ int main(int argc, char **argv) } return 0; } + if (op == "dup") { + string target_type; + char fn[PATH_MAX]; + snprintf(fn, sizeof(fn), "%s/type", target_data_path.c_str()); + int fd = ::open(fn, O_RDONLY); + if (fd < 0) { + cerr << "Unable to open " << target_data_path << "/type" << std::endl; + exit(1); + } + bufferlist bl; + bl.read_fd(fd, 64); + if (bl.length()) { + target_type = string(bl.c_str(), bl.length() - 1); // drop \n + } + ::close(fd); + ObjectStore *targetfs = ObjectStore::create( + g_ceph_context, target_type, + target_data_path, "", 0); + if (targetfs == NULL) { + cerr << "Unable to open store of type " << target_type << std::endl; + return 1; + } + int r = dup(dpath, fs, target_data_path, targetfs); + if (r < 0) { + cerr << "dup failed: " << cpp_strerror(r) << std::endl; + return 1; + } + return 0; + } ObjectStore::Sequencer *osr = new ObjectStore::Sequencer(__func__); int ret = fs->mount(); From 9f8b36de95cf29568225c9b62a3b46c5ce5dbcc9 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 17:28:49 -0400 Subject: [PATCH 02/10] os/memstore: implement collection_bits() Signed-off-by: Sage Weil --- src/os/memstore/MemStore.cc | 18 ++++++++++++++++-- src/os/memstore/MemStore.h | 4 +++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/os/memstore/MemStore.cc b/src/os/memstore/MemStore.cc index 520edfacc56..c4cc023462e 100644 --- a/src/os/memstore/MemStore.cc +++ b/src/os/memstore/MemStore.cc @@ -460,6 +460,16 @@ int MemStore::collection_empty(const coll_t& cid, bool *empty) return 0; } +int MemStore::collection_bits(const coll_t& cid) +{ + dout(10) << __func__ << " " << cid << dendl; + CollectionRef c = get_collection(cid); + if (!c) + return -ENOENT; + RWLock::RLocker l(c->lock); + return c->bits; +} + int MemStore::collection_list(const coll_t& cid, const ghobject_t& start, const ghobject_t& end, @@ -854,7 +864,7 @@ void MemStore::_do_transaction(Transaction& t) case Transaction::OP_MKCOLL: { coll_t cid = i.get_cid(op->cid); - r = _create_collection(cid); + r = _create_collection(cid, op->split_bits); } break; @@ -1345,7 +1355,7 @@ int MemStore::_omap_setheader(const coll_t& cid, const ghobject_t &oid, return 0; } -int MemStore::_create_collection(const coll_t& cid) +int MemStore::_create_collection(const coll_t& cid, int bits) { dout(10) << __func__ << " " << cid << dendl; RWLock::WLocker l(coll_lock); @@ -1353,6 +1363,7 @@ int MemStore::_create_collection(const coll_t& cid) if (!result.second) return -EEXIST; result.first->second.reset(new Collection(cct, cid)); + result.first->second->bits = bits; return 0; } @@ -1458,6 +1469,9 @@ int MemStore::_split_collection(const coll_t& cid, uint32_t bits, uint32_t match } } + sc->bits = bits; + assert(dc->bits == (int)bits); + return 0; } namespace { diff --git a/src/os/memstore/MemStore.h b/src/os/memstore/MemStore.h index ca1c5004f6e..2cac56fe206 100644 --- a/src/os/memstore/MemStore.h +++ b/src/os/memstore/MemStore.h @@ -96,6 +96,7 @@ public: struct PageSetObject; struct Collection : public CollectionImpl { coll_t cid; + int bits; CephContext *cct; bool use_page_set; ceph::unordered_map object_hash; ///< for lookup @@ -223,7 +224,7 @@ private: int _collection_hint_expected_num_objs(const coll_t& cid, uint32_t pg_num, uint64_t num_objs) const { return 0; } - int _create_collection(const coll_t& c); + int _create_collection(const coll_t& c, int bits); int _destroy_collection(const coll_t& c); int _collection_add(const coll_t& cid, const coll_t& ocid, const ghobject_t& oid); int _collection_move_rename(const coll_t& oldcid, const ghobject_t& oldoid, @@ -325,6 +326,7 @@ public: } bool collection_exists(const coll_t& c) override; int collection_empty(const coll_t& c, bool *empty) override; + int collection_bits(const coll_t& c) override; using ObjectStore::collection_list; int collection_list(const coll_t& cid, const ghobject_t& start, const ghobject_t& end, int max, From 0207654da06561cf8f21bcff86590af01b0bde01 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 17:28:57 -0400 Subject: [PATCH 03/10] os/kstore: implement collection_bits Signed-off-by: Sage Weil --- src/os/kstore/KStore.cc | 12 ++++++++++++ src/os/kstore/KStore.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/os/kstore/KStore.cc b/src/os/kstore/KStore.cc index fc7e9e4823b..0a543bc72d1 100755 --- a/src/os/kstore/KStore.cc +++ b/src/os/kstore/KStore.cc @@ -1400,6 +1400,18 @@ int KStore::collection_empty(const coll_t& cid, bool *empty) return 0; } +int KStore::collection_bits(const coll_t& cid) +{ + dout(15) << __func__ << " " << cid << dendl; + CollectionHandle ch = _get_collection(cid); + if (!ch) + return -ENOENT; + Collection *c = static_cast(ch.get()); + RWLock::RLocker l(c->lock); + dout(10) << __func__ << " " << cid << " = " << c->cnode.bits << dendl; + return c->cnode.bits; +} + int KStore::collection_list( const coll_t& cid, const ghobject_t& start, const ghobject_t& end, int max, vector *ls, ghobject_t *pnext) diff --git a/src/os/kstore/KStore.h b/src/os/kstore/KStore.h index c80deb54679..9df25f4fb4f 100644 --- a/src/os/kstore/KStore.h +++ b/src/os/kstore/KStore.h @@ -480,7 +480,7 @@ public: int list_collections(vector& ls) override; bool collection_exists(const coll_t& c) override; int collection_empty(const coll_t& c, bool *empty) override; - + int collection_bits(const coll_t& c) override; int collection_list( const coll_t& cid, const ghobject_t& start, const ghobject_t& end, int max, From 0088bcb8ce7751782edad2177e44ecdbfb40d520 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 17:29:19 -0400 Subject: [PATCH 04/10] os/filestore: stub out collectionn_bits Doesn't work yet, just a placeholder. Signed-off-by: Sage Weil --- src/os/filestore/FileStore.cc | 7 +++++++ src/os/filestore/FileStore.h | 1 + 2 files changed, 8 insertions(+) diff --git a/src/os/filestore/FileStore.cc b/src/os/filestore/FileStore.cc index 9238150ef21..c6fd5b886db 100644 --- a/src/os/filestore/FileStore.cc +++ b/src/os/filestore/FileStore.cc @@ -4789,6 +4789,13 @@ int FileStore::collection_empty(const coll_t& c, bool *empty) tracepoint(objectstore, collection_empty_exit, *empty); return 0; } + +int FileStore::collection_bits(const coll_t& c) +{ +#warning fixme + return -EAGAIN; +} + int FileStore::collection_list(const coll_t& c, const ghobject_t& orig_start, const ghobject_t& end, diff --git a/src/os/filestore/FileStore.h b/src/os/filestore/FileStore.h index a67c79f12a8..1788f5c1d44 100644 --- a/src/os/filestore/FileStore.h +++ b/src/os/filestore/FileStore.h @@ -652,6 +652,7 @@ public: // collections using ObjectStore::collection_list; + int collection_bits(const coll_t& c) override; int collection_list(const coll_t& c, const ghobject_t& start, const ghobject_t& end, int max, vector *ls, ghobject_t *next) override; From bab899c21306fe6f31af121b79554c838cd39d53 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 17:29:32 -0400 Subject: [PATCH 05/10] os/ObjectStore: make collection_bits required Signed-off-by: Sage Weil --- src/os/ObjectStore.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/os/ObjectStore.h b/src/os/ObjectStore.h index 34f28875d1d..5a168d005f6 100644 --- a/src/os/ObjectStore.h +++ b/src/os/ObjectStore.h @@ -1836,12 +1836,11 @@ public: * return the number of significant bits of the coll_t::pgid. * * This should return what the last create_collection or split_collection - * set. A lazy backend can choose not to store and report this (e.g., - * FileStore). + * set. A legacy backend may return -EAGAIN if the value is unavailable + * (because we upgraded from an older version, e.g., FileStore). */ - virtual int collection_bits(const coll_t& c) { - return -EOPNOTSUPP; - } + virtual int collection_bits(const coll_t& c) = 0; + /** * list contents of a collection that fall in the range [start, end) and no more than a specified many result From 7b3353f8edb99779d55adf0d0a552c850eb4c864 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 17:39:43 -0400 Subject: [PATCH 06/10] os/filestore: store collection bits Set on create, adjust on split, return from collection_bits(). Signed-off-by: Sage Weil --- src/os/filestore/FileStore.cc | 56 +++++++++++++++++++++++++++++++---- src/os/filestore/FileStore.h | 5 +++- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/os/filestore/FileStore.cc b/src/os/filestore/FileStore.cc index c6fd5b886db..eb3a2885110 100644 --- a/src/os/filestore/FileStore.cc +++ b/src/os/filestore/FileStore.cc @@ -1851,7 +1851,7 @@ void FileStore::init_temp_collections() temps.erase(temp); } else { dout(10) << __func__ << " creating " << temp << dendl; - r = _create_collection(temp, spos); + r = _create_collection(temp, 0, spos); assert(r == 0); } } @@ -2743,7 +2743,7 @@ void FileStore::_do_transaction( const coll_t &cid = i.get_cid(op->cid); tracepoint(objectstore, mkcoll_enter, osr_name); if (_check_replay_guard(cid, spos) > 0) - r = _create_collection(cid, spos); + r = _create_collection(cid, op->split_bits, spos); tracepoint(objectstore, mkcoll_exit, r); } break; @@ -4790,10 +4790,50 @@ int FileStore::collection_empty(const coll_t& c, bool *empty) return 0; } +int FileStore::_collection_set_bits(const coll_t& c, int bits) +{ + char fn[PATH_MAX]; + get_cdir(c, fn, sizeof(fn)); + dout(10) << "collection_set_bits " << fn << " " << bits << dendl; + char n[PATH_MAX]; + int r; + int32_t v = bits; + int fd = ::open(fn, O_RDONLY); + if (fd < 0) { + r = -errno; + goto out; + } + get_attrname("bits", n, PATH_MAX); + r = chain_fsetxattr(fd, n, (char*)&v, sizeof(v)); + VOID_TEMP_FAILURE_RETRY(::close(fd)); + out: + dout(10) << "collection_setattr " << fn << " " << bits << " = " << r << dendl; + return r; +} + int FileStore::collection_bits(const coll_t& c) { -#warning fixme - return -EAGAIN; + char fn[PATH_MAX]; + get_cdir(c, fn, sizeof(fn)); + dout(15) << "collection_bits " << fn << dendl; + int r; + char n[PATH_MAX]; + int32_t bits; + int fd = ::open(fn, O_RDONLY); + if (fd < 0) { + r = -errno; + goto out; + } + get_attrname("bits", n, PATH_MAX); + r = chain_fgetxattr(fd, n, (char*)&bits, sizeof(bits)); + VOID_TEMP_FAILURE_RETRY(::close(fd)); + if (r < 0) { + bits = r; + goto out; + } + out: + dout(10) << "collection_bits " << fn << " = " << bits << dendl; + return bits; } int FileStore::collection_list(const coll_t& c, @@ -5084,6 +5124,7 @@ int FileStore::_collection_hint_expected_num_objs(const coll_t& c, uint32_t pg_n int FileStore::_create_collection( const coll_t& c, + int bits, const SequencerPosition &spos) { char fn[PATH_MAX]; @@ -5101,11 +5142,13 @@ int FileStore::_create_collection( r = init_index(c); if (r < 0) return r; - + r = _collection_set_bits(c, bits); + if (r < 0) + return r; // create parallel temp collection, too if (!c.is_meta() && !c.is_temp()) { coll_t temp = c.get_temp(); - r = _create_collection(temp, spos); + r = _create_collection(temp, 0, spos); if (r < 0) return r; } @@ -5493,6 +5536,7 @@ int FileStore::_split_collection(const coll_t& cid, _close_replay_guard(cid, spos); _close_replay_guard(dest, spos); } + _collection_set_bits(cid, bits); if (!r && cct->_conf->filestore_debug_verify_split) { vector objects; ghobject_t next; diff --git a/src/os/filestore/FileStore.h b/src/os/filestore/FileStore.h index 1788f5c1d44..a9e51bb6e76 100644 --- a/src/os/filestore/FileStore.h +++ b/src/os/filestore/FileStore.h @@ -650,6 +650,8 @@ public: int _collection_remove_recursive(const coll_t &cid, const SequencerPosition &spos); + int _collection_set_bits(const coll_t& cid, int bits); + // collections using ObjectStore::collection_list; int collection_bits(const coll_t& c) override; @@ -683,7 +685,8 @@ public: using ObjectStore::get_omap_iterator; ObjectMap::ObjectMapIterator get_omap_iterator(const coll_t& c, const ghobject_t &oid) override; - int _create_collection(const coll_t& c, const SequencerPosition &spos); + int _create_collection(const coll_t& c, int bits, + const SequencerPosition &spos); int _destroy_collection(const coll_t& c); /** * Give an expected number of objects hint to the collection. From 7dd5dd62e0edd0d7b10d020352bb8acb6702ac0b Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 17:40:07 -0400 Subject: [PATCH 07/10] os/ObjectStore: add collection_set_bits op This is only for FileStore, the only one that doesn't already store it. Signed-off-by: Sage Weil --- src/os/ObjectStore.h | 16 +++++++++++++++- src/os/Transaction.cc | 9 +++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/os/ObjectStore.h b/src/os/ObjectStore.h index 5a168d005f6..e2cc6e9f910 100644 --- a/src/os/ObjectStore.h +++ b/src/os/ObjectStore.h @@ -403,6 +403,8 @@ public: OP_COLL_HINT = 40, // cid, type, bl OP_TRY_RENAME = 41, // oldcid, oldoid, newoid + + OP_COLL_SET_BITS = 42, // cid, bits }; // Transaction hint type @@ -429,7 +431,8 @@ public: }; __le64 expected_object_size; //OP_SETALLOCHINT __le64 expected_write_size; //OP_SETALLOCHINT - __le32 split_bits; //OP_SPLIT_COLLECTION2 + __le32 split_bits; //OP_SPLIT_COLLECTION2,OP_COLL_SET_BITS, + //OP_MKCOLL __le32 split_rem; //OP_SPLIT_COLLECTION2 } __attribute__ ((packed)) ; @@ -677,6 +680,7 @@ public: case OP_COLL_RMATTR: case OP_COLL_SETATTRS: case OP_COLL_HINT: + case OP_COLL_SET_BITS: assert(op->cid < cm.size()); op->cid = cm[op->cid]; break; @@ -1392,6 +1396,16 @@ public: data.ops++; } + void collection_set_bits( + coll_t cid, + int bits) { + Op* _op = _get_next_op(); + _op->op = OP_COLL_SET_BITS; + _op->cid = _get_coll_id(cid); + _op->split_bits = bits; + data.ops++; + } + /// Set allocation hint for an object /// make 0 values(expected_object_size, expected_write_size) noops for all implementations void set_alloc_hint( diff --git a/src/os/Transaction.cc b/src/os/Transaction.cc index b07183c61d2..8840d7cb25a 100644 --- a/src/os/Transaction.cc +++ b/src/os/Transaction.cc @@ -219,6 +219,15 @@ void ObjectStore::Transaction::dump(ceph::Formatter *f) } break; + case Transaction::OP_COLL_SET_BITS: + { + coll_t cid = i.get_cid(op->cid); + f->dump_string("op_name", "coll_set_bits"); + f->dump_stream("collection") << cid; + f->dump_unsigned("bits", op->split_bits); + } + break; + case Transaction::OP_RMCOLL: { coll_t cid = i.get_cid(op->cid); From d6e512b7af4277871672a164f50683675bc2f61c Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 17:40:17 -0400 Subject: [PATCH 08/10] os/filestore: implement collection_set_bits Signed-off-by: Sage Weil --- src/os/filestore/FileStore.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/os/filestore/FileStore.cc b/src/os/filestore/FileStore.cc index eb3a2885110..e14c72a6d00 100644 --- a/src/os/filestore/FileStore.cc +++ b/src/os/filestore/FileStore.cc @@ -2748,6 +2748,14 @@ void FileStore::_do_transaction( } break; + case Transaction::OP_COLL_SET_BITS: + { + const coll_t &cid = i.get_cid(op->cid); + int bits = op->split_bits; + r = _collection_set_bits(cid, bits); + } + break; + case Transaction::OP_COLL_HINT: { const coll_t &cid = i.get_cid(op->cid); From d342ff1bc048ccfd437879329e01f923e0a87287 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 18:05:32 -0400 Subject: [PATCH 09/10] osd/PG: fix filestore collections' bits Legacy FileStore didn't store the bit width of a collection, which prevents you from duplicating/ converting the store to something else (BlueStore). Fix it up on startup. Signed-off-by: Sage Weil --- src/osd/PG.cc | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/osd/PG.cc b/src/osd/PG.cc index 537b5241b5e..71b3518c220 100644 --- a/src/osd/PG.cc +++ b/src/osd/PG.cc @@ -5753,6 +5753,21 @@ void PG::update_store_with_options() if(r < 0 && r != -EOPNOTSUPP) { derr << __func__ << "set_collection_opts returns error:" << r << dendl; } + + if (osd->store->get_type() == "filestore") { + // legacy filestore didn't store collection bit width; fix. + int bits = osd->store->collection_bits(coll); + if (bits < 0) { + if (coll.is_meta()) + bits = 0; + else + bits = info.pgid.get_split_bits(pool.info.get_pg_num()); + lderr(cct) << __func__ << " setting bit width to " << bits << dendl; + ObjectStore::Transaction t; + t.collection_set_bits(coll, bits); + osd->store->apply_transaction(osr.get(), std::move(t)); + } + } } std::ostream& operator<<(std::ostream& oss, From c279a2de0b677f547b2eba750cef12d41726205b Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 28 Mar 2017 22:19:11 -0400 Subject: [PATCH 10/10] test/osd/osd-dup.sh: filestore -> bluestore conversion test Pretty basic; just verifies the osd restarts and scrub doesn't immediately turn up problems. Signed-off-by: Sage Weil --- src/test/osd/CMakeLists.txt | 1 + src/test/osd/osd-dup.sh | 72 +++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100755 src/test/osd/osd-dup.sh diff --git a/src/test/osd/CMakeLists.txt b/src/test/osd/CMakeLists.txt index 35e07ad3e71..f5985dc5428 100644 --- a/src/test/osd/CMakeLists.txt +++ b/src/test/osd/CMakeLists.txt @@ -27,6 +27,7 @@ add_ceph_test(osd-scrub-repair.sh ${CMAKE_CURRENT_SOURCE_DIR}/osd-scrub-repair.s add_ceph_test(osd-scrub-snaps.sh ${CMAKE_CURRENT_SOURCE_DIR}/osd-scrub-snaps.sh) add_ceph_test(osd-copy-from.sh ${CMAKE_CURRENT_SOURCE_DIR}/osd-copy-from.sh) add_ceph_test(osd-fast-mark-down.sh ${CMAKE_CURRENT_SOURCE_DIR}/osd-fast-mark-down.sh) +add_ceph_test(osd-dup.sh ${CMAKE_CURRENT_SOURCE_DIR}/osd-dup.sh) # unittest_osdmap add_executable(unittest_osdmap diff --git a/src/test/osd/osd-dup.sh b/src/test/osd/osd-dup.sh new file mode 100755 index 00000000000..d0961143941 --- /dev/null +++ b/src/test/osd/osd-dup.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +source $(dirname $0)/../detect-build-env-vars.sh +source $CEPH_ROOT/qa/workunits/ceph-helpers.sh + +function run() { + local dir=$1 + shift + + export CEPH_MON="127.0.0.1:7146" # git grep '\<7146\>' : there must be only one + export CEPH_ARGS + CEPH_ARGS+="--fsid=$(uuidgen) --auth-supported=none " + CEPH_ARGS+="--mon-host=$CEPH_MON " + CEPH_ARGS+="--enable-experimental-unrecoverable-data-corrupting-features bluestore " + local funcs=${@:-$(set | sed -n -e 's/^\(TEST_[0-9a-z_]*\) .*/\1/p')} + for func in $funcs ; do + setup $dir || return 1 + $func $dir || return 1 + teardown $dir || return 1 + done +} + +function TEST_filestore_to_bluestore() { + local dir=$1 + + run_mon $dir a || return 1 + run_osd $dir 0 || return 1 + osd_pid=$(cat $dir/osd.0.pid) + run_osd $dir 1 || return 1 + run_osd $dir 2 || return 1 + + sleep 5 + + ceph osd pool create foo 16 + + # write some objects + rados bench -p foo 10 write -b 4096 --no-cleanup || return 1 + + # kill + while kill $osd_pid; do sleep 1 ; done + ceph osd down 0 + + mv $dir/0 $dir/0.old || return 1 + mkdir $dir/0 || return 1 + ofsid=$(cat $dir/0.old/fsid) + echo "osd fsid $ofsid" + O=$CEPH_ARGS + CEPH_ARGS+="--log-file $dir/cot.log --log-max-recent 0 " + ceph-objectstore-tool --type bluestore --data-path $dir/0 --fsid $ofsid \ + --op mkfs || return 1 + ceph-objectstore-tool --data-path $dir/0.old --target-data-path $dir/0 \ + --op dup || return 1 + CEPH_ARGS=$O + + run_osd $dir 0 || return 1 + + while ! ceph osd stat | grep '3 up' ; do sleep 1 ; done + ceph osd metadata 0 | grep bluestore || return 1 + + ceph osd scrub 0 + + # give it some time + sleep 15 + + ceph -s | grep '20 active+clean' || return 1 +} + +main osd-dup "$@" + +# Local Variables: +# compile-command: "cd ../.. ; make -j4 && test/osd/osd-dup.sh" +# End: