using crimson::osd::OSD;
using namespace crimson::common;
+namespace {
+seastar::logger& logger()
+{
+ return crimson::get_logger(ceph_subsys_osd);
+}
+} // namespace
+
namespace crimson::admin {
using crimson::common::local_conf;
};
template std::unique_ptr<AdminSocketHook> make_asok_hook<SeastarMetricsHook>();
+
+static ghobject_t test_ops_get_object_name(
+ const OSDMap& osdmap,
+ const cmdmap_t& cmdmap)
+{
+ auto pool = [&] {
+ auto pool_arg = cmd_getval<std::string>(cmdmap, "pool");
+ if (!pool_arg) {
+ throw std::invalid_argument{"No 'pool' specified"};
+ }
+ int64_t pool = osdmap.lookup_pg_pool_name(*pool_arg);
+ if (pool < 0 && std::isdigit((*pool_arg)[0])) {
+ pool = std::atoll(pool_arg->c_str());
+ }
+ if (pool < 0) {
+ // the return type of `fmt::format` is `std::string`
+ using namespace fmt::literals;
+ throw std::invalid_argument{
+ "Invalid pool '{}'"_format(*pool_arg)
+ };
+ }
+ return pool;
+ }();
+
+ auto [ objname, nspace, raw_pg ] = [&] {
+ auto obj_arg = cmd_getval<std::string>(cmdmap, "objname");
+ if (!obj_arg) {
+ throw std::invalid_argument{"No 'objname' specified"};
+ }
+ std::string objname, nspace;
+ if (std::size_t sep_pos = obj_arg->find_first_of('/');
+ sep_pos != obj_arg->npos) {
+ nspace = obj_arg->substr(0, sep_pos);
+ objname = obj_arg->substr(sep_pos+1);
+ } else {
+ objname = *obj_arg;
+ }
+ pg_t raw_pg;
+ if (object_locator_t oloc(pool, nspace);
+ osdmap.object_locator_to_pg(object_t(objname), oloc, raw_pg) < 0) {
+ throw std::invalid_argument{"Invalid namespace/objname"};
+ }
+ return std::make_tuple(std::move(objname),
+ std::move(nspace),
+ std::move(raw_pg));
+ }();
+
+ auto shard_id = cmd_getval_or<int64_t>(cmdmap,
+ "shardid",
+ shard_id_t::NO_SHARD);
+
+ return ghobject_t{
+ hobject_t{
+ object_t{objname}, std::string{}, CEPH_NOSNAP, raw_pg.ps(), pool, nspace
+ },
+ ghobject_t::NO_GEN,
+ shard_id_t{static_cast<int8_t>(shard_id)}
+ };
+}
+
+// Usage:
+// injectdataerr <pool> [namespace/]<obj-name> [shardid]
+class InjectDataErrorHook : public AdminSocketHook {
+public:
+ InjectDataErrorHook(crimson::osd::ShardServices& shard_services) :
+ AdminSocketHook("injectdataerr",
+ "name=pool,type=CephString " \
+ "name=objname,type=CephObjectname " \
+ "name=shardid,type=CephInt,req=false,range=0|255",
+ "inject data error to an object"),
+ shard_services(shard_services) {
+ }
+
+ seastar::future<tell_result_t> call(const cmdmap_t& cmdmap,
+ std::string_view format,
+ ceph::bufferlist&& input) const final
+ {
+ ghobject_t obj;
+ try {
+ obj = test_ops_get_object_name(*shard_services.get_osdmap(), cmdmap);
+ } catch (const std::invalid_argument& e) {
+ logger().info("error during data error injection: {}", e.what());
+ return seastar::make_ready_future<tell_result_t>(-EINVAL,
+ e.what());
+ }
+ return shard_services.get_store().inject_data_error(obj).then([=] {
+ logger().info("successfully injected data error for obj={}", obj);
+ ceph::bufferlist bl;
+ bl.append("ok"sv);
+ return seastar::make_ready_future<tell_result_t>(0,
+ std::string{}, // no err
+ std::move(bl));
+ });
+ }
+
+private:
+ crimson::osd::ShardServices& shard_services;
+};
+template std::unique_ptr<AdminSocketHook> make_asok_hook<InjectDataErrorHook>(
+ crimson::osd::ShardServices&);
+
} // namespace crimson::admin