--- /dev/null
+// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
+// vim: ts=8 sw=2 smarttab
+/*
+ * Ceph - scalable distributed file system
+ *
+ * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
+ *
+ * This is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software
+ * Foundation. See file COPYING.
+ *
+ */
+
+#ifndef CEPH_MOSDSCRUBRESERVE_H
+#define CEPH_MOSDSCRUBRESERVE_H
+
+#include "MOSDFastDispatchOp.h"
+
+class MOSDScrubReserve : public MOSDFastDispatchOp {
+ static const int HEAD_VERSION = 1;
+ static const int COMPAT_VERSION = 1;
+public:
+ spg_t pgid;
+ epoch_t map_epoch;
+ enum {
+ REQUEST = 0,
+ GRANT = 1,
+ RELEASE = 2,
+ REJECT = 3,
+ };
+ int32_t type;
+ pg_shard_t from;
+
+ epoch_t get_map_epoch() const override {
+ return map_epoch;
+ }
+ spg_t get_spg() const override {
+ return pgid;
+ }
+
+ MOSDScrubReserve()
+ : MOSDFastDispatchOp(MSG_OSD_SCRUB_RESERVE, HEAD_VERSION, COMPAT_VERSION),
+ map_epoch(0), type(-1) {}
+ MOSDScrubReserve(spg_t pgid,
+ epoch_t map_epoch,
+ int type,
+ pg_shard_t from)
+ : MOSDFastDispatchOp(MSG_OSD_SCRUB_RESERVE, HEAD_VERSION, COMPAT_VERSION),
+ pgid(pgid), map_epoch(map_epoch),
+ type(type), from(from) {}
+
+ const char *get_type_name() const {
+ return "MOSDScrubReserve";
+ }
+
+ void print(ostream& out) const {
+ out << "MOSDScrubReserve(" << pgid << " ";
+ switch (type) {
+ case REQUEST:
+ out << "REQUEST ";
+ break;
+ case GRANT:
+ out << "GRANT ";
+ break;
+ case REJECT:
+ out << "REJECT ";
+ break;
+ case RELEASE:
+ out << "RELEASE ";
+ break;
+ }
+ out << "e" << map_epoch << ")";
+ return;
+ }
+
+ void decode_payload() {
+ bufferlist::iterator p = payload.begin();
+ ::decode(pgid, p);
+ ::decode(map_epoch, p);
+ ::decode(type, p);
+ ::decode(from, p);
+ }
+
+ void encode_payload(uint64_t features) {
+ ::encode(pgid, payload);
+ ::encode(map_epoch, payload);
+ ::encode(type, payload);
+ ::encode(from, payload);
+ }
+};
+
+#endif
#include "messages/MOSDPGUpdateLogMissing.h"
#include "messages/MOSDPGUpdateLogMissingReply.h"
#include "messages/MOSDBackoff.h"
-
+#include "messages/MOSDScrubReserve.h"
#include "messages/MOSDSubOp.h"
#include "messages/MOSDRepOp.h"
#include "messages/MOSDSubOpReply.h"
replica.osd, repscrubop, get_osdmap()->get_epoch());
}
-void PG::sub_op_scrub_reserve(OpRequestRef op)
+void PG::handle_scrub_reserve_request(OpRequestRef op)
{
- const MOSDSubOp *m = static_cast<const MOSDSubOp*>(op->get_req());
- assert(m->get_type() == MSG_OSD_SUBOP);
- dout(7) << "sub_op_scrub_reserve" << dendl;
-
+ dout(7) << __func__ << " " << *op->get_req() << dendl;
+ op->mark_started();
if (scrubber.reserved) {
- dout(10) << "Ignoring reserve request: Already reserved" << dendl;
+ dout(10) << __func__ << " ignoring reserve request: Already reserved"
+ << dendl;
return;
}
-
- op->mark_started();
-
scrubber.reserved = osd->inc_scrubs_pending();
-
- MOSDSubOpReply *reply = new MOSDSubOpReply(
- m, pg_whoami, 0, get_osdmap()->get_epoch(), CEPH_OSD_FLAG_ACK);
- ::encode(scrubber.reserved, reply->get_data());
- osd->send_message_osd_cluster(reply, m->get_connection());
+ if (op->get_req()->get_type() == MSG_OSD_SCRUB_RESERVE) {
+ const MOSDScrubReserve *m =
+ static_cast<const MOSDScrubReserve*>(op->get_req());
+ Message *reply = new MOSDScrubReserve(
+ spg_t(info.pgid.pgid, primary.shard),
+ m->map_epoch,
+ scrubber.reserved ? MOSDScrubReserve::GRANT : MOSDScrubReserve::REJECT,
+ pg_whoami);
+ osd->send_message_osd_cluster(reply, op->get_req()->get_connection());
+ } else {
+ // for jewel compat only
+ const MOSDSubOp *req = static_cast<const MOSDSubOp*>(op->get_req());
+ assert(req->get_type() == MSG_OSD_SUBOP);
+ MOSDSubOpReply *reply = new MOSDSubOpReply(
+ req, pg_whoami, 0, get_osdmap()->get_epoch(), CEPH_OSD_FLAG_ACK);
+ ::encode(scrubber.reserved, reply->get_data());
+ osd->send_message_osd_cluster(reply, op->get_req()->get_connection());
+ }
}
-void PG::sub_op_scrub_reserve_reply(OpRequestRef op)
+void PG::handle_scrub_reserve_grant(OpRequestRef op, pg_shard_t from)
{
- const MOSDSubOpReply *reply = static_cast<const MOSDSubOpReply*>(op->get_req());
- assert(reply->get_type() == MSG_OSD_SUBOPREPLY);
- dout(7) << "sub_op_scrub_reserve_reply" << dendl;
-
+ dout(7) << __func__ << " " << *op->get_req() << dendl;
+ op->mark_started();
if (!scrubber.reserved) {
dout(10) << "ignoring obsolete scrub reserve reply" << dendl;
return;
}
+ if (scrubber.reserved_peers.find(from) != scrubber.reserved_peers.end()) {
+ dout(10) << " already had osd." << from << " reserved" << dendl;
+ } else {
+ dout(10) << " osd." << from << " scrub reserve = success" << dendl;
+ scrubber.reserved_peers.insert(from);
+ sched_scrub();
+ }
+}
+void PG::handle_scrub_reserve_reject(OpRequestRef op, pg_shard_t from)
+{
+ dout(7) << __func__ << " " << *op->get_req() << dendl;
op->mark_started();
-
- pg_shard_t from = reply->from;
- bufferlist::iterator p = const_cast<bufferlist&>(reply->get_data()).begin();
- bool reserved;
- ::decode(reserved, p);
-
+ if (!scrubber.reserved) {
+ dout(10) << "ignoring obsolete scrub reserve reply" << dendl;
+ return;
+ }
if (scrubber.reserved_peers.find(from) != scrubber.reserved_peers.end()) {
dout(10) << " already had osd." << from << " reserved" << dendl;
} else {
- if (reserved) {
- dout(10) << " osd." << from << " scrub reserve = success" << dendl;
- scrubber.reserved_peers.insert(from);
- } else {
- /* One decline stops this pg from being scheduled for scrubbing. */
- dout(10) << " osd." << from << " scrub reserve = fail" << dendl;
- scrubber.reserve_failed = true;
- }
+ /* One decline stops this pg from being scheduled for scrubbing. */
+ dout(10) << " osd." << from << " scrub reserve = fail" << dendl;
+ scrubber.reserve_failed = true;
sched_scrub();
}
}
-void PG::sub_op_scrub_unreserve(OpRequestRef op)
+void PG::handle_scrub_reserve_release(OpRequestRef op)
{
- assert(op->get_req()->get_type() == MSG_OSD_SUBOP);
- dout(7) << "sub_op_scrub_unreserve" << dendl;
-
+ dout(7) << __func__ << " " << *op->get_req() << dendl;
op->mark_started();
-
clear_scrub_reserved();
}
++i) {
if (*i == pg_whoami) continue;
dout(10) << "scrub requesting reserve from osd." << *i << dendl;
- vector<OSDOp> scrub(1);
- scrub[0].op.op = CEPH_OSD_OP_SCRUB_RESERVE;
- hobject_t poid;
- eversion_t v;
- osd_reqid_t reqid;
- MOSDSubOp *subop = new MOSDSubOp(
- reqid, pg_whoami, spg_t(info.pgid.pgid, i->shard), poid, 0,
- get_osdmap()->get_epoch(), osd->get_tid(), v);
- subop->ops = scrub;
- osd->send_message_osd_cluster(
- i->osd, subop, get_osdmap()->get_epoch());
+ if (HAVE_FEATURE(get_min_acting_features(), SERVER_LUMINOUS)) {
+ osd->send_message_osd_cluster(
+ i->osd,
+ new MOSDScrubReserve(spg_t(info.pgid.pgid, i->shard),
+ get_osdmap()->get_epoch(),
+ MOSDScrubReserve::REQUEST, pg_whoami),
+ get_osdmap()->get_epoch());
+ } else {
+ // for jewel compat only
+ vector<OSDOp> scrub(1);
+ scrub[0].op.op = CEPH_OSD_OP_SCRUB_RESERVE;
+ hobject_t poid;
+ eversion_t v;
+ osd_reqid_t reqid;
+ MOSDSubOp *subop = new MOSDSubOp(
+ reqid, pg_whoami, spg_t(info.pgid.pgid, i->shard), poid, 0,
+ get_osdmap()->get_epoch(), osd->get_tid(), v);
+ subop->ops = scrub;
+ osd->send_message_osd_cluster(
+ i->osd, subop, get_osdmap()->get_epoch());
+ }
}
}
++i) {
if (*i == pg_whoami) continue;
dout(10) << "scrub requesting unreserve from osd." << *i << dendl;
- vector<OSDOp> scrub(1);
- scrub[0].op.op = CEPH_OSD_OP_SCRUB_UNRESERVE;
- hobject_t poid;
- eversion_t v;
- osd_reqid_t reqid;
- MOSDSubOp *subop = new MOSDSubOp(
- reqid, pg_whoami, spg_t(info.pgid.pgid, i->shard), poid, 0,
- get_osdmap()->get_epoch(), osd->get_tid(), v);
- subop->ops = scrub;
- osd->send_message_osd_cluster(i->osd, subop, get_osdmap()->get_epoch());
+ if (HAVE_FEATURE(get_min_acting_features(), SERVER_LUMINOUS)) {
+ osd->send_message_osd_cluster(
+ i->osd,
+ new MOSDScrubReserve(spg_t(info.pgid.pgid, i->shard),
+ get_osdmap()->get_epoch(),
+ MOSDScrubReserve::RELEASE, pg_whoami),
+ get_osdmap()->get_epoch());
+ } else {
+ // for jewel compat only
+ vector<OSDOp> scrub(1);
+ scrub[0].op.op = CEPH_OSD_OP_SCRUB_UNRESERVE;
+ hobject_t poid;
+ eversion_t v;
+ osd_reqid_t reqid;
+ MOSDSubOp *subop = new MOSDSubOp(
+ reqid, pg_whoami, spg_t(info.pgid.pgid, i->shard), poid, 0,
+ get_osdmap()->get_epoch(), osd->get_tid(), v);
+ subop->ops = scrub;
+ osd->send_message_osd_cluster(i->osd, subop, get_osdmap()->get_epoch());
+ }
}
}
return can_discard_replica_op<MOSDECSubOpReadReply, MSG_OSD_EC_READ_REPLY>(op);
case MSG_OSD_REP_SCRUB:
return can_discard_replica_op<MOSDRepScrub, MSG_OSD_REP_SCRUB>(op);
+ case MSG_OSD_SCRUB_RESERVE:
+ return can_discard_replica_op<MOSDScrubReserve, MSG_OSD_SCRUB_RESERVE>(op);
case MSG_OSD_REP_SCRUBMAP:
return can_discard_replica_op<MOSDRepScrubMap, MSG_OSD_REP_SCRUBMAP>(op);
case MSG_OSD_PG_UPDATE_LOG_MISSING:
cur_epoch,
static_cast<const MOSDRepScrub*>(op->get_req())->map_epoch);
+ case MSG_OSD_SCRUB_RESERVE:
+ return !have_same_or_newer_map(
+ cur_epoch,
+ static_cast<const MOSDScrubReserve*>(op->get_req())->map_epoch);
+
case MSG_OSD_REP_SCRUBMAP:
return !have_same_or_newer_map(
cur_epoch,
#include "messages/MOSDPGUpdateLogMissing.h"
#include "messages/MOSDPGUpdateLogMissingReply.h"
#include "messages/MCommandReply.h"
+#include "messages/MOSDScrubReserve.h"
#include "mds/inode_backtrace.h" // Ugh
#include "common/EventTrace.h"
do_backfill_remove(op);
break;
+ case MSG_OSD_SCRUB_RESERVE:
+ {
+ const MOSDScrubReserve *m =
+ static_cast<const MOSDScrubReserve*>(op->get_req());
+ switch (m->type) {
+ case MOSDScrubReserve::REQUEST:
+ handle_scrub_reserve_request(op);
+ break;
+ case MOSDScrubReserve::GRANT:
+ handle_scrub_reserve_grant(op, m->from);
+ break;
+ case MOSDScrubReserve::REJECT:
+ handle_scrub_reserve_reject(op, m->from);
+ break;
+ case MOSDScrubReserve::RELEASE:
+ handle_scrub_reserve_release(op);
+ break;
+ }
+ }
+ break;
+
case MSG_OSD_REP_SCRUB:
replica_scrub(op, handle);
break;
sub_op_remove(op);
return;
case CEPH_OSD_OP_SCRUB_RESERVE:
- sub_op_scrub_reserve(op);
+ handle_scrub_reserve_request(op);
return;
case CEPH_OSD_OP_SCRUB_UNRESERVE:
- sub_op_scrub_unreserve(op);
+ handle_scrub_reserve_release(op);
return;
case CEPH_OSD_OP_SCRUB_MAP:
sub_op_scrub_map(op);
const OSDOp& first = r->ops[0];
switch (first.op.op) {
case CEPH_OSD_OP_SCRUB_RESERVE:
- sub_op_scrub_reserve_reply(op);
+ {
+ pg_shard_t from = r->from;
+ bufferlist::iterator p = const_cast<bufferlist&>(r->get_data()).begin();
+ bool reserved;
+ ::decode(reserved, p);
+ if (reserved) {
+ handle_scrub_reserve_grant(op, from);
+ } else {
+ handle_scrub_reserve_reject(op, from);
+ }
+ }
return;
}
}