* If msg->scrub_from is not set, replica_scrub calls build_scrubmap to
* build a complete map (with the pg lock dropped).
*
- * If msg->scrub_from is set, we build an incremental scrub map with
- * the pg lock held.
+ * If msg->scrub_from is set, replica_scrub sets finalizing_scrub.
+ * Similarly to scrub, if last_update_applied is behind info.last_update
+ * replica_scrub returns to be requeued by sub_op_modify_applied.
+ * replica_scrub then builds an incremental scrub map with the
+ * pg lock held.
*/
void PG::replica_scrub(MOSDRepScrub *msg)
{
+ assert(!active_rep_scrub);
dout(7) << "replica_scrub" << dendl;
if (msg->map_epoch < info.history.same_interval_since) {
ScrubMap map;
if (msg->scrub_from > eversion_t()) {
- // flush out in-flight writes to disk, so we can scrub the
- // resulting on-disk state.
- osr.flush();
+ if (finalizing_scrub) {
+ assert(last_update_applied == info.last_update);
+ } else {
+ finalizing_scrub = 1;
+ if (last_update_applied != info.last_update) {
+ active_rep_scrub = msg;
+ return;
+ }
+ }
build_inc_scrub_map(map, msg->scrub_from);
+ finalizing_scrub = 0;
} else {
build_scrub_map(map);
}
int scrub_waiting_on;
epoch_t scrub_epoch_start;
ScrubMap primary_scrubmap;
+ MOSDRepScrub *active_rep_scrub;
void repair_object(const hobject_t& soid, ScrubMap::object *po, int bad_peer, int ok_peer);
bool _compare_scrub_objects(ScrubMap::object &auth,
finish_sync_event(NULL),
finalizing_scrub(false),
scrub_reserved(false), scrub_reserve_failed(false),
- scrub_waiting_on(0)
+ scrub_waiting_on(0),
+ active_rep_scrub(0)
{
pool->get();
}
bool done = rm->applied && rm->committed;
last_update_applied = rm->op->version;
+ if (last_update_applied == info.last_update && finalizing_scrub) {
+ assert(active_rep_scrub);
+ osd->rep_scrub_wq.queue(active_rep_scrub);
+ active_rep_scrub->put();
+ active_rep_scrub = 0;
+ }
unlock();
if (done) {