with special handling for the 0-replica case.
Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
act_token);
}
-void OSDService::queue_for_scrub_granted(PG* pg, Scrub::scrub_prio_t with_priority)
-{
- // Resulting scrub event: 'RemotesReserved'
- queue_scrub_event_msg<PGScrubResourcesOK>(pg, with_priority);
-}
-
void OSDService::queue_for_scrub_resched(PG* pg, Scrub::scrub_prio_t with_priority)
{
// Resulting scrub event: 'InternalSchedScrub'
void queue_scrub_after_repair(PG* pg, Scrub::scrub_prio_t with_priority);
- /// queue the message (-> event) that all replicas have reserved scrub resources for us
- void queue_for_scrub_granted(PG* pg, Scrub::scrub_prio_t with_priority);
-
/// Signals either (a) the end of a sleep period, or (b) a recheck of the availability
/// of the primary map being created by the backend.
void queue_for_scrub_resched(PG* pg, Scrub::scrub_prio_t with_priority);
"SchedReplica");
}
- void scrub_send_resources_granted(epoch_t queued, ThreadPool::TPHandle& handle)
- {
- forward_scrub_event(&ScrubPgIF::send_remotes_reserved, queued, "RemotesReserved");
- }
-
void scrub_send_scrub_resched(epoch_t queued, ThreadPool::TPHandle& handle)
{
forward_scrub_event(&ScrubPgIF::send_scrub_resched, queued, "InternalSchedScrub");
pg->unlock();
}
-void PGScrubResourcesOK::run(OSD* osd,
- OSDShard* sdata,
- PGRef& pg,
- ThreadPool::TPHandle& handle)
-{
- pg->scrub_send_resources_granted(epoch_queued, handle);
- pg->unlock();
-}
-
void PGScrubPushesUpdate::run(OSD* osd,
OSDShard* sdata,
PGRef& pg,
void run(OSD* osd, OSDShard* sdata, PGRef& pg, ThreadPool::TPHandle& handle) final;
};
-/**
- * all replicas have granted our scrub resources request
- */
-class PGScrubResourcesOK : public PGScrubItem {
- public:
- PGScrubResourcesOK(spg_t pg, epoch_t epoch_queued)
- : PGScrubItem{pg, epoch_queued, "PGScrubResourcesOK"}
- {}
- void run(OSD* osd, OSDShard* sdata, PGRef& pg, ThreadPool::TPHandle& handle) final;
-};
-
/**
* called when a repair process completes, to initiate scrubbing. No local/remote
* resources are allocated.
dout(10) << "scrubber event --<< " << __func__ << dendl;
}
-void PgScrubber::send_remotes_reserved(epoch_t epoch_queued)
-{
- dout(10) << "scrubber event -->> " << __func__ << " epoch: " << epoch_queued
- << dendl;
- // note: scrub is not active yet
- if (check_interval(epoch_queued)) {
- m_fsm->process_event(RemotesReserved{});
- }
- dout(10) << "scrubber event --<< " << __func__ << dendl;
-}
-
void PgScrubber::send_chunk_free(epoch_t epoch_queued)
{
dout(10) << "scrubber event -->> " << __func__ << " epoch: " << epoch_queued
void send_preempted_replica() final;
- void send_remotes_reserved(epoch_t epoch_queued) final;
-
/**
* does the PG have newer updates than what we (the scrubber) know?
*/
// initiate the reservation process
context<Session>().m_reservations.emplace(*scrbr);
- auto timeout = scrbr->get_pg_cct()->_conf.get_val<milliseconds>(
- "osd_scrub_reservation_timeout");
- if (timeout.count() > 0) {
- // Start a timer to handle case where the replicas take a long time to
- // ack the reservation. See ReservationTimeout handler below.
- m_timeout_token = machine.schedule_timer_event_after<ReservationTimeout>(
- timeout);
+ if (context<Session>().m_reservations->get_last_sent()) {
+ // the 1'st reservation request was sent
+
+ auto timeout = scrbr->get_pg_cct()->_conf.get_val<milliseconds>(
+ "osd_scrub_reservation_timeout");
+ if (timeout.count() > 0) {
+ // Start a timer to handle case where the replicas take a long time to
+ // ack the reservation. See ReservationTimeout handler below.
+ m_timeout_token =
+ machine.schedule_timer_event_after<ReservationTimeout>(timeout);
+ }
+ } else {
+ // no replicas to reserve
+ dout(10) << "no replicas to reserve" << dendl;
+ // can't transit directly from here
+ post_event(RemotesReserved{});
}
}
DECLARE_LOCALS; // 'scrbr' & 'pg_id' aliases
dout(10) << "ReservingReplicas::react(const ReplicaGrant&)" << dendl;
- context<Session>().m_reservations->handle_reserve_grant(ev.m_op, ev.m_from);
+ if (context<Session>().m_reservations->handle_reserve_grant(
+ ev.m_op, ev.m_from)) {
+ // we are done with the reservation process
+ return transit<ActiveScrubbing>();
+ }
return discard_event();
}
release_all();
}
-void ReplicaReservations::handle_reserve_grant(OpRequestRef op, pg_shard_t from)
+bool ReplicaReservations::handle_reserve_grant(OpRequestRef op, pg_shard_t from)
{
// verify that the grant is from the peer we expected. If not?
// for now - abort the OSD. \todo reconsider the reaction.
get_last_sent().value_or(pg_shard_t{}))
<< dendl;
ceph_assert(from == get_last_sent());
- return;
+ return false;
}
auto elapsed = clock::now() - m_last_request_sent_at;
active_requests_cnt(), m_sorted_secondaries.size(),
duration_cast<milliseconds>(elapsed).count())
<< dendl;
- send_next_reservation_or_complete();
+ return send_next_reservation_or_complete();
}
-void ReplicaReservations::send_next_reservation_or_complete()
+bool ReplicaReservations::send_next_reservation_or_complete()
{
if (m_next_to_request == m_sorted_secondaries.cend()) {
// granted by all replicas
dout(10) << "remote reservation complete" << dendl;
- m_osds->queue_for_scrub_granted(m_pg, scrub_prio_t::low_priority);
-
- } else {
- // send the next reservation request
- const auto peer = *m_next_to_request;
- const auto epoch = m_pg->get_osdmap_epoch();
- auto m = make_message<MOSDScrubReserve>(
- spg_t{m_pgid, peer.shard}, epoch, MOSDScrubReserve::REQUEST,
- m_pg->pg_whoami);
- m_pg->send_cluster_message(peer.osd, m, epoch, false);
- m_last_request_sent_at = clock::now();
- dout(10) << fmt::format(
- "reserving {} (the {} of {} replicas)", *m_next_to_request,
- active_requests_cnt()+1, m_sorted_secondaries.size())
- << dendl;
- m_next_to_request++;
+ return true; // done
}
+
+ // send the next reservation request
+ const auto peer = *m_next_to_request;
+ const auto epoch = m_pg->get_osdmap_epoch();
+ auto m = make_message<MOSDScrubReserve>(
+ spg_t{m_pgid, peer.shard}, epoch, MOSDScrubReserve::REQUEST,
+ m_pg->pg_whoami);
+ m_pg->send_cluster_message(peer.osd, m, epoch, false);
+ m_last_request_sent_at = clock::now();
+ dout(10) << fmt::format(
+ "reserving {} (the {} of {} replicas)", *m_next_to_request,
+ active_requests_cnt() + 1, m_sorted_secondaries.size())
+ << dendl;
+ m_next_to_request++;
+ return false;
}
void ReplicaReservations::verify_rejections_source(
* the replica we are expecting a reply from) is noted, and triggers
* one of two: either sending a reservation request to the next replica,
* or notifying the scrubber that we have reserved them all.
+ *
+ * \returns true if there are no more replicas to send reservation requests
+ * (i.e., the scrubber should proceed to the next phase), false otherwise.
*/
- void handle_reserve_grant(OpRequestRef op, pg_shard_t from);
+ bool handle_reserve_grant(OpRequestRef op, pg_shard_t from);
/**
* Verify that the sender of the received rejection is the replica we
*/
void discard_remote_reservations();
+ /// the only replica we are expecting a reply from
+ std::optional<pg_shard_t> get_last_sent() const;
+
// note: 'public', as accessed via the 'standard' dout_prefix() macro
std::ostream& gen_prefix(std::ostream& out, std::string fn) const;
/// send 'release' messages to all replicas we have managed to reserve
void release_all();
- /// the only replica we are expecting a reply from
- std::optional<pg_shard_t> get_last_sent() const;
-
/// The number of requests that have been sent (and not rejected) so far.
size_t active_requests_cnt() const;
/**
- * Either send a reservation request to the next replica, or notify the
- * scrubber that we have reserved all the replicas.
+ * Send a reservation request to the next replica.
+ * - if there are no more replicas to send requests to, return true
*/
- void send_next_reservation_or_complete();
+ bool send_next_reservation_or_complete();
};
} // namespace Scrub
*/
virtual void clear_pgscrub_state() = 0;
- /**
- * triggers the 'RemotesReserved' (all replicas granted scrub resources)
- * state-machine event
- */
- virtual void send_remotes_reserved(epoch_t epoch_queued) = 0;
-
virtual void cleanup_store(ObjectStore::Transaction* t) = 0;
virtual bool get_store_errors(const scrub_ls_arg_t& arg,