void OSD::tick_without_osd_lock()
{
  assert(tick_timer_lock.is_locked());
  dout(10) << "tick_without_osd_lock" << dendl;

  logger->set(l_osd_buf, buffer::get_total_alloc());
  logger->set(l_osd_history_alloc_bytes, SHIFT_ROUND_UP(buffer::get_history_alloc_bytes(), 20));
  logger->set(l_osd_history_alloc_num, buffer::get_history_alloc_num());
  logger->set(l_osd_cached_crc, buffer::get_cached_crc());
  logger->set(l_osd_cached_crc_adjusted, buffer::get_cached_crc_adjusted());
  logger->set(l_osd_missed_crc, buffer::get_missed_crc());
  logger->set(l_osd_pg_removing, remove_wq.get_remove_queue_len());

  // osd_lock is not being held, which means the OSD state
  // might change when doing the monitor report
  if (is_active() || is_waiting_for_healthy()) {
    heartbeat_lock.Lock();
    heartbeat_check();
    heartbeat_lock.Unlock();

    map_lock.get_read();
    Mutex::Locker l(mon_report_lock);

    // mon report?
    bool reset = false;
    bool report = false;
    utime_t now = ceph_clock_now();
    pg_stat_queue_lock.Lock();
    double backoff = stats_ack_timeout / cct->_conf->osd_mon_ack_timeout;
    double adjusted_min = cct->_conf->osd_mon_report_interval_min * backoff;
    // note: we shouldn't adjust max because it must remain < the
    // mon's mon_osd_report_timeout (which defaults to 1.5x our
    // value).
    double max = cct->_conf->osd_mon_report_interval_max;
    if (!outstanding_pg_stats.empty() &&
	(now - stats_ack_timeout) > last_pg_stats_ack) {
      dout(1) << __func__ << " mon hasn't acked PGStats in "
	      << now - last_pg_stats_ack
	      << " seconds, reconnecting elsewhere" << dendl;
      reset = true;
      last_pg_stats_ack = now;  // reset clock
      last_pg_stats_sent = utime_t();
      stats_ack_timeout =
	MAX(cct->_conf->osd_mon_ack_timeout,
	    stats_ack_timeout * cct->_conf->osd_stats_ack_timeout_factor);
      outstanding_pg_stats.clear();
    }
    if (now - last_pg_stats_sent > max) {
      osd_stat_updated = true;
      report = true;
    } else if (service.need_fullness_update()) {
      report = true;
    } else if ((int)outstanding_pg_stats.size() >=
	       cct->_conf->osd_mon_report_max_in_flight) {
      dout(20) << __func__ << " have max " << outstanding_pg_stats
	       << " stats updates in flight" << dendl;
    } else {
      if (now - last_mon_report > adjusted_min) {
	dout(20) << __func__ << " stats backoff " << backoff
		 << " adjusted_min " << adjusted_min << " - sending report"
		 << dendl;
        osd_stat_updated = true;
	report = true;
      }
    }
    pg_stat_queue_lock.Unlock();

    if (reset) {
      monc->reopen_session();
    } else if (report) {
      last_mon_report = now;

      // do any pending reports
      send_full_update();
      send_failures();
      if (osdmap->require_osd_release < CEPH_RELEASE_LUMINOUS) {
	send_pg_stats(now);
      }
    }
    map_lock.put_read();
  }

  if (is_active()) {
    if (!scrub_random_backoff()) {
      sched_scrub();
    }
    service.promote_throttle_recalibrate();
    resume_creating_pg();
    bool need_send_beacon = false;
    const auto now = ceph::coarse_mono_clock::now();
    {
      // borrow lec lock to pretect last_sent_beacon from changing
      Mutex::Locker l{min_last_epoch_clean_lock};
      const auto elapsed = now - last_sent_beacon;
      if (chrono::duration_cast<chrono::seconds>(elapsed).count() >
        cct->_conf->osd_beacon_report_interval) {
        need_send_beacon = true;
      }
    }
    if (need_send_beacon) {
      send_beacon(now);
    }
  }

  mgrc.update_osd_health(get_health_metrics());
  service.kick_recovery_queue();
  tick_timer_without_osd_lock.add_event_after(OSD_TICK_INTERVAL, new C_Tick_WithoutOSDLock(this));
}