namespace Scrub {
class Store;
class ReplicaReservations;
- class LocalReservation;
class ReservedByRemotePrimary;
enum class schedule_result_t;
}
m_queue.remove_from_osd_queue(sjob);
}
-bool OsdScrub::inc_scrubs_local()
+std::unique_ptr<Scrub::LocalResourceWrapper> OsdScrub::inc_scrubs_local(
+ bool is_high_priority)
{
- return m_resource_bookkeeper.inc_scrubs_local();
+ return m_resource_bookkeeper.inc_scrubs_local(is_high_priority);
}
void OsdScrub::dec_scrubs_local()
// ---------------------------------------------------------------
// updating the resource counters
- bool inc_scrubs_local();
+ std::unique_ptr<Scrub::LocalResourceWrapper> inc_scrubs_local(
+ bool is_high_priority);
void dec_scrubs_local();
bool inc_scrubs_remote(pg_t pgid);
void dec_scrubs_remote(pg_t pgid);
bool PgScrubber::reserve_local()
{
// try to create the reservation object (which translates into asking the
- // OSD for the local scrub resource). If failing - undo it immediately
-
- m_local_osd_resource.emplace(m_osds);
- if (m_local_osd_resource->is_reserved()) {
+ // OSD for a local scrub resource). The object returned is a
+ // a wrapper around the actual reservation, and that object releases
+ // the local resource automatically when reset.
+ m_local_osd_resource = m_osds->get_scrub_services().inc_scrubs_local(
+ m_scrub_job->is_high_priority());
+ if (m_local_osd_resource) {
dout(15) << __func__ << ": local resources reserved" << dendl;
return true;
}
- dout(10) << __func__ << ": failed to reserve local scrub resources" << dendl;
- m_local_osd_resource.reset();
+ dout(15) << __func__ << ": failed to reserve local scrub resources" << dendl;
return false;
}
m_size_divisor = 1;
}
-
-// ///////////////////// LocalReservation //////////////////////////////////
-
namespace Scrub {
-// note: no dout()s in LocalReservation functions. Client logs interactions.
-LocalReservation::LocalReservation(OSDService* osds) : m_osds{osds}
-{
- if (m_osds->get_scrub_services().inc_scrubs_local()) {
- // a failure is signalled by not having m_holding_local_reservation set
- m_holding_local_reservation = true;
- }
-}
-
-LocalReservation::~LocalReservation()
-{
- if (m_holding_local_reservation) {
- m_holding_local_reservation = false;
- m_osds->get_scrub_services().dec_scrubs_local();
- }
-}
-
// ///////////////////// MapsCollectionStatus ////////////////////////////////
auto MapsCollectionStatus::mark_arriving_map(pg_shard_t from)
namespace Scrub {
class ScrubMachine;
struct BuildMap;
+class LocalResourceWrapper;
-/**
- * wraps the local OSD scrub resource reservation in an RAII wrapper
- */
-class LocalReservation {
- OSDService* m_osds;
- bool m_holding_local_reservation{false};
-
- public:
- explicit LocalReservation(OSDService* osds);
- ~LocalReservation();
- bool is_reserved() const { return m_holding_local_reservation; }
-};
-
/**
* Once all replicas' scrub maps are received, we go on to compare the maps.
* That is - unless we we have not yet completed building our own scrub map.
epoch_t m_last_aborted{}; // last time we've noticed a request to abort
- // 'optional', as 'LocalReservation' is
- // 'RAII-designed' to guarantee un-reserving when deleted.
- std::optional<Scrub::LocalReservation> m_local_osd_resource;
+ /**
+ * once we acquire the local OSD resource, this is set to a wrapper that
+ * guarantees that the resource will be released when the scrub is done
+ */
+ std::unique_ptr<Scrub::LocalResourceWrapper> m_local_osd_resource;
void cleanup_on_finish(); // scrub_clear_state() as called for a Primary when
// Active->NotActive
using ScrubResources = Scrub::ScrubResources;
+using LocalResourceWrapper = Scrub::LocalResourceWrapper;
ScrubResources::ScrubResources(
log_upwards_t log_access,
return can_inc_local_scrubs_unlocked();
}
-bool ScrubResources::inc_scrubs_local()
+std::unique_ptr<LocalResourceWrapper> ScrubResources::inc_scrubs_local(
+ bool is_high_priority)
{
std::lock_guard lck{resource_lock};
- if (can_inc_local_scrubs_unlocked()) {
+ if (is_high_priority || can_inc_local_scrubs_unlocked()) {
++scrubs_local;
log_upwards(fmt::format(
"{}: {} -> {} (max {}, remote {})", __func__, (scrubs_local - 1),
scrubs_local, conf->osd_max_scrubs, granted_reservations.size()));
- return true;
+ return std::make_unique<LocalResourceWrapper>(*this);
}
- return false;
+ return nullptr;
}
bool ScrubResources::can_inc_local_scrubs_unlocked() const
f->dump_string("PGs being served", fmt::format("{}", granted_reservations));
f->dump_int("osd_max_scrubs", conf->osd_max_scrubs);
}
+
+// --------------- LocalResourceWrapper
+
+Scrub::LocalResourceWrapper::LocalResourceWrapper(
+ ScrubResources& resource_bookkeeper)
+ : m_resource_bookkeeper{resource_bookkeeper}
+{}
+
+Scrub::LocalResourceWrapper::~LocalResourceWrapper()
+{
+ m_resource_bookkeeper.dec_scrubs_local();
+}
+
* (prefix func, OSD id, etc.)
*/
using log_upwards_t = std::function<void(std::string msg)>;
+class LocalResourceWrapper;
/**
* The number of concurrent scrub operations performed on an OSD is limited
* acting as primary and acting as a replica, and for enforcing the limit.
*/
class ScrubResources {
- /// the number of concurrent scrubs performed by Primaries on this OSD
+ friend class LocalResourceWrapper;
+
+ /**
+ * the number of concurrent scrubs performed by Primaries on this OSD.
+ *
+ * Note that, as high priority scrubs are always allowed to proceed, this
+ * counter may exceed the configured limit. When in this state - no new
+ * regular scrubs will be allowed to start.
+ */
int scrubs_local{0};
/// the set of PGs that have active scrub reservations as replicas
bool can_inc_scrubs() const;
/// increments the number of scrubs acting as a Primary
- bool inc_scrubs_local();
+ std::unique_ptr<LocalResourceWrapper> inc_scrubs_local(bool is_high_priority);
/// decrements the number of scrubs acting as a Primary
void dec_scrubs_local();
void dump_scrub_reservations(ceph::Formatter* f) const;
};
+
+
+/**
+ * a wrapper around a "local scrub resource". The resources bookkeeper
+ * is handing these out to the PGs that acquired the local OSD's scrub
+ * resources. The PGs use these to release the resources when they are
+ * done scrubbing.
+ */
+class LocalResourceWrapper {
+ ScrubResources& m_resource_bookkeeper;
+
+ public:
+ LocalResourceWrapper(
+ ScrubResources& resource_bookkeeper);
+ ~LocalResourceWrapper();
+};
+
} // namespace Scrub