diff --git a/src/osd.cpp b/src/osd.cpp index e6c7bfab..54e69941 100644 --- a/src/osd.cpp +++ b/src/osd.cpp @@ -210,6 +210,7 @@ void osd_t::parse_config(bool init) inode_vanish_time = config["inode_vanish_time"].uint64_value(); if (!inode_vanish_time) inode_vanish_time = 60; + auto old_auto_scrub = auto_scrub; auto_scrub = json_is_true(config["auto_scrub"]); global_scrub_interval = parse_time(config["scrub_interval"].string_value()); if (!global_scrub_interval) @@ -224,6 +225,14 @@ void osd_t::parse_config(bool init) scrub_list_limit = config["scrub_list_limit"].uint64_value(); if (!scrub_list_limit) scrub_list_limit = 1000; + if (!old_auto_scrub && auto_scrub) + { + // Schedule scrubbing + for (auto & pgp: pgs) + { + plan_scrub(pgp.second); + } + } if (old_no_scrub && !no_scrub) { // Wakeup scrubbing diff --git a/src/osd.h b/src/osd.h index 23f9f5e0..5f22cf71 100644 --- a/src/osd.h +++ b/src/osd.h @@ -243,6 +243,7 @@ class osd_t int pick_next_scrub(object_id & next_oid); void submit_scrub_op(object_id oid); bool continue_scrub(); + void plan_scrub(pg_t & pg, bool report_state = true); void schedule_scrub(pg_t & pg); // op execution diff --git a/src/osd_peering.cpp b/src/osd_peering.cpp index 05f9b7b8..27f9243d 100644 --- a/src/osd_peering.cpp +++ b/src/osd_peering.cpp @@ -24,8 +24,8 @@ void osd_t::handle_peers() if (!p.second.peering_state->list_ops.size()) { p.second.calc_object_states(log_level); - schedule_scrub(p.second); report_pg_state(p.second); + schedule_scrub(p.second); incomplete_objects += p.second.incomplete_objects.size(); misplaced_objects += p.second.misplaced_objects.size(); // FIXME: degraded objects may currently include misplaced, too! Report them separately? @@ -494,6 +494,7 @@ void osd_t::report_pg_state(pg_t & pg) pg.all_peers = pg.target_set; std::sort(pg.all_peers.begin(), pg.all_peers.end()); pg.cur_peers = pg.target_set; + plan_scrub(pg, false); // Change pg_config at the same time, otherwise our PG reconciling loop may try to apply the old metadata auto & pg_cfg = st_cli.pool_config[pg.pool_id].pg_config[pg.pg_num]; pg_cfg.target_history = pg.target_history; @@ -537,6 +538,7 @@ void osd_t::report_pg_state(pg_t & pg) pg.cur_peers.push_back(pg_osd); } } + plan_scrub(pg, false); auto & pg_cfg = st_cli.pool_config[pg.pool_id].pg_config[pg.pg_num]; pg_cfg.target_history = pg.target_history; pg_cfg.all_peers = pg.all_peers; diff --git a/src/osd_scrub.cpp b/src/osd_scrub.cpp index 33932de7..ac99feba 100644 --- a/src/osd_scrub.cpp +++ b/src/osd_scrub.cpp @@ -192,13 +192,10 @@ int osd_t::pick_next_scrub(object_id & next_oid) if (pg_it->second.state & PG_SCRUBBING) { scrub_last_pg = {}; - auto & pool_cfg = st_cli.pool_config.at(pg_it->first.pool_id); - auto interval = pool_cfg.scrub_interval ? pool_cfg.scrub_interval : global_scrub_interval; - pg_it->second.next_scrub = auto_scrub ? tv_now.tv_sec + interval : 0; pg_it->second.state = pg_it->second.state & ~PG_SCRUBBING; + pg_it->second.next_scrub = 0; pg_it->second.history_changed = true; report_pg_state(pg_it->second); - schedule_scrub(pg_it->second); } // The list is definitely not needed anymore if (scrub_cur_list.buf) @@ -318,6 +315,25 @@ bool osd_t::continue_scrub() return true; } +void osd_t::plan_scrub(pg_t & pg, bool report_state) +{ + if ((pg.state & PG_ACTIVE) && !pg.next_scrub && auto_scrub) + { + timespec tv_now; + clock_gettime(CLOCK_REALTIME, &tv_now); + auto & pool_cfg = st_cli.pool_config.at(pg.pool_id); + auto interval = pool_cfg.scrub_interval ? pool_cfg.scrub_interval : global_scrub_interval; + if (pg.next_scrub != tv_now.tv_sec + interval) + { + pool_cfg.pg_config[pg.pg_num].next_scrub = pg.next_scrub = tv_now.tv_sec + interval; + pg.history_changed = true; + if (report_state) + report_pg_state(pg); + } + schedule_scrub(pg); + } +} + void osd_t::schedule_scrub(pg_t & pg) { if (!no_scrub && pg.next_scrub && (!scrub_nearest_ts || scrub_nearest_ts > pg.next_scrub))