Skip to content

core: Extracting scrub-related code from the PG & friends - w.i.p#37317

Closed
ronen-fr wants to merge 17 commits intoceph:masterfrom
ronen-fr:scrub4
Closed

core: Extracting scrub-related code from the PG & friends - w.i.p#37317
ronen-fr wants to merge 17 commits intoceph:masterfrom
ronen-fr:scrub4

Conversation

@ronen-fr
Copy link
Contributor

@ronen-fr ronen-fr commented Sep 22, 2020

DNM as:

  • contains too many extra log messages and debugging aids

Objectives:

- identify and extract scrub code, as a first step into sharing scrub code between classic
  and Crimson implementations;
- refactor the code as needed for clarity;

Main changes:

- PgScrubber (pg_scrubber.{h,cc}) implements the scrub code that resided in PG.cc. And:

- PrimaryLogScrub.{h,cc} now implement the parts of the scrub code that resided in PrimaryLogPG.
  (note that I didn't see much point in the separation, but changing that was outside the scope of this PR)

- The flags that govern scrub scheduling/operation were separated into two structures: one is maintained
  by the PG, and details the "next scrub" parameters. The other is PgScrubber-owned, and determines the
  operation options for the running scrub. This collection of flags is set (and is "frozen") at
  PG:queue_scrub(), following the logic of the existing code.

- the scrubbing is now implemented as an explicit state-machine.
- and the events that trigger state changes are now translated into separate specific messages, that
  are initiated using specific calls;
- the priorities used when queueing and handling those events were reworked, trying to match the original
  semantics.

- Scrub-related resources (the OSD-owned 'local' and 'remote' scrub resources) are managed using RAII
  wrappers, hopefully guaranteeing no leakage.

Design decisions:

- the new scrub FSM (in scrub_machine.*) does not contain PG-specific code. All code that requires knowledge
  of the PG internals (or PrimaryLogPG internals) is in PgScrubber & PrimaryLogScrub. That, to achieve:
  - easy switching from (the slow) boost::state_chart to something better (I promised the SML author to give
    it a second try, after he has incorporated some needed changes);
  - ease of adaptation to Crimson;
  - clearer separation of concerns.

@athanatos
Copy link
Contributor

I think this approach in general should be viable. @dzafman should probably take a look.

@athanatos
Copy link
Contributor

This would be greatly easier to review if perhaps you could sequence the commits so that there's a single commit that moves the main logic into pg_scrubber* prior to re-factoring the state machine. I understand if you don't want to take the effort to do that, however.

@ronen-fr
Copy link
Contributor Author

"This would be greatly easier to review if perhaps you could sequence the commits so that there's a single commit that moves the main logic into pg_scrubber* prior to re-factoring the state machine. I understand if you don't want to take the effort to do that, however."

I will try to improve on that in the rebased version (which I plan to do line-by-line).

@ronen-fr
Copy link
Contributor Author

jenkins retest this please

@ronen-fr
Copy link
Contributor Author

ronen-fr commented Oct 1, 2020

jenkins retest this please

unrelated issues in the makecheck. All but one test OK on the 1st round. Strane results on the 2nd.
On the 3rd:

100% tests passed, 0 tests failed out of 207
Total Test time (real) = 1048.75 sec

  • sleep 5
  • grep ceph
  • ps -ef
  • grep -v jnlp
    jenkins+ 30648 1859 0 06:08 ? 00:00:00 grep ceph
    Recording test results
    ERROR: Step ?Publish JUnit test result report? aborted due to exception:
    java.lang.OutOfMemoryError: Java heap space

@neha-ojha
Copy link
Member

rados run: https://pulpito.ceph.com/nojha-2020-09-30_21:58:00-rados-wip-37317-distro-basic-smithi/

@ronen-fr The following failures look related:

2020-10-01T03:46:29.719+0000 7fbf604d2700 -1 *** Caught signal (Segmentation fault) **
 in thread 7fbf604d2700 thread_name:tp_osd_tp

 ceph version 16.0.0-6074-g20fb6e3a (20fb6e3af4910aba8d6fc8d07056a1054f96ccf0) pacific (dev)
 1: ()
 2: ()
 3: (std::pair<std::_Rb_tree_iterator<std::pair<Context* const, std::_Rb_tree_iterator<std::pair<std::chrono::time_point<ceph::real_clock, std::chrono::duration<unsigned long, std::ratio<1l, 1000000000l> > > const, Context*> > > >, bool> std::_Rb_tree<Context*, std::pair<Context* const, std::_Rb_tree_iterator<std::pair<std::chrono::time_point<ceph::real_clock, std::chrono::duration<unsigned long, std::ratio<1l, 1000000000l> > > const, Context*> > >, std::_Select1st<std::pair<Context* const, std::_Rb_tree_iterator<std::pair<std::chrono::time_point<ceph::real_clock, std::chrono::duration<unsigned long, std::ratio<1l, 1000000000l> > > const, Context*> > > >, std::less<Context*>, std::allocator<std::pair<Context* const, std::_Rb_tree_iterator<std::pair<std::chrono::time_point<ceph::real_clock, std::chrono::duration<unsigned long, std::ratio<1l, 1000000000l> > > const, Context*> > > > >::_M_emplace_unique<std::pair<Context* const, std::_Rb_tree_iterator<std::pair<std::chrono::time_point<ceph::real_clock, std::chrono::duration<unsigned long, std::ratio<1l, 1000000000l> > > const, Context*> > >&>(std::pair<Context* const, std::_Rb_tree_iterator<std::pair<std::chrono::time_point<ceph::real_clock, std::chrono::duration<unsigned long, std::ratio<1l, 1000000000l> > > const, Context*> > >&)+0xb7) [0x55e9f847ee07]
 4: (SafeTimer::add_event_at(std::chrono::time_point<ceph::real_clock, std::chrono::duration<unsigned long, std::ratio<1l, 1000000000l> > >, Context*)+0x2cc) [0x55e9f847d2dc]
 5: (SafeTimer::add_event_after(double, Context*)+0x72) [0x55e9f847d6a2]
 6: (PgScrubber::add_delayed_scheduling()+0x25c) [0x55e9f814c15c]
 7: (Scrub::PendingTimer::PendingTimer(boost::statechart::state<Scrub::PendingTimer, Scrub::ActiveScrubbing, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::my_context)+0xfc) [0x55e9f8167e2c]
 8: (boost::statechart::state<Scrub::PendingTimer, Scrub::ActiveScrubbing, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::deep_construct(boost::intrusive_ptr<Scrub::ActiveScrubbing> const&, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>&)+0x5b) [0x55e9f817504b]
 9: (Scrub::WaitDigestUpdate::react(Scrub::DigestUpdate const&)+0xf4) [0x55e9f816e634]
 10: (boost::statechart::simple_state<Scrub::WaitDigestUpdate, Scrub::ActiveScrubbing, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::react_impl(boost::statechart::event_base const&, void const*)+0x9a) [0x55e9f817700a]
 11: (boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>::process_event(boost::statechart::event_base const&)+0x284) [0x55e9f81657b4]
 12: (PgScrubber::send_replica_maps_ready()+0x2ea) [0x55e9f8148a2a]
 13: (PG::scrub_send_replmaps_ready(unsigned int, ThreadPool::TPHandle&)+0x3f) [0x55e9f7ea646f]
 14: (ceph::osd::scheduler::PGScrubGotReplMaps::run(OSD*, OSDShard*, boost::intrusive_ptr<PG>&, ThreadPool::TPHandle&)+0x16) [0x55e9f804cc96]
 15: (OSD::ShardedOpWQ::_process(unsigned int, ceph::heartbeat_handle_d*)+0x12ef) [0x55e9f7e127df]
 16: (ShardedThreadPool::shardedthreadpool_worker(unsigned int)+0x5c4) [0x55e9f8484524]
 17: (ShardedThreadPool::WorkThreadSharded::entry()+0x14) [0x55e9f84871c4]
 18: ()
 19: clone()

Copy link
Contributor

@dzafman dzafman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have more reviewing to do, but I wanted to submit these comments.

src/osd/PG.cc Outdated
queue_scrub();
m_planned_scrub.must_deep_scrub = true;
m_planned_scrub.check_repair = true;
m_planned_scrub.must_scrub = true; // RRR added this line, as I don't see how the comment in PG::sched_scrub_initial() is true otherwise
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting must_scrub isn't required in the original code because queue_scrub() knows we are scrubbing, so it doesn't matter in that function if this is a scheduled scrub or user initiated scrub.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is why req_scrub is added, to remember whether original scrub was user requested. Also, the comment in sched_scrub_initial() is true at a higher level. Internally, it doesn't have to be so strict, but maybe it is ok to set it here as long as it is cleared. We don't want that flag on during scrubbing. We don't want to show MUST_SCRUB generally in the log, so it is cleared once scrub starts.

Copy link
Contributor Author

@ronen-fr ronen-fr Oct 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification.

(req_scrub wasn't there yet when I added the comment you ref'ed to.)

I have found the flags handling the hardest to follow, and made the following changes - mostly for structure & legibility - while following all the details of the existing implementation.

The flags are now divided into the following categories/structures:

(A) Flags managed by the PG to affect the next scrub parameters (and scheduling):

Grouped in PG.m_planned_scrub of type requested_scrub_t.

  • Primary only;
  • all next-scrub ((next commit push later today)) flags are cleared on PG::sched_scrub(), after affecting the running scrub flags (B below).
    Note that this is different from the existing implementation, though I think I maintained the existing behaviour.
    Specifically:
    • must_scrub: was cleared in the original code. A copy is now maintained in marked_must (see below).
    • need_auto, must_deep_scrub: cleared in the original code too;
    • must_repair: same. State is remembered in PG_STATE_REPAIR.
    • deep_scrub_on_error: copied to the running flags. That copy is only cleared at scrub_finish(), after initiating an auto deep-scrub.
    • check_repair: original behavior is maintained.
    • time_for_deep: TBD... I am verifying the code now...
    • auto_repair: state affects running scrub 'auto_repair' flag; also saved in PG_STATE_REPAIR. Clearing matches original code.
    • req_scrub - note that the new version uses m_planned_scrub.req_scrub for the role played by save_req_scrub:
      when scrub_finish() determines that a scrub_after_recovery is in order, it copies ('or'ing, actually) the current
      required flag (what was req_scrub when we started) back into the next-scrub's flag in m_planned_scrub.
  • note the detailed description of each flag, per my understanding of the code, in scrub_common.h;

(B) Flags used by the executing scrub. These are owned by the PgScrubber.

Grouped in PgScrubber.m_flags, of type scrub_flags_t.

  • used by both primary and replicas;
  • set in PgScrubber::set_op_parameters() (for a Primary), which is called from:
    • PG::sched_scrub() - and note that we never reach here again after the scrubbing starts; and
    • PG::queue_scrub_after_recovery()

and by PgScrubber::replica_scrub_op()

  • a new marked_must flag captures the state of must_scrub at start time, to affect the scrubber periodic sleeps before each NewChunk (note that I didn't see that being handled in the original code.
    Seems like it uses must_scrub that was already cleared in PG::sched_scrub()).
  • cleared when scrubbing finishes, in PgSCrubber::reset_internal_state().

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please note that req_scrub stands for requested scrub which is the same as marked_must. req_scrub was only set in limited cases where a new scrub would happen and we needed to keep track of whether the instigating scrub was user requested. If you set req_scrub early in the scrub process, you just need to be careful not to clear it in the cases where it is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently there are some differences in the ways req_scrub vs mark_scrub affect scrubbing behaviour. After discussing this with others - I will merge the two anyway.

@ronen-fr

This comment has been minimized.

@ronen-fr
Copy link
Contributor Author

ronen-fr commented Oct 7, 2020

jenkins retest this please

Copy link
Member

@jdurgin jdurgin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tried to answer some of the RRR questions. At a high level the split into different pieces makes sense. I'm not sure about the special handling of recovery_after_scrub - @dzafman probably has more context on that.

@ronen-fr
Copy link
Contributor Author

jenkins retest this please

(previous round, b4 the last commit, was OK. Last check round fails for what seem to be unrelated)

@ronen-fr ronen-fr requested a review from athanatos October 16, 2020 10:11
Copy link
Contributor

@athanatos athanatos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done a review pass on the first few files. If there are still outstanding questions you need help with, perhaps it would help to compile those in one place so that we can get them answered?

What

virtual void on_info_history_change() = 0;
/// Notify that a scrub has been requested
virtual void scrub_requested(bool deep, bool repair, bool need_auto = false) = 0;
virtual void scrub_requested(scrub_level_t is_deep, scrub_type_t is_repair) = 0;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

param names, see prior

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. But like I said - I don't really like the result re the 'is_repair'. Looking for a better name.

<< "," << scrubber.end << ")" << dendl;
}
}
m_scrubber->add_stats_if_lower(delta_stats, soid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add_stats_if_lower isn't particularly descriptive. How about notify_object_stats_changed(delta_stats, soid)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lower part is an implementation detail of the scrubber, it simply reflects that objects < scrubber.start are reflected in the compiled scrub stats.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't use 'notify', as no notification takes place. Added comments to the PrimaryLogScrub (copied from Josh's notes). And renaming to stats_of_handled_objects() (?)

@dzafman
Copy link
Contributor

dzafman commented Oct 27, 2020

These 2 subtests failed with the same assert.

qa/standalone/scrub/osd-scrub-test.sh TEST_deep_scrub_abort
qa/standalone/scrub/osd-scrub-dump.sh TEST_recover_unexpected

 -1015> 2020-10-26T20:19:30.693-0700 7f20f835e700 -1 /home/dzafman/ceph/src/common/Timer.cc: In function 'Context* SafeTimer::add_event_after(double, Context*)' thread 7f20f835e700 time 2020-10-26T20:19:30.636167-0700
/home/dzafman/ceph/src/common/Timer.cc: 120: FAILED ceph_assert(((lock).is_locked()))

 ceph version 16.0.0-5961-g874367c2edd (874367c2edd799b332b1b33cda51af056b705d21) pacific (dev)
 1: (ceph::__ceph_assert_fail(char const*, char const*, int, char const*)+0x19d) [0x557960279ebb]
 2: ()
 3: (SafeTimer::add_event_after(double, Context*)+0x44) [0x55796025da82]
 4: (PgScrubber::add_delayed_scheduling()+0x411) [0x55795fd8b653]
 5: (Scrub::PendingTimer::PendingTimer(boost::statechart::state<Scrub::PendingTimer, Scrub::ActiveScrubbing, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::my_context)+0x253) [0x55795fdb3f1f]
 6: (boost::statechart::state<Scrub::PendingTimer, Scrub::ActiveScrubbing, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::shallow_construct(boost::intrusive_ptr<Scrub::ActiveScrubbing> const&, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>&)+0x68) [0x55795fdc4dc4]
 7: (boost::statechart::state<Scrub::PendingTimer, Scrub::ActiveScrubbing, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::deep_construct(boost::intrusive_ptr<Scrub::ActiveScrubbing> const&, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>&)+0x37) [0x55795fdc3da2]
 8: (void boost::statechart::simple_state<Scrub::ActiveScrubbing, Scrub::ScrubMachine, Scrub::PendingTimer, (boost::statechart::history_mode)0>::deep_construct_inner_impl_non_empty::deep_construct_inner_impl<boost::mpl::list<Scrub::PendingTimer, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >(boost::intrusive_ptr<Scrub::ActiveScrubbing> const&, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>&)+0x23) [0x55795fdd1f20]
 9: (void boost::statechart::simple_state<Scrub::ActiveScrubbing, Scrub::ScrubMachine, Scrub::PendingTimer, (boost::statechart::history_mode)0>::deep_construct_inner<boost::mpl::list<Scrub::PendingTimer, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >(boost::intrusive_ptr<Scrub::ActiveScrubbing> const&, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>&)+0x23) [0x55795fdd1ad1]
 10: (boost::statechart::state<Scrub::ActiveScrubbing, Scrub::ScrubMachine, Scrub::PendingTimer, (boost::statechart::history_mode)0>::deep_construct(boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>* const&, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>&)+0x4a) [0x55795fdd1370]
 11: (boost::statechart::detail::inner_constructor<boost::mpl::l_item<mpl_::long_<1l>, Scrub::ActiveScrubbing, boost::mpl::l_end>, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator> >::construct(boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>* const&, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>&)+0x23) [0x55795fdd0d32]
 12: (boost::statechart::detail::safe_reaction_result boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::transit_impl<Scrub::ActiveScrubbing, Scrub::ScrubMachine, boost::statechart::detail::no_transition_function>(boost::statechart::detail::no_transition_function const&)+0x8f) [0x55795fdd059d]
 13: (boost::statechart::detail::safe_reaction_result boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::transit<Scrub::ActiveScrubbing>()+0x36) [0x55795fdcfd2a]
 14: (boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>::reactions<Scrub::ReservingReplicas>::react_without_action(Scrub::ReservingReplicas&)+0x32) [0x55795fdcf80f]
 15: (boost::statechart::detail::reaction_dispatcher<boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>::reactions<Scrub::ReservingReplicas>, Scrub::ReservingReplicas, boost::statechart::event_base, Scrub::RemotesReserved, boost::statechart::detail::no_context<Scrub::RemotesReserved>, void const*>::without_action::react(Scrub::ReservingReplicas&, boost::statechart::event_base const&)+0x36) [0x55795fdcef69]
 16: (boost::statechart::detail::reaction_dispatcher<boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>::reactions<Scrub::ReservingReplicas>, Scrub::ReservingReplicas, boost::statechart::event_base, Scrub::RemotesReserved, boost::statechart::detail::no_context<Scrub::RemotesReserved>, void const*>::derived::react(Scrub::ReservingReplicas&, boost::statechart::event_base const&, void const* const&)+0x55) [0x55795fdce93d]
 17: (boost::statechart::detail::reaction_dispatcher<boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>::reactions<Scrub::ReservingReplicas>, Scrub::ReservingReplicas, boost::statechart::event_base, Scrub::RemotesReserved, boost::statechart::detail::no_context<Scrub::RemotesReserved>, void const*>::react(Scrub::ReservingReplicas&, boost::statechart::event_base const&, void const* const&)+0x3c) [0x55795fdce202]
 18: (boost::statechart::detail::reaction_result boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>::react<Scrub::ReservingReplicas, boost::statechart::event_base, void const*>(Scrub::ReservingReplicas&, boost::statechart::event_base const&, void const* const&)+0x2b) [0x55795fdcdb66]
 19: (boost::statechart::detail::reaction_result boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::local_react_impl_non_empty::local_react_impl<boost::mpl::list3<boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>, boost::statechart::custom_reaction<Scrub::FullReset>, boost::statechart::custom_reaction<Scrub::ReservationFailure> >, boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0> >(boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>&, boost::statechart::event_base const&, void const*)+0x36) [0x55795fdcd3f0]
 20: (boost::statechart::detail::reaction_result boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::local_react<boost::mpl::list3<boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>, boost::statechart::custom_reaction<Scrub::FullReset>, boost::statechart::custom_reaction<Scrub::ReservationFailure> > >(boost::statechart::event_base const&, void const*)+0x2b) [0x55795fdcca17]
 21: (boost::statechart::detail::reaction_result boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::local_react_impl_non_empty::local_react_impl<boost::mpl::list<boost::statechart::custom_reaction<Scrub::EpochChanged>, boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>, boost::statechart::custom_reaction<Scrub::FullReset>, boost::statechart::custom_reaction<Scrub::ReservationFailure>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0> >(boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>&, boost::statechart::event_base const&, void const*)+0x56) [0x55795fdcbb10]
 22: (boost::statechart::detail::reaction_result boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::local_react<boost::mpl::list<boost::statechart::custom_reaction<Scrub::EpochChanged>, boost::statechart::transition<Scrub::RemotesReserved, Scrub::ActiveScrubbing, boost::statechart::detail::no_context<Scrub::RemotesReserved>, &boost::statechart::detail::no_context<Scrub::RemotesReserved>::no_function>, boost::statechart::custom_reaction<Scrub::FullReset>, boost::statechart::custom_reaction<Scrub::ReservationFailure>, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na> >(boost::statechart::event_base const&, void const*)+0x2b) [0x55795fdca657]
 23: (boost::statechart::simple_state<Scrub::ReservingReplicas, Scrub::ScrubMachine, boost::mpl::list<mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na>, (boost::statechart::history_mode)0>::react_impl(boost::statechart::event_base const&, void const*)+0x2b) [0x55795fdc8785]
 24: (boost::statechart::detail::send_function<boost::statechart::detail::state_base<std::allocator<boost::statechart::none>, boost::statechart::detail::rtti_policy>, boost::statechart::event_base, void const*>::operator()()+0x50) [0x55795f8d8c2e]
 25: (boost::statechart::detail::safe_reaction_result boost::statechart::null_exception_translator::operator()<boost::statechart::detail::send_function<boost::statechart::detail::state_base<std::allocator<boost::statechart::none>, boost::statechart::detail::rtti_policy>, boost::statechart::event_base, void const*>, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>::exception_event_handler>(boost::statechart::detail::send_function<boost::statechart::detail::state_base<std::allocator<boost::statechart::none>, boost::statechart::detail::rtti_policy>, boost::statechart::event_base, void const*>, boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>::exception_event_handler)+0x37) [0x55795fda88a7]
 26: (boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>::send_event(boost::statechart::event_base const&)+0x177) [0x55795fda5e7b]
 27: (boost::statechart::state_machine<Scrub::ScrubMachine, Scrub::NotActive, std::allocator<boost::statechart::none>, boost::statechart::null_exception_translator>::process_event(boost::statechart::event_base const&)+0x33) [0x55795fda3253]
 28: (PgScrubber::send_remotes_reserved()+0x160) [0x55795fd87774]
 29: (PG::scrub_send_resources_granted(unsigned int, ThreadPool::TPHandle&)+0x13a) [0x55795f89ca4e]
 30: (ceph::osd::scheduler::PGScrubResourcesOK::run(OSD*, OSDShard*, boost::intrusive_ptr<PG>&, ThreadPool::TPHandle&)+0x40) [0x55795fbd1b60]
 31: (ceph::osd::scheduler::OpSchedulerItem::run(OSD*, OSDShard*, boost::intrusive_ptr<PG>&, ThreadPool::TPHandle&)+0x4b) [0x55795f75e55f]
 32: (OSD::ShardedOpWQ::_process(unsigned int, ceph::heartbeat_handle_d*)+0x3632) [0x55795f73e500]
 33: (ShardedThreadPool::shardedthreadpool_worker(unsigned int)+0x58a) [0x5579602655ec]
 34: (ShardedThreadPool::WorkThreadSharded::entry()+0x25) [0x5579602671ff]
 35: (Thread::entry_wrapper()+0x83) [0x5579602514db]
 36: (Thread::_entry_func(void*)+0x18) [0x55796025144e]
 37: ()
 38: clone()

@ronen-fr
Copy link
Contributor Author

ronen-fr commented Oct 28, 2020

These 2 subtests failed with the same assert.

Thanks. Removed the lock by mistake.

@dzafman
Copy link
Contributor

dzafman commented Oct 29, 2020

The following test using b22a806060c3ffdffa4e085cb0eb75e749947e9e PASSED! I'll run all standalone tests now.

../qa/run-standalone.sh scrub
../qa/run-standalone.sh osd

Objectives:

- identify and extract scrub code, as a first step into sharing scrub code between classic
  and Crimson implementations;
- refactor the code as needed for clarity;

Main changes:

- PgScrubber (pg_scrubber.{h,cc}) implements the scrub code that resided in PG.cc. And:

- PrimaryLogScrub.{h,cc} now implement the parts of the scrub code that resided in PrimaryLogPG.
  (note that I didn't see much point in the separation, but changing that was outside the scope of this PR)

- The flags that govern scrub scheduling/operation were separated into two structures: one is maintained
  by the PG, and details the "next scrub" parameters. The other is PgScrubber-owned, and determines the
  operation options for the running scrub. This collection of flags is set (and is "frozen") at
  PG:queue_scrub(), following the logic of the existing code.

- the scrubbing is now implemented as an explicit state-machine.
- and the events that trigger state changes are now translated into separate specific messages, that
  are initiated using specific calls;
- the priorities used when queuing and handling those events were reworked, trying to match the original
  semantics.

Design decisions:

- the new scrub FSM (in scrub_machine.*) does not contain PG-specific code. All code that requires knowledge
  of the PG internals (or PrimaryLogPG internals) is in PgScrubber & PrimaryLogScrub. That, to achieve:
  - easy switching from (the slow) boost::state_chart to something better (I promised the SML author to give
    it a second try, after he has incorporated some needed changes);
  - ease of adaptation to Crimson;
  - clearer separation of concerns.

Not done yet:

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
a set of shards"

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
    Objectives:

    - identify and extract scrub code, as a first step into sharing scrub code between classic
      and Crimson implementations;
    - refactor the code as needed for clarity;

    Main changes:

    - PgScrubber (pg_scrubber.{h,cc}) implements the scrub code that resided in PG.cc. And:

    - PrimaryLogScrub.{h,cc} now implement the parts of the scrub code that resided in PrimaryLogPG.
      (note that I didn't see much point in the separation, but changing that was outside the scope of this PR)

    - The flags that govern scrub scheduling/operation were separated into two structures: one is maintained
      by the PG, and details the "next scrub" parameters. The other is PgScrubber-owned, and determines the
      operation options for the running scrub. This collection of flags is set (and is "frozen") at
      PG:queue_scrub(), following the logic of the existing code.

    - the scrubbing is now implemented as an explicit state-machine.
    - and the events that trigger state changes are now translated into separate specific messages, that
      are initiated using specific calls;
    - the priorities used when queueing and handling those events were reworked, trying to match the original
      semantics.

    - Scrub-related resources (the OSD-owned 'local' and 'remote' scrub resources) are managed using RAII
      wrappers, hopefully guaranteeing no leakage.

    Design decisions:

    - the new scrub FSM (in scrub_machine.*) does not contain PG-specific code. All code that requires knowledge
      of the PG internals (or PrimaryLogPG internals) is in PgScrubber & PrimaryLogScrub. That, to achieve:
      - easy switching from (the slow) boost::state_chart to something better (I promised the SML author to give
        it a second try, after he has incorporated some needed changes);
      - ease of adaptation to Crimson;
      - clearer separation of concerns.

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
- a bug related to the scrub/osd-scrub-dump test
- a bug related to the scrub/osd-scrub-repair test
- code review comments

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
object that manages the status of all maps.

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
    - static anal. warnings regarding state-chart post-event() of non-heap allocated events
    - some scrubbing state transitions, esp re error events
    - a temporary fix to osd-scrub-test.sh (the problem encountered is this:
      when testing 'deep-scrub abort', once the nodeepscrub conf is released - the
      OSD might immediately schedule the regular (non-deep) scrub on that PG.
      The test is not expecting that.

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
Clarifying the distinction between the two "scrub_requested()" flavours:
the "external" one, triggered by a command, vs the 'auto' request that
may be triggered at scrub termination (and which sets 'need_auto').
That one is internal to the PgScrubber object.

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
of scrub flags when scrubbing after recovery.


Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
- refactoring sched_scrub_initial() (now - verify_scrub_mode())
- cosmetics

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
Also - multiple minor changes following code-review comments.

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
…ions

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
…maps()

and
multiple minor logging/formatting changes

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
(and some minor formatting)

Signed-off-by: Ronen Friedman <rfriedma@redhat.com>
@jdurgin
Copy link
Member

jdurgin commented Dec 15, 2020

superseded by #38111

@jdurgin jdurgin closed this Dec 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants