]> git.proxmox.com Git - ceph.git/blame - ceph/src/crimson/osd/osd_operations/background_recovery.cc
import quincy beta 17.1.0
[ceph.git] / ceph / src / crimson / osd / osd_operations / background_recovery.cc
CommitLineData
f67539c2
TL
1// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2// vim: ts=8 sw=2 smarttab
3
4#include <seastar/core/future.hh>
20effc67 5#include <seastar/core/sleep.hh>
f67539c2
TL
6
7#include "messages/MOSDOp.h"
8
9#include "crimson/osd/pg.h"
10#include "crimson/osd/shard_services.h"
11#include "common/Formatter.h"
12#include "crimson/osd/osd_operations/background_recovery.h"
13
14namespace {
15 seastar::logger& logger() {
16 return crimson::get_logger(ceph_subsys_osd);
17 }
18}
19
20namespace crimson::osd {
21
22BackgroundRecovery::BackgroundRecovery(
23 Ref<PG> pg,
24 ShardServices &ss,
25 epoch_t epoch_started,
20effc67
TL
26 crimson::osd::scheduler::scheduler_class_t scheduler_class,
27 float delay)
f67539c2
TL
28 : pg(pg),
29 epoch_started(epoch_started),
20effc67 30 delay(delay),
f67539c2
TL
31 ss(ss),
32 scheduler_class(scheduler_class)
33{}
34
35void BackgroundRecovery::print(std::ostream &lhs) const
36{
37 lhs << "BackgroundRecovery(" << pg->get_pgid() << ")";
38}
39
40void BackgroundRecovery::dump_detail(Formatter *f) const
41{
42 f->dump_stream("pgid") << pg->get_pgid();
43 f->open_object_section("recovery_detail");
44 {
45 // TODO pg->dump_recovery_state(f);
46 }
47 f->close_section();
48}
49
50seastar::future<> BackgroundRecovery::start()
51{
52 logger().debug("{}: start", *this);
53
54 IRef ref = this;
20effc67
TL
55 auto maybe_delay = seastar::now();
56 if (delay) {
57 maybe_delay = seastar::sleep(
58 std::chrono::milliseconds(std::lround(delay * 1000)));
59 }
60 return maybe_delay.then([ref, this] {
61 return ss.throttler.with_throttle_while(
62 this, get_scheduler_params(), [this] {
63 return interruptor::with_interruption([this] {
64 return do_recovery();
65 }, [](std::exception_ptr) {
66 return seastar::make_ready_future<bool>(false);
67 }, pg);
68 }).handle_exception_type([ref, this](const std::system_error& err) {
69 if (err.code() == std::make_error_code(std::errc::interrupted)) {
70 logger().debug("{} recovery interruped: {}", *pg, err.what());
71 return seastar::now();
72 }
73 return seastar::make_exception_future<>(err);
74 });
75 });
f67539c2
TL
76}
77
20effc67
TL
78UrgentRecovery::interruptible_future<bool>
79UrgentRecovery::do_recovery()
f67539c2 80{
20effc67 81 logger().debug("{}: {}", __func__, *this);
f67539c2 82 if (!pg->has_reset_since(epoch_started)) {
20effc67 83 return with_blocking_future_interruptible<interruptor::condition>(
f67539c2 84 pg->get_recovery_handler()->recover_missing(soid, need)
20effc67 85 ).then_interruptible([] {
f67539c2
TL
86 return seastar::make_ready_future<bool>(false);
87 });
88 }
89 return seastar::make_ready_future<bool>(false);
90}
91
92void UrgentRecovery::print(std::ostream &lhs) const
93{
94 lhs << "UrgentRecovery(" << pg->get_pgid() << ", "
20effc67
TL
95 << soid << ", v" << need << ", epoch_started: "
96 << epoch_started << ")";
f67539c2
TL
97}
98
99void UrgentRecovery::dump_detail(Formatter *f) const
100{
101 f->dump_stream("pgid") << pg->get_pgid();
102 f->open_object_section("recovery_detail");
103 {
104 f->dump_stream("oid") << soid;
105 f->dump_stream("version") << need;
106 }
107 f->close_section();
108}
109
110PglogBasedRecovery::PglogBasedRecovery(
111 Ref<PG> pg,
112 ShardServices &ss,
20effc67
TL
113 const epoch_t epoch_started,
114 float delay)
f67539c2
TL
115 : BackgroundRecovery(
116 std::move(pg),
117 ss,
118 epoch_started,
20effc67
TL
119 crimson::osd::scheduler::scheduler_class_t::background_recovery,
120 delay)
f67539c2
TL
121{}
122
20effc67
TL
123PglogBasedRecovery::interruptible_future<bool>
124PglogBasedRecovery::do_recovery()
f67539c2 125{
20effc67 126 if (pg->has_reset_since(epoch_started)) {
f67539c2 127 return seastar::make_ready_future<bool>(false);
20effc67
TL
128 }
129 return with_blocking_future_interruptible<interruptor::condition>(
f67539c2
TL
130 pg->get_recovery_handler()->start_recovery_ops(
131 crimson::common::local_conf()->osd_recovery_max_single_start));
132}
133
134BackfillRecovery::BackfillRecoveryPipeline &BackfillRecovery::bp(PG &pg)
135{
136 return pg.backfill_pipeline;
137}
138
20effc67
TL
139BackfillRecovery::interruptible_future<bool>
140BackfillRecovery::do_recovery()
f67539c2
TL
141{
142 logger().debug("{}", __func__);
143
144 if (pg->has_reset_since(epoch_started)) {
145 logger().debug("{}: pg got reset since epoch_started={}",
146 __func__, epoch_started);
147 return seastar::make_ready_future<bool>(false);
148 }
149 // TODO: limits
20effc67 150 return with_blocking_future_interruptible<interruptor::condition>(
f67539c2
TL
151 // process_event() of our boost::statechart machine is non-reentrant.
152 // with the backfill_pipeline we protect it from a second entry from
153 // the implementation of BackfillListener.
154 // additionally, this stage serves to synchronize with PeeringEvent.
155 handle.enter(bp(*pg).process)
20effc67 156 ).then_interruptible([this] {
f67539c2
TL
157 pg->get_recovery_handler()->dispatch_backfill_event(std::move(evt));
158 return seastar::make_ready_future<bool>(false);
159 });
160}
161
162} // namespace crimson::osd