#include "crush/CrushTester.h"
#include "crush/CrushTreeDumper.h"
+#include "messages/MOSDBeacon.h"
#include "messages/MOSDFailure.h"
#include "messages/MOSDMarkMeDown.h"
#include "messages/MOSDFull.h"
return preprocess_alive(op);
case MSG_OSD_PGTEMP:
return preprocess_pgtemp(op);
+ case MSG_OSD_BEACON:
+ return preprocess_beacon(op);
case CEPH_MSG_POOLOP:
return preprocess_pool_op(op);
return prepare_alive(op);
case MSG_OSD_PGTEMP:
return prepare_pgtemp(op);
+ case MSG_OSD_BEACON:
+ return prepare_beacon(op);
case MSG_MON_COMMAND:
return prepare_command(op);
case MSG_REMOVE_SNAPS:
return prepare_remove_snaps(op);
+
default:
ceph_abort();
}
return true;
}
+// osd beacon
+bool OSDMonitor::preprocess_beacon(MonOpRequestRef op)
+{
+ op->mark_osdmon_event(__func__);
+ auto beacon = static_cast<MOSDBeacon*>(op->get_req());
+ // check caps
+ auto session = beacon->get_session();
+ if (!session) {
+ dout(10) << __func__ << " no monitor session!" << dendl;
+ return true;
+ }
+ if (!session->is_capable("osd", MON_CAP_X)) {
+ derr << __func__ << " received from entity "
+ << "with insufficient privileges " << session->caps << dendl;
+ return true;
+ }
+ // Always forward the beacon to the leader, even if they are the same as
+ // the old one. The leader will mark as down osds that haven't sent
+ // beacon for a few minutes.
+ return false;
+}
+
+bool OSDMonitor::prepare_beacon(MonOpRequestRef op)
+{
+ op->mark_osdmon_event(__func__);
+ const auto beacon = static_cast<MOSDBeacon*>(op->get_req());
+ const auto src = beacon->get_orig_source();
+ dout(10) << __func__ << " " << *beacon
+ << " from " << src << dendl;
+ int from = src.num();
+
+ if (!src.is_osd() ||
+ !osdmap.is_up(from) ||
+ beacon->get_orig_source_inst() != osdmap.get_inst(from)) {
+ dout(1) << " ignoring beacon from non-active osd." << dendl;
+ return false;
+ }
+
+ last_osd_report[from] = ceph_clock_now();
+ return false;
+}
// ---------------
// map helpers
bool do_propose = false;
utime_t now = ceph_clock_now();
+ if (handle_osd_timeouts(now, last_osd_report))
+ do_propose = true;
+
// mark osds down?
if (check_failures(now))
do_propose = true;
propose_pending();
}
-void OSDMonitor::handle_osd_timeouts(const utime_t &now,
+bool OSDMonitor::handle_osd_timeouts(const utime_t &now,
std::map<int,utime_t> &last_osd_report)
{
utime_t timeo(g_conf->mon_osd_report_timeout, 0);
+ if (now - mon->get_leader_since() < timeo) {
+ // We haven't been the leader for long enough to consider OSD timeouts
+ return false;
+ }
+
int max_osd = osdmap.get_max_osd();
bool new_down = false;
for (int i=0; i < max_osd; ++i) {
- dout(30) << "handle_osd_timeouts: checking up on osd " << i << dendl;
+ dout(30) << __func__ << ": checking up on osd " << i << dendl;
if (!osdmap.is_up(i))
continue;
const std::map<int,utime_t>::const_iterator t = last_osd_report.find(i);
}
}
}
- if (new_down) {
- propose_pending();
- }
+ return new_down;
}
void OSDMonitor::get_health(list<pair<health_status_t,string> >& summary,
int load_metadata(int osd, map<string, string>& m, ostream *err);
- public:
+ // when we last received PG stats from each osd
+ map<int,utime_t> last_osd_report;
+ bool preprocess_beacon(MonOpRequestRef op);
+ bool prepare_beacon(MonOpRequestRef op);
+
+public:
OSDMonitor(CephContext *cct, Monitor *mn, Paxos *p, const string& service_name);
void tick() override; // check state, take actions
int prepare_command_pool_set(map<string,cmd_vartype> &cmdmap,
stringstream& ss);
- void handle_osd_timeouts(const utime_t &now,
+ bool handle_osd_timeouts(const utime_t &now,
std::map<int,utime_t> &last_osd_report);
void send_latest(MonOpRequestRef op, epoch_t start=0);