Skip to content

Commit b550e1c

Browse files
committed
tools/ceph_objectstore_tool: add op "expand-log"
There are circumstances in which, although we can't find enough OSDs to form a valid ec acting set, we can enough OSDs that are fully backfilled and it's only because their PGLog are lagged behind that they can't be added the acting set. In this case, right now, we can only drop the entire pg's data by recreating it. This commit add the ability to fill in the pg log gap between the backfilled OSDs and the auth log shard, so the pg can be brought to active losing only part of its data and those uncorruped data can be recovered. Signed-off-by: Xuehan Xu <[email protected]>
1 parent a973827 commit b550e1c

File tree

1 file changed

+98
-2
lines changed

1 file changed

+98
-2
lines changed

src/tools/ceph_objectstore_tool.cc

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,6 +1057,84 @@ int get_osdmap(ObjectStore *store, epoch_t e, OSDMap &osdmap, bufferlist& bl)
10571057
return 0;
10581058
}
10591059

1060+
int expand_log(
1061+
CephContext *cct,
1062+
ObjectStore *fs,
1063+
spg_t pgid,
1064+
pg_info_t &info,
1065+
eversion_t target_version)
1066+
{
1067+
try {
1068+
bufferlist bl;
1069+
OSDMap osdmap;
1070+
int ret = get_osdmap(fs, info.last_update.epoch, osdmap, bl);
1071+
if (ret < 0) {
1072+
std::cerr << "Can't find latest local OSDMap " << info.last_update.epoch << std::endl;
1073+
return ret;
1074+
}
1075+
ceph_assert(osdmap.have_pg_pool(info.pgid.pool()));
1076+
auto pool_info = osdmap.get_pg_pool(info.pgid.pool());
1077+
if (!pool_info->is_erasure()) {
1078+
std::cerr << "extend-log-with-fake-entries can only apply to pgs of ec pools" << std::endl;
1079+
return -EINVAL;
1080+
}
1081+
1082+
PGLog log(cct);
1083+
pg_missing_t missing;
1084+
auto ch = fs->open_collection(coll_t(pgid));
1085+
if (!ch) {
1086+
return -ENOENT;
1087+
}
1088+
ostringstream oss;
1089+
log.read_log_and_missing(
1090+
fs, ch,
1091+
pgid.make_pgmeta_oid(),
1092+
info,
1093+
oss,
1094+
cct->_conf->osd_ignore_stale_divergent_priors,
1095+
cct->_conf->osd_debug_verify_missing_on_start);
1096+
if (debug && oss.str().size())
1097+
cerr << oss.str() << std::endl;
1098+
1099+
auto e = target_version;
1100+
e.version = log.get_head().version + 1;
1101+
auto entry = *log.get_log().log.rbegin();
1102+
for (; e <= target_version; e.version++) {
1103+
entry.version = e;
1104+
std::cout << "adding " << e << std::endl;
1105+
log.add(entry, true);
1106+
}
1107+
info.last_complete = target_version;
1108+
info.last_update = target_version;
1109+
info.last_user_version = target_version.version + 1;
1110+
1111+
std::map<string, bufferlist> km;
1112+
ObjectStore::Transaction t;
1113+
1114+
pg_fast_info_t fast;
1115+
fast.populate_from(info);
1116+
encode(fast, km[string(fastinfo_key)]);
1117+
encode(info, km[string(info_key)]);
1118+
log.write_log_and_missing(
1119+
t,
1120+
&km,
1121+
coll_t(pgid),
1122+
pgid.make_pgmeta_oid(),
1123+
pool_info->require_rollback());
1124+
1125+
for (auto &ent : km) {
1126+
std::cout << "km key: " << ent.first << std::endl;
1127+
}
1128+
1129+
t.omap_setkeys(coll_t(pgid), pgid.make_pgmeta_oid(), km);
1130+
fs->queue_transaction(ch, std::move(t));
1131+
return 0;
1132+
} catch (const buffer::error &e) {
1133+
cerr << "read_log_and_missing threw exception error " << e.what() << std::endl;
1134+
return -EFAULT;
1135+
}
1136+
}
1137+
10601138
int get_pg_num_history(ObjectStore *store, pool_pg_num_history_t *h)
10611139
{
10621140
ObjectStore::CollectionHandle ch = store->open_collection(coll_t::meta());
@@ -3350,7 +3428,7 @@ bool ends_with(const string& check, const string& ending)
33503428
int main(int argc, char **argv)
33513429
{
33523430
string dpath, jpath, pgidstr, op, file, mountpoint, mon_store_path, object;
3353-
string target_data_path, fsid;
3431+
string target_data_path, fsid, target_version_str;
33543432
string objcmd, arg1, arg2, type, format, argnspace, pool, rmtypestr, dump_data_dir;
33553433
boost::optional<std::string> nspace;
33563434
spg_t pgid;
@@ -3368,6 +3446,8 @@ int main(int argc, char **argv)
33683446
"Arg is one of [bluestore (default), memstore]")
33693447
("data-path", po::value<string>(&dpath),
33703448
"path to object store, mandatory")
3449+
("target-version", po::value<string>(&target_version_str),
3450+
"the target version that log is expected to be expanded to")
33713451
("journal-path", po::value<string>(&jpath),
33723452
"path to journal, use if tool can't find it")
33733453
("pgid", po::value<string>(&pgidstr),
@@ -3623,6 +3703,18 @@ int main(int argc, char **argv)
36233703
return 1;
36243704
}
36253705

3706+
eversion_t target_version;
3707+
if (op == "extend-log-with-fake-entries") {
3708+
if (target_version_str.empty()) {
3709+
std::cerr << "target-version needed" << std::endl;
3710+
return 1;
3711+
}
3712+
std::string epoch_str = target_version_str.substr(0, target_version_str.find("."));
3713+
std::string version_str = target_version_str.substr(target_version_str.find(".") + 1);
3714+
target_version.epoch = std::stoi(epoch_str);
3715+
target_version.version = std::stoll(version_str);
3716+
}
3717+
36263718
std::unique_ptr<ObjectStore> fs = ObjectStore::create(g_ceph_context, type, dpath, jpath, flags);
36273719
if (!fs) {
36283720
cerr << "Unable to create store of type " << type << std::endl;
@@ -4110,7 +4202,7 @@ int main(int argc, char **argv)
41104202

41114203
// If not an object command nor any of the ops handled below, then output this usage
41124204
// before complaining about a bad pgid
4113-
if (!vm.count("objcmd") && op != "export" && op != "export-remove" && op != "info" && op != "log" && op != "mark-complete" && op != "trim-pg-log" && op != "trim-pg-log-dups" && op != "pg-log-inject-dups") {
4205+
if (!vm.count("objcmd") && op != "export" && op != "export-remove" && op != "info" && op != "log" && op != "mark-complete" && op != "trim-pg-log" && op != "trim-pg-log-dups" && op != "pg-log-inject-dups" && op != "extend-log-with-fake-entries") {
41144206
cerr << "Must provide --op (info, log, remove, mkfs, fsck, repair, export, export-remove, import, list, fix-lost, list-pgs, dump-super, meta-list, "
41154207
"get-osdmap, set-osdmap, get-inc-osdmap, set-inc-osdmap, mark-complete, reset-last-complete, dump-export, trim-pg-log, trim-pg-log-dups statfs)"
41164208
<< std::endl;
@@ -4426,6 +4518,10 @@ int main(int argc, char **argv)
44264518
goto out;
44274519

44284520
dump_log(formatter, cout, log, missing);
4521+
} else if (op == "extend-log-with-fake-entries") {
4522+
ret = expand_log(cct.get(), fs.get(), pgid, info, target_version);
4523+
if (ret < 0)
4524+
goto out;
44294525
} else if (op == "mark-complete") {
44304526
ObjectStore::Transaction tran;
44314527
ObjectStore::Transaction *t = &tran;

0 commit comments

Comments
 (0)