mirror of
https://github.com/ceph/ceph
synced 2025-01-20 10:01:45 +00:00
ceph-objectstore-tool: prevent import of pg that has since merged
We currently import a portion of the PG if it has split. Merge is more complicated, though, mainly because COT is operating in a mode where it fast-forwards the PG to the latest OSDMap epoch, which means it has to implement any transformations to the PG (split/merge) independently. Avoid doing this for merge. Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
parent
44de03d5e6
commit
6bd682f53d
@ -334,6 +334,12 @@ class Thrasher:
|
||||
elif proc.exitstatus == 11:
|
||||
self.log("Attempt to import an incompatible export"
|
||||
"...ignored")
|
||||
elif proc.exitstatus == 12:
|
||||
# this should be safe to ignore because we only ever move 1
|
||||
# copy of the pg at a time, and merge is only initiated when
|
||||
# all replicas are peered and happy. /me crosses fingers
|
||||
self.log("PG merged on target"
|
||||
"...ignored")
|
||||
elif proc.exitstatus:
|
||||
raise Exception("ceph-objectstore-tool: "
|
||||
"import failure with status {ret}".
|
||||
|
@ -848,6 +848,20 @@ int get_osdmap(ObjectStore *store, epoch_t e, OSDMap &osdmap, bufferlist& bl)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int get_pg_num_history(ObjectStore *store, pool_pg_num_history_t *h)
|
||||
{
|
||||
ObjectStore::CollectionHandle ch = store->open_collection(coll_t::meta());
|
||||
bufferlist bl;
|
||||
auto pghist = OSD::make_pg_num_history_oid();
|
||||
int r = store->read(ch, pghist, 0, 0, bl, 0);
|
||||
if (r >= 0 && bl.length() > 0) {
|
||||
auto p = bl.cbegin();
|
||||
decode(*h, p);
|
||||
}
|
||||
cout << __func__ << " pg_num_history " << *h << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int add_osdmap(ObjectStore *store, metadata_section &ms)
|
||||
{
|
||||
return get_osdmap(store, ms.map_epoch, ms.osdmap, ms.osdmap_bl);
|
||||
@ -1804,6 +1818,16 @@ int ObjectStoreTool::do_import(ObjectStore *store, OSDSuperblock& sb,
|
||||
return 10; // Positive return means exit status
|
||||
}
|
||||
|
||||
const pg_pool_t *pi = curmap.get_pg_pool(pgid.pgid.m_pool);
|
||||
if (pi->get_pg_num() <= pgid.pgid.m_seed) {
|
||||
cerr << "PG " << pgid.pgid << " no longer exists" << std::endl;
|
||||
// Special exit code for this error, used by test code
|
||||
return 12; // Positive return means exit status
|
||||
}
|
||||
|
||||
pool_pg_num_history_t pg_num_history;
|
||||
get_pg_num_history(store, &pg_num_history);
|
||||
|
||||
ghobject_t pgmeta_oid = pgid.make_pgmeta_oid();
|
||||
|
||||
//Check for PG already present.
|
||||
@ -1814,20 +1838,6 @@ int ObjectStoreTool::do_import(ObjectStore *store, OSDSuperblock& sb,
|
||||
}
|
||||
|
||||
ObjectStore::CollectionHandle ch;
|
||||
if (!dry_run) {
|
||||
ObjectStore::Transaction t;
|
||||
ch = store->create_new_collection(coll);
|
||||
PG::_create(t, pgid,
|
||||
pgid.get_split_bits(curmap.get_pg_pool(pgid.pool())->get_pg_num()));
|
||||
PG::_init(t, pgid, NULL);
|
||||
|
||||
// mark this coll for removal until we're done
|
||||
map<string,bufferlist> values;
|
||||
encode((char)1, values["_remove"]);
|
||||
t.omap_setkeys(coll, pgid.make_pgmeta_oid(), values);
|
||||
|
||||
store->queue_transaction(ch, std::move(t));
|
||||
}
|
||||
|
||||
OSDriver driver(
|
||||
store,
|
||||
@ -1858,6 +1868,7 @@ int ObjectStoreTool::do_import(ObjectStore *store, OSDSuperblock& sb,
|
||||
}
|
||||
switch(type) {
|
||||
case TYPE_OBJECT_BEGIN:
|
||||
ceph_assert(found_metadata);
|
||||
ret = get_object(store, driver, mapper, coll, ebl, curmap, &skipped_objects);
|
||||
if (ret) return ret;
|
||||
break;
|
||||
@ -1865,8 +1876,51 @@ int ObjectStoreTool::do_import(ObjectStore *store, OSDSuperblock& sb,
|
||||
ret = get_pg_metadata(store, ebl, ms, sb, curmap, pgid);
|
||||
if (ret) return ret;
|
||||
found_metadata = true;
|
||||
|
||||
// make sure there are no conflicting merges
|
||||
{
|
||||
auto p = pg_num_history.pg_nums.find(pgid.pgid.m_pool);
|
||||
if (p != pg_num_history.pg_nums.end()) {
|
||||
unsigned pg_num = ms.osdmap.get_pg_num(pgid.pgid.m_pool);
|
||||
for (auto q = p->second.lower_bound(ms.map_epoch);
|
||||
q != p->second.end();
|
||||
++q) {
|
||||
pg_t parent;
|
||||
if (pgid.pgid.is_merge_source(pg_num, q->second, &parent)) {
|
||||
cerr << "PG " << pgid.pgid << " merge source in epoch "
|
||||
<< q->first << " pg_num " << pg_num
|
||||
<< " -> " << q->second << std::endl;
|
||||
return 12;
|
||||
}
|
||||
if (pgid.pgid.is_merge_target(pg_num, q->second)) {
|
||||
cerr << "PG " << pgid.pgid << " merge target in epoch "
|
||||
<< q->first << " pg_num " << pg_num
|
||||
<< " -> " << q->second << std::endl;
|
||||
return 12;
|
||||
}
|
||||
pg_num = q->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!dry_run) {
|
||||
ObjectStore::Transaction t;
|
||||
ch = store->create_new_collection(coll);
|
||||
PG::_create(t, pgid,
|
||||
pgid.get_split_bits(curmap.get_pg_pool(pgid.pool())->get_pg_num()));
|
||||
PG::_init(t, pgid, NULL);
|
||||
|
||||
// mark this coll for removal until we're done
|
||||
map<string,bufferlist> values;
|
||||
encode((char)1, values["_remove"]);
|
||||
t.omap_setkeys(coll, pgid.make_pgmeta_oid(), values);
|
||||
|
||||
store->queue_transaction(ch, std::move(t));
|
||||
}
|
||||
|
||||
break;
|
||||
case TYPE_PG_END:
|
||||
ceph_assert(found_metadata);
|
||||
done = true;
|
||||
break;
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user