void shard_info_wrapper::set_object(const ScrubMap::object& object)
{
- for (auto attr : object.attrs) {
- bufferlist bl;
- bl.push_back(attr.second);
- attrs.insert(std::make_pair(attr.first, std::move(bl)));
+ // logically no-op, changes the comparator from std::less<void>
+ // while avoiding `reinterpret_cast<const std::map<std::string,
+ // ceph::bufferlist>&>(object.attrs)`
+ attrs.clear();
+ for (const auto& kv : object.attrs) {
+ attrs.insert(kv);
}
size = object.size;
if (object.omap_digest_present) {
if (i.second.length() == 0) {
entry.attrs[i.first];
} else {
- entry.attrs.emplace(i.first, i.second.front());
+ entry.attrs.emplace(i.first, i.second);
}
}
}).handle_error_interruptible(
if (xiter == obj.attrs.end()) {
ret.shard_info.set_info_missing();
} else {
- bufferlist bl;
- bl.push_back(xiter->second);
ret.object_info = object_info_t{};
try {
- auto bliter = bl.cbegin();
+ auto bliter = xiter->second.cbegin();
::decode(*(ret.object_info), bliter);
} catch (...) {
ret.shard_info.set_info_corrupted();
if (xiter == obj.attrs.end()) {
ret.shard_info.set_snapset_missing();
} else {
- bufferlist bl;
- bl.push_back(xiter->second);
ret.snapset = SnapSet{};
try {
- auto bliter = bl.cbegin();
+ auto bliter = xiter->second.cbegin();
::decode(*(ret.snapset), bliter);
} catch (...) {
ret.shard_info.set_snapset_corrupted();
if (xiter == obj.attrs.end()) {
ret.shard_info.set_hinfo_missing();
} else {
- bufferlist bl;
- bl.push_back(xiter->second);
ret.hinfo = ECUtil::HashInfo{};
try {
- auto bliter = bl.cbegin();
+ auto bliter = xiter->second.cbegin();
decode(*(ret.hinfo), bliter);
} catch (...) {
ret.shard_info.set_hinfo_corrupted();
if (op.recovery_progress.first && op.obc) {
/* We've got the attrs and the hinfo, might as well use them */
- op.hinfo = get_hash_info(op.hoid);
+ op.hinfo = get_hash_info(op.hoid, false, &op.obc->attr_cache);
if (!op.hinfo) {
derr << __func__ << ": " << op.hoid << " has inconsistent hinfo"
<< dendl;
// Do NOT check osd_read_eio_on_bad_digest here. We need to report
// the state of our chunk in case other chunks could substitute.
ECUtil::HashInfoRef hinfo;
- hinfo = get_hash_info(i->first);
+ map<string, bufferlist, less<>> attrs;
+ int r = PGBackend::objects_get_attrs(i->first, &attrs);
+ if (r >= 0) {
+ hinfo = get_hash_info(i->first, false, &attrs);
+ } else {
+ derr << "get_hash_info" << ": stat " << i->first << " failed: "
+ << cpp_strerror(r) << dendl;
+ }
if (!hinfo) {
r = -EIO;
get_parent()->clog_error() << "Corruption detected: object "
sinfo,
*(op->t),
[&](const hobject_t &i) {
- ECUtil::HashInfoRef ref = get_hash_info(i, true);
+ ECUtil::HashInfoRef ref = get_hash_info(i, true, &op->t->obc_map[hoid]->attr_cache);
if (!ref) {
derr << __func__ << ": get_hash_info(" << i << ")"
<< " returned a null pointer and there is no "
ECUtil::HashInfoRef ECBackend::get_hash_info(
- const hobject_t &hoid, bool create, const map<string,bufferptr,less<>> *attrs)
+ const hobject_t &hoid, bool create, const map<string,bufferlist,less<>> *attrs)
{
dout(10) << __func__ << ": Getting attr on " << hoid << dendl;
ECUtil::HashInfoRef ref = unstable_hashinfo_registry.lookup(hoid);
if (r >= 0) {
dout(10) << __func__ << ": found on disk, size " << st.st_size << dendl;
bufferlist bl;
- if (attrs) {
- map<string, bufferptr>::const_iterator k = attrs->find(ECUtil::get_hinfo_key());
- if (k == attrs->end()) {
- dout(5) << __func__ << " " << hoid << " missing hinfo attr" << dendl;
- } else {
- bl.push_back(k->second);
- }
+ ceph_assert(attrs);
+ map<string, bufferlist>::const_iterator k = attrs->find(ECUtil::get_hinfo_key());
+ if (k == attrs->end()) {
+ dout(5) << __func__ << " " << hoid << " missing hinfo attr" << dendl;
} else {
- r = store->getattr(
- ch,
- ghobject_t(hoid, ghobject_t::NO_GEN, get_parent()->whoami_shard().shard),
- ECUtil::get_hinfo_key(),
- bl);
- if (r < 0) {
- dout(5) << __func__ << ": getattr failed: " << cpp_strerror(r) << dendl;
- bl.clear(); // just in case
- }
+ bl = k->second;
}
if (bl.length() > 0) {
auto bp = bl.cbegin();
const hobject_t &hoid,
map<string, bufferlist, less<>> *out)
{
- int r = store->getattrs(
- ch,
- ghobject_t(hoid, ghobject_t::NO_GEN, get_parent()->whoami_shard().shard),
- *out);
+ // call from parents -- get raw attrs, without any filtering for hinfo
+ int r = PGBackend::objects_get_attrs(hoid, out);
if (r < 0)
return r;
const ECUtil::stripe_info_t sinfo;
/// If modified, ensure that the ref is held until the update is applied
SharedPtrRegistry<hobject_t, ECUtil::HashInfo> unstable_hashinfo_registry;
- ECUtil::HashInfoRef get_hash_info(const hobject_t &hoid, bool create = false,
- const std::map<std::string, ceph::buffer::ptr, std::less<>> *attr = NULL);
+ ECUtil::HashInfoRef get_hash_info(const hobject_t &hoid, bool create,
+ const std::map<std::string, ceph::buffer::list, std::less<>> *attr);
public:
ECBackend(
o.back()->negative = true;
o.push_back(new object);
o.back()->size = 123;
- o.back()->attrs["foo"] = ceph::buffer::copy("foo", 3);
- o.back()->attrs["bar"] = ceph::buffer::copy("barval", 6);
+ {
+ bufferlist foobl;
+ foobl.push_back(ceph::buffer::copy("foo", 3));
+ o.back()->attrs["foo"] = std::move(foobl);
+ }
+ {
+ bufferlist barbl;
+ barbl.push_back(ceph::buffer::copy("barval", 6));
+ o.back()->attrs["bar"] = std::move(barbl);
+ }
}
// -- OSDOp --
*/
struct ScrubMap {
struct object {
- std::map<std::string, ceph::buffer::ptr, std::less<>> attrs;
+ std::map<std::string, ceph::buffer::list, std::less<>> attrs;
uint64_t size;
__u32 omap_digest; ///< omap crc32c
__u32 digest; ///< data crc32c
// note the special handling of (1) OI_ATTR and (2) non-printables
for (auto [k, v] : so.attrs) {
- std::string bkstr{v.raw_c_str(), v.raw_length()};
+ std::string bkstr = v.to_str();
if (k == std::string{OI_ATTR}) {
/// \todo consider parsing the OI args here. Maybe add a specific format
/// specifier
fmt::format_to(ctx.out(), "{{{}:<<OI_ATTR>>({})}} ", k, bkstr.length());
} else if (k == std::string{SS_ATTR}) {
- bufferlist bl;
- bl.push_back(v);
- SnapSet sns{bl};
+ SnapSet sns{v};
fmt::format_to(ctx.out(), "{{{}:{:D}}} ", k, sns);
} else {
fmt::format_to(ctx.out(), "{{{}:{}({})}} ", k, bkstr, bkstr.length());
if (o.attrs.find(OI_ATTR) == o.attrs.end()) {
continue;
}
- bufferlist bl;
- bl.push_back(o.attrs[OI_ATTR]);
object_info_t oi;
try {
- oi.decode(bl);
+ oi.decode(o.attrs[OI_ATTR]);
} catch (...) {
continue;
}
<< "...repaired";
// Fix object info
oi.soid = hoid;
- bl.clear();
+ bufferlist bl;
encode(oi,
bl,
m_pg->get_osdmap()->get_features(CEPH_ENTITY_TYPE_OSD, nullptr));
- bufferptr bp(bl.c_str(), bl.length());
- o.attrs[OI_ATTR] = bp;
+ o.attrs[OI_ATTR] = std::move(bl);
t.setattr(m_pg->coll, ghobject_t(hoid), OI_ATTR, bl);
int r = m_pg->osd->store->queue_transaction(m_pg->ch, std::move(t));
try {
bufferlist bv;
if (po.attrs.count(OI_ATTR)) {
- bv.push_back(po.attrs.find(OI_ATTR)->second);
+ bv = po.attrs.find(OI_ATTR)->second;
}
auto bliter = bv.cbegin();
decode(oi, bliter);
&shard_info_wrapper::set_snapset_missing,
"candidate had a missing snapset key"sv,
errstream)) {
- bufferlist ss_bl;
+ const bufferlist& ss_bl = k->second;
SnapSet snapset;
- ss_bl.push_back(k->second);
try {
auto bliter = ss_bl.cbegin();
decode(snapset, bliter);
&shard_info_wrapper::set_hinfo_missing,
"candidate had a missing hinfo key"sv,
errstream)) {
- bufferlist hk_bl;
+ const bufferlist& hk_bl = k->second;
ECUtil::HashInfo hi;
- hk_bl.push_back(k->second);
try {
auto bliter = hk_bl.cbegin();
decode(hi, bliter);
return shard_as_auth_t{errstream.str()};
}
- bufferlist bl;
- bl.push_back(k->second);
try {
- auto bliter = bl.cbegin();
+ auto bliter = k->second.cbegin();
decode(oi, bliter);
} catch (...) {
// invalid object info, probably corrupt
auto can_attr = candidate.attrs.find(OI_ATTR);
ceph_assert(can_attr != candidate.attrs.end());
- bufferlist can_bl;
- can_bl.push_back(can_attr->second);
+ const bufferlist& can_bl = can_attr->second;
auto auth_attr = auth.attrs.find(OI_ATTR);
ceph_assert(auth_attr != auth.attrs.end());
- bufferlist auth_bl;
- auth_bl.push_back(auth_attr->second);
+ const bufferlist& auth_bl = auth_attr->second;
if (!can_bl.contents_equal(auth_bl)) {
fmt::format_to(std::back_inserter(out),
auto can_attr = candidate.attrs.find(SS_ATTR);
ceph_assert(can_attr != candidate.attrs.end());
- bufferlist can_bl;
- can_bl.push_back(can_attr->second);
+ const bufferlist& can_bl = can_attr->second;
auto auth_attr = auth.attrs.find(SS_ATTR);
ceph_assert(auth_attr != auth.attrs.end());
- bufferlist auth_bl;
- auth_bl.push_back(auth_attr->second);
+ const bufferlist& auth_bl = auth_attr->second;
if (!can_bl.contents_equal(auth_bl)) {
fmt::format_to(std::back_inserter(out),
auto can_hi = candidate.attrs.find(ECUtil::get_hinfo_key());
ceph_assert(can_hi != candidate.attrs.end());
- bufferlist can_bl;
- can_bl.push_back(can_hi->second);
+ const bufferlist& can_bl = can_hi->second;
auto auth_hi = auth.attrs.find(ECUtil::get_hinfo_key());
ceph_assert(auth_hi != auth.attrs.end());
- bufferlist auth_bl;
- auth_bl.push_back(auth_hi->second);
+ const bufferlist& auth_bl = auth_hi->second;
if (!can_bl.contents_equal(auth_bl)) {
fmt::format_to(std::back_inserter(out),
sep(error),
k);
obj_result.set_attr_name_mismatch();
- } else if (cand->second.cmp(v)) {
+ } else if (!cand->second.contents_equal(v)) {
fmt::format_to(std::back_inserter(out),
"{}attr value mismatch '{}'",
sep(error),
this_chunk->m_error_counts.shallow_errors++;
soid_error.set_info_missing();
} else {
- bufferlist bv;
- bv.push_back(p->second.attrs[OI_ATTR]);
try {
- oi = object_info_t(bv);
+ oi = object_info_t(std::as_const(p->second.attrs[OI_ATTR]));
} catch (ceph::buffer::error& e) {
oi = std::nullopt;
clog.error() << m_mode_desc << " " << m_pg_id << " " << soid
snapset = std::nullopt;
head_error.set_snapset_missing();
} else {
- bufferlist bl;
- bl.push_back(p->second.attrs[SS_ATTR]);
- auto blp = bl.cbegin();
+ auto blp = p->second.attrs[SS_ATTR].cbegin();
try {
snapset = SnapSet(); // Initialize optional<> before decoding into it
decode(*snapset, blp);
- head_error.ss_bl.push_back(p->second.attrs[SS_ATTR]);
+ head_error.ss_bl.append(p->second.attrs[SS_ATTR]);
} catch (ceph::buffer::error& e) {
snapset = std::nullopt;
clog.error() << m_mode_desc << " " << m_pg_id << " " << soid
if (hoid.is_head()) {
// parse the SnapSet
- bufferlist bl;
if (o.attrs.find(SS_ATTR) == o.attrs.end()) {
// no snaps for this head
continue;
}
- bl.push_back(o.attrs[SS_ATTR]);
- auto p = bl.cbegin();
+ auto p = o.attrs[SS_ATTR].cbegin();
try {
decode(snapset, p);
} catch (...) {
void so_set_attr_len(ScrubMap::object &obj, const std::string &name, size_t len)
{
- obj.attrs[name] = buffer::ptr(len);
+ obj.attrs[name] = bufferlist();
+ obj.attrs[name].push_back(buffer::ptr(len));
}
void so_set_attr(ScrubMap::object &obj, const std::string &name, bufferlist bl)
{
bl.rebuild();
- obj.attrs[name] = bl.front();
+ obj.attrs[name] = bl;
}
std::optional<bufferlist> so_get_attr(
ScrubMap::object &obj, const std::string &name)
{
if (obj.attrs.count(name)) {
- bufferlist bl;
- bl.push_back(obj.attrs[name]);
- return bl;
+ return obj.attrs[name];
} else {
return std::nullopt;
}
using namespace ScrubGenerator;
// ref: PGLogTestRebuildMissing()
-bufferptr create_object_info(const ScrubGenerator::RealObj& objver)
+bufferlist create_object_info(const ScrubGenerator::RealObj& objver)
{
object_info_t oi{};
oi.soid = objver.ghobj.hobj;
bufferlist bl;
oi.encode(bl,
0 /*get_osdmap()->get_features(CEPH_ENTITY_TYPE_OSD, nullptr)*/);
- bufferptr bp(bl.c_str(), bl.length());
- return bp;
+ return bl;
}
-std::pair<bufferptr, std::vector<snapid_t>> create_object_snapset(
+std::pair<bufferlist, std::vector<snapid_t>> create_object_snapset(
const ScrubGenerator::RealObj& robj,
const SnapsetMockData* snapset_mock_data)
{
if (!snapset_mock_data) {
- return {bufferptr(), {}};
+ return {bufferlist(), {}};
}
/// \todo fill in missing version/osd details from the robj
auto sns = snapset_mock_data->make_snapset();
bufferlist bl;
encode(sns, bl);
- bufferptr bp = bufferptr(bl.c_str(), bl.length());
// extract the set of object snaps
- return {bp, sns.snaps};
+ return {bl, sns.snaps};
}
RealObjsConfList ScrubGenerator::make_real_objs_conf(
ret.ghobj = blueprint.ghobj;
ret.smobj.attrs[OI_ATTR] = create_object_info(blueprint);
if (blueprint.snapset_mock_data) {
- auto [bp, snaps] =
+ auto [bl, snaps] =
create_object_snapset(blueprint, blueprint.snapset_mock_data);
- ret.smobj.attrs[SS_ATTR] = bp;
+ ret.smobj.attrs[SS_ATTR] = bl;
std::cout << fmt::format("{}: ({}) osd:{} snaps:{}",
__func__,
ret.ghobj.hobj,
}
for (const auto& [at_k, at_v] : blueprint.data.attrs) {
- ret.smobj.attrs[at_k] = ceph::buffer::copy(at_v.c_str(), at_v.size());
+ // deep copy assignment
+ ret.smobj.attrs[at_k].clear();
+ ret.smobj.attrs[at_k].append(at_v.c_str(), at_v.size());
{
// verifying (to be removed after dev phase)
- auto bk = ret.smobj.attrs[at_k].begin_deep().get_ptr(
- ret.smobj.attrs[at_k].length());
- std::string bkstr{bk.raw_c_str(), bk.raw_length()};
+ std::string bkstr = ret.smobj.attrs[at_k].to_str();
std::cout << fmt::format("{}: verification: {}", __func__, bkstr)
<< std::endl;
}