2020-01-21 14:04:58 +03:00
|
|
|
#include <netinet/tcp.h>
|
|
|
|
#include <sys/epoll.h>
|
2020-01-23 21:43:45 +03:00
|
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
2020-04-16 23:22:32 +03:00
|
|
|
#include "base64.h"
|
2020-01-21 14:04:58 +03:00
|
|
|
#include "osd.h"
|
|
|
|
|
|
|
|
// Peering loop
|
|
|
|
void osd_t::handle_peers()
|
|
|
|
{
|
2020-02-11 02:30:46 +03:00
|
|
|
if (peering_state & OSD_PEERING_PGS)
|
2020-01-21 14:04:58 +03:00
|
|
|
{
|
2020-03-13 21:41:54 +03:00
|
|
|
bool still = false;
|
|
|
|
for (auto & p: pgs)
|
2020-01-21 14:04:58 +03:00
|
|
|
{
|
2020-03-13 21:41:54 +03:00
|
|
|
if (p.second.state == PG_PEERING)
|
2020-01-21 14:04:58 +03:00
|
|
|
{
|
2020-03-13 21:41:54 +03:00
|
|
|
if (!p.second.peering_state->list_ops.size())
|
2020-01-22 02:36:14 +03:00
|
|
|
{
|
2020-04-27 14:32:59 +03:00
|
|
|
p.second.calc_object_states(log_level);
|
|
|
|
report_pg_state(p.second);
|
2020-03-31 17:50:50 +03:00
|
|
|
incomplete_objects += p.second.incomplete_objects.size();
|
|
|
|
misplaced_objects += p.second.misplaced_objects.size();
|
2020-04-04 02:18:29 +03:00
|
|
|
// FIXME: degraded objects may currently include misplaced, too! Report them separately?
|
2020-03-31 17:50:50 +03:00
|
|
|
degraded_objects += p.second.degraded_objects.size();
|
2020-05-01 02:09:18 +03:00
|
|
|
if ((p.second.state & (PG_ACTIVE | PG_HAS_UNCLEAN)) == (PG_ACTIVE | PG_HAS_UNCLEAN))
|
2020-03-13 21:41:54 +03:00
|
|
|
peering_state = peering_state | OSD_FLUSHING_PGS;
|
2020-03-25 02:17:12 +03:00
|
|
|
else
|
|
|
|
peering_state = peering_state | OSD_RECOVERING;
|
2020-01-22 02:36:14 +03:00
|
|
|
}
|
2020-02-11 02:30:46 +03:00
|
|
|
else
|
2020-01-22 02:36:14 +03:00
|
|
|
{
|
2020-03-13 21:41:54 +03:00
|
|
|
still = true;
|
2020-01-22 02:36:14 +03:00
|
|
|
}
|
2020-01-21 14:04:58 +03:00
|
|
|
}
|
|
|
|
}
|
2020-03-13 21:41:54 +03:00
|
|
|
if (!still)
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
|
|
|
// Done all PGs
|
|
|
|
peering_state = peering_state & ~OSD_PEERING_PGS;
|
|
|
|
}
|
|
|
|
}
|
2020-04-11 12:05:28 +03:00
|
|
|
if ((peering_state & OSD_FLUSHING_PGS) && !readonly)
|
2020-03-13 21:41:54 +03:00
|
|
|
{
|
|
|
|
bool still = false;
|
|
|
|
for (auto & p: pgs)
|
|
|
|
{
|
2020-05-01 02:09:18 +03:00
|
|
|
if ((p.second.state & (PG_ACTIVE | PG_HAS_UNCLEAN)) == (PG_ACTIVE | PG_HAS_UNCLEAN))
|
2020-03-13 21:41:54 +03:00
|
|
|
{
|
|
|
|
if (!p.second.flush_batch)
|
|
|
|
{
|
|
|
|
submit_pg_flush_ops(p.first);
|
|
|
|
}
|
|
|
|
still = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!still)
|
|
|
|
{
|
2020-03-24 01:13:04 +03:00
|
|
|
peering_state = peering_state & ~OSD_FLUSHING_PGS | OSD_RECOVERING;
|
|
|
|
}
|
|
|
|
}
|
2020-04-11 12:05:28 +03:00
|
|
|
if ((peering_state & OSD_RECOVERING) && !readonly)
|
2020-03-24 01:13:04 +03:00
|
|
|
{
|
|
|
|
if (!continue_recovery())
|
|
|
|
{
|
|
|
|
peering_state = peering_state & ~OSD_RECOVERING;
|
2020-03-13 21:41:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-20 17:44:03 +03:00
|
|
|
void osd_t::repeer_pgs(osd_num_t peer_osd)
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
|
|
|
// Re-peer affected PGs
|
2020-03-13 21:41:54 +03:00
|
|
|
for (auto & p: pgs)
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
|
|
|
bool repeer = false;
|
2020-04-27 14:32:59 +03:00
|
|
|
if (p.second.state & (PG_PEERING | PG_ACTIVE | PG_INCOMPLETE))
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
2020-04-19 00:20:18 +03:00
|
|
|
for (osd_num_t pg_osd: p.second.all_peers)
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
2020-04-20 17:44:03 +03:00
|
|
|
if (pg_osd == peer_osd)
|
2020-04-07 01:53:13 +03:00
|
|
|
{
|
|
|
|
repeer = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (repeer)
|
|
|
|
{
|
|
|
|
// Repeer this pg
|
2020-04-21 00:10:59 +03:00
|
|
|
printf("[PG %u] Repeer because of OSD %lu\n", p.second.pg_num, peer_osd);
|
2020-04-07 01:53:13 +03:00
|
|
|
start_pg_peering(p.second.pg_num);
|
2020-02-11 02:30:46 +03:00
|
|
|
}
|
|
|
|
}
|
2020-01-21 14:04:58 +03:00
|
|
|
}
|
|
|
|
}
|
2020-01-22 02:36:14 +03:00
|
|
|
|
2020-02-11 02:30:46 +03:00
|
|
|
// Repeer on each connect/disconnect peer event
|
2020-03-13 21:41:54 +03:00
|
|
|
void osd_t::start_pg_peering(pg_num_t pg_num)
|
2020-01-22 02:36:14 +03:00
|
|
|
{
|
2020-03-13 21:41:54 +03:00
|
|
|
auto & pg = pgs[pg_num];
|
2020-02-11 02:30:46 +03:00
|
|
|
pg.state = PG_PEERING;
|
2020-04-27 14:32:59 +03:00
|
|
|
this->peering_state |= OSD_PEERING_PGS;
|
|
|
|
report_pg_state(pg);
|
2020-04-03 13:03:42 +03:00
|
|
|
// Reset PG state
|
2020-05-04 01:32:24 +03:00
|
|
|
pg.cur_peers.clear();
|
2020-02-11 02:30:46 +03:00
|
|
|
pg.state_dict.clear();
|
2020-03-31 17:50:50 +03:00
|
|
|
incomplete_objects -= pg.incomplete_objects.size();
|
|
|
|
misplaced_objects -= pg.misplaced_objects.size();
|
|
|
|
degraded_objects -= pg.degraded_objects.size();
|
2020-03-30 19:43:12 +03:00
|
|
|
pg.incomplete_objects.clear();
|
2020-03-24 01:13:04 +03:00
|
|
|
pg.misplaced_objects.clear();
|
|
|
|
pg.degraded_objects.clear();
|
2020-03-13 21:41:54 +03:00
|
|
|
pg.flush_actions.clear();
|
2020-03-30 19:43:12 +03:00
|
|
|
pg.ver_override.clear();
|
2020-03-13 21:41:54 +03:00
|
|
|
if (pg.flush_batch)
|
2020-03-30 19:43:12 +03:00
|
|
|
{
|
2020-03-13 21:41:54 +03:00
|
|
|
delete pg.flush_batch;
|
2020-03-30 19:43:12 +03:00
|
|
|
}
|
2020-03-13 21:41:54 +03:00
|
|
|
pg.flush_batch = NULL;
|
2020-03-30 19:43:12 +03:00
|
|
|
for (auto p: pg.write_queue)
|
|
|
|
{
|
2020-06-01 01:53:32 +03:00
|
|
|
cancel_primary_write(p.second);
|
2020-03-30 19:43:12 +03:00
|
|
|
}
|
|
|
|
pg.write_queue.clear();
|
2020-03-31 02:09:25 +03:00
|
|
|
for (auto it = unstable_writes.begin(); it != unstable_writes.end(); )
|
|
|
|
{
|
2020-04-03 13:03:42 +03:00
|
|
|
// Forget this PG's unstable writes
|
2020-03-31 02:09:25 +03:00
|
|
|
pg_num_t n = (it->first.oid.inode + it->first.oid.stripe / pg_stripe_size) % pg_count + 1;
|
|
|
|
if (n == pg.pg_num)
|
|
|
|
unstable_writes.erase(it++);
|
|
|
|
else
|
|
|
|
it++;
|
|
|
|
}
|
2020-04-03 13:03:42 +03:00
|
|
|
dirty_pgs.erase(pg.pg_num);
|
2020-04-19 00:20:18 +03:00
|
|
|
// Calculate current write OSD set
|
2020-02-11 02:30:46 +03:00
|
|
|
pg.pg_cursize = 0;
|
2020-04-17 02:33:44 +03:00
|
|
|
pg.cur_set.resize(pg.target_set.size());
|
2020-05-05 00:16:01 +03:00
|
|
|
pg.cur_loc_set.clear();
|
2020-04-17 02:33:44 +03:00
|
|
|
for (int role = 0; role < pg.target_set.size(); role++)
|
2020-01-22 02:36:14 +03:00
|
|
|
{
|
2020-04-17 02:33:44 +03:00
|
|
|
pg.cur_set[role] = pg.target_set[role] == this->osd_num ||
|
2020-05-26 21:23:01 +03:00
|
|
|
c_cli.osd_peer_fds.find(pg.target_set[role]) != c_cli.osd_peer_fds.end() ? pg.target_set[role] : 0;
|
2020-02-11 02:30:46 +03:00
|
|
|
if (pg.cur_set[role] != 0)
|
2020-01-22 02:36:14 +03:00
|
|
|
{
|
2020-02-11 02:30:46 +03:00
|
|
|
pg.pg_cursize++;
|
2020-05-05 00:16:01 +03:00
|
|
|
pg.cur_loc_set.push_back({
|
|
|
|
.role = (uint64_t)role,
|
|
|
|
.osd_num = pg.cur_set[role],
|
|
|
|
.outdated = false,
|
|
|
|
});
|
2020-02-11 02:30:46 +03:00
|
|
|
}
|
|
|
|
}
|
2020-04-19 00:20:18 +03:00
|
|
|
if (pg.target_history.size())
|
|
|
|
{
|
|
|
|
// Refuse to start PG if no peers are available from any of the historical OSD sets
|
|
|
|
// (PG history is kept up to the latest active+clean state)
|
|
|
|
for (auto & history_set: pg.target_history)
|
|
|
|
{
|
|
|
|
bool found = false;
|
|
|
|
for (auto history_osd: history_set)
|
|
|
|
{
|
2020-05-26 21:23:01 +03:00
|
|
|
if (history_osd != 0 && c_cli.osd_peer_fds.find(history_osd) != c_cli.osd_peer_fds.end())
|
2020-04-19 00:20:18 +03:00
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!found)
|
|
|
|
{
|
|
|
|
pg.state = PG_INCOMPLETE;
|
2020-04-27 14:32:59 +03:00
|
|
|
report_pg_state(pg);
|
2020-04-19 00:20:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-11 02:30:46 +03:00
|
|
|
if (pg.pg_cursize < pg.pg_minsize)
|
|
|
|
{
|
|
|
|
pg.state = PG_INCOMPLETE;
|
2020-04-27 14:32:59 +03:00
|
|
|
report_pg_state(pg);
|
2020-02-11 02:30:46 +03:00
|
|
|
}
|
2020-04-19 00:20:18 +03:00
|
|
|
std::set<osd_num_t> cur_peers;
|
2020-05-26 21:23:01 +03:00
|
|
|
for (auto pg_osd: pg.all_peers)
|
2020-04-19 00:20:18 +03:00
|
|
|
{
|
2020-05-26 21:23:01 +03:00
|
|
|
if (pg_osd == this->osd_num || c_cli.osd_peer_fds.find(pg_osd) != c_cli.osd_peer_fds.end())
|
2020-04-19 00:20:18 +03:00
|
|
|
{
|
2020-05-26 21:23:01 +03:00
|
|
|
cur_peers.insert(pg_osd);
|
2020-04-19 00:20:18 +03:00
|
|
|
}
|
2020-05-26 21:23:01 +03:00
|
|
|
else if (c_cli.wanted_peers.find(pg_osd) == c_cli.wanted_peers.end())
|
2020-04-19 01:01:26 +03:00
|
|
|
{
|
2020-06-06 01:39:58 +03:00
|
|
|
c_cli.connect_peer(pg_osd, st_cli.peer_states[pg_osd]);
|
2020-04-19 01:01:26 +03:00
|
|
|
}
|
2020-04-19 00:20:18 +03:00
|
|
|
}
|
2020-05-04 01:32:24 +03:00
|
|
|
pg.cur_peers.insert(pg.cur_peers.begin(), cur_peers.begin(), cur_peers.end());
|
2020-02-11 02:30:46 +03:00
|
|
|
if (pg.peering_state)
|
|
|
|
{
|
2020-04-19 00:20:18 +03:00
|
|
|
// Adjust the peering operation that's still in progress - discard unneeded results
|
2020-04-20 17:44:03 +03:00
|
|
|
for (auto it = pg.peering_state->list_ops.begin(); it != pg.peering_state->list_ops.end();)
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
2020-04-19 00:20:18 +03:00
|
|
|
if (pg.state == PG_INCOMPLETE || cur_peers.find(it->first) == cur_peers.end())
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
|
|
|
// Discard the result after completion, which, chances are, will be unsuccessful
|
2020-04-27 14:32:59 +03:00
|
|
|
discard_list_subop(it->second);
|
2020-02-13 19:13:16 +03:00
|
|
|
pg.peering_state->list_ops.erase(it);
|
|
|
|
it = pg.peering_state->list_ops.begin();
|
2020-02-11 02:30:46 +03:00
|
|
|
}
|
2020-04-20 17:44:03 +03:00
|
|
|
else
|
|
|
|
it++;
|
2020-02-11 02:30:46 +03:00
|
|
|
}
|
2020-04-20 17:44:03 +03:00
|
|
|
for (auto it = pg.peering_state->list_results.begin(); it != pg.peering_state->list_results.end();)
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
2020-04-19 00:20:18 +03:00
|
|
|
if (pg.state == PG_INCOMPLETE || cur_peers.find(it->first) == cur_peers.end())
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
2020-02-24 01:01:34 +03:00
|
|
|
if (it->second.buf)
|
|
|
|
{
|
|
|
|
free(it->second.buf);
|
|
|
|
}
|
|
|
|
pg.peering_state->list_results.erase(it);
|
|
|
|
it = pg.peering_state->list_results.begin();
|
2020-02-11 02:30:46 +03:00
|
|
|
}
|
2020-04-20 17:44:03 +03:00
|
|
|
else
|
|
|
|
it++;
|
2020-02-11 02:30:46 +03:00
|
|
|
}
|
2020-01-22 02:36:14 +03:00
|
|
|
}
|
2020-02-11 02:30:46 +03:00
|
|
|
if (pg.state == PG_INCOMPLETE)
|
2020-01-22 02:36:14 +03:00
|
|
|
{
|
2020-02-11 02:30:46 +03:00
|
|
|
if (pg.peering_state)
|
|
|
|
{
|
|
|
|
delete pg.peering_state;
|
|
|
|
pg.peering_state = NULL;
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!pg.peering_state)
|
|
|
|
{
|
|
|
|
pg.peering_state = new pg_peering_state_t();
|
2020-04-19 00:20:18 +03:00
|
|
|
pg.peering_state->pg_num = pg.pg_num;
|
2020-02-11 02:30:46 +03:00
|
|
|
}
|
2020-04-19 00:20:18 +03:00
|
|
|
for (osd_num_t peer_osd: cur_peers)
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
2020-04-19 00:20:18 +03:00
|
|
|
if (pg.peering_state->list_ops.find(peer_osd) != pg.peering_state->list_ops.end() ||
|
|
|
|
pg.peering_state->list_results.find(peer_osd) != pg.peering_state->list_results.end())
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
2020-05-01 12:55:15 +03:00
|
|
|
submit_sync_and_list_subop(peer_osd, pg.peering_state);
|
2020-04-19 00:20:18 +03:00
|
|
|
}
|
|
|
|
ringloop->wakeup();
|
|
|
|
}
|
|
|
|
|
2020-05-01 12:55:15 +03:00
|
|
|
void osd_t::submit_sync_and_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
|
|
|
|
{
|
|
|
|
// Sync before listing, if not readonly
|
|
|
|
if (readonly)
|
|
|
|
{
|
|
|
|
submit_list_subop(role_osd, ps);
|
|
|
|
}
|
|
|
|
else if (role_osd == this->osd_num)
|
|
|
|
{
|
|
|
|
// Self
|
|
|
|
osd_op_t *op = new osd_op_t();
|
|
|
|
op->op_type = 0;
|
|
|
|
op->peer_fd = 0;
|
2020-05-11 02:58:13 +03:00
|
|
|
clock_gettime(CLOCK_REALTIME, &op->tv_begin);
|
2020-05-01 12:55:15 +03:00
|
|
|
op->bs_op = new blockstore_op_t();
|
|
|
|
op->bs_op->opcode = BS_OP_SYNC;
|
|
|
|
op->bs_op->callback = [this, ps, op, role_osd](blockstore_op_t *bs_op)
|
|
|
|
{
|
|
|
|
if (bs_op->retval < 0)
|
|
|
|
{
|
|
|
|
printf("Local OP_SYNC failed: %d (%s)\n", bs_op->retval, strerror(-bs_op->retval));
|
|
|
|
force_stop(1);
|
|
|
|
return;
|
|
|
|
}
|
2020-05-11 02:58:13 +03:00
|
|
|
add_bs_subop_stats(op);
|
2020-05-25 15:09:55 +03:00
|
|
|
delete op->bs_op;
|
|
|
|
op->bs_op = NULL;
|
2020-05-01 12:55:15 +03:00
|
|
|
delete op;
|
|
|
|
ps->list_ops.erase(role_osd);
|
|
|
|
submit_list_subop(role_osd, ps);
|
|
|
|
};
|
|
|
|
bs->enqueue_op(op->bs_op);
|
|
|
|
ps->list_ops[role_osd] = op;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Peer
|
2020-05-26 21:23:01 +03:00
|
|
|
auto & cl = c_cli.clients.at(c_cli.osd_peer_fds[role_osd]);
|
2020-05-01 12:55:15 +03:00
|
|
|
osd_op_t *op = new osd_op_t();
|
|
|
|
op->op_type = OSD_OP_OUT;
|
|
|
|
op->send_list.push_back(op->req.buf, OSD_PACKET_SIZE);
|
|
|
|
op->peer_fd = cl.peer_fd;
|
|
|
|
op->req = {
|
|
|
|
.sec_sync = {
|
|
|
|
.header = {
|
|
|
|
.magic = SECONDARY_OSD_OP_MAGIC,
|
2020-05-26 21:23:01 +03:00
|
|
|
.id = c_cli.next_subop_id++,
|
2020-05-01 12:55:15 +03:00
|
|
|
.opcode = OSD_OP_SECONDARY_SYNC,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
op->callback = [this, ps, role_osd](osd_op_t *op)
|
|
|
|
{
|
|
|
|
if (op->reply.hdr.retval < 0)
|
|
|
|
{
|
|
|
|
// FIXME: Mark peer as failed and don't reconnect immediately after dropping the connection
|
|
|
|
printf("Failed to sync OSD %lu: %ld (%s), disconnecting peer\n", role_osd, op->reply.hdr.retval, strerror(-op->reply.hdr.retval));
|
|
|
|
ps->list_ops.erase(role_osd);
|
2020-05-26 21:23:01 +03:00
|
|
|
c_cli.stop_client(op->peer_fd);
|
2020-05-01 12:55:15 +03:00
|
|
|
delete op;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
delete op;
|
|
|
|
ps->list_ops.erase(role_osd);
|
|
|
|
submit_list_subop(role_osd, ps);
|
|
|
|
};
|
2020-05-26 21:23:01 +03:00
|
|
|
c_cli.outbox_push(op);
|
2020-05-01 12:55:15 +03:00
|
|
|
ps->list_ops[role_osd] = op;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-19 00:20:18 +03:00
|
|
|
void osd_t::submit_list_subop(osd_num_t role_osd, pg_peering_state_t *ps)
|
|
|
|
{
|
|
|
|
if (role_osd == this->osd_num)
|
|
|
|
{
|
|
|
|
// Self
|
|
|
|
osd_op_t *op = new osd_op_t();
|
|
|
|
op->op_type = 0;
|
|
|
|
op->peer_fd = 0;
|
2020-05-11 02:58:13 +03:00
|
|
|
clock_gettime(CLOCK_REALTIME, &op->tv_begin);
|
2020-04-19 00:20:18 +03:00
|
|
|
op->bs_op = new blockstore_op_t();
|
|
|
|
op->bs_op->opcode = BS_OP_LIST;
|
|
|
|
op->bs_op->oid.stripe = pg_stripe_size;
|
|
|
|
op->bs_op->len = pg_count;
|
|
|
|
op->bs_op->offset = ps->pg_num-1;
|
2020-05-11 02:58:13 +03:00
|
|
|
op->bs_op->callback = [this, ps, op, role_osd](blockstore_op_t *bs_op)
|
2020-01-22 02:36:14 +03:00
|
|
|
{
|
2020-04-19 00:20:18 +03:00
|
|
|
if (op->bs_op->retval < 0)
|
2020-01-24 02:23:27 +03:00
|
|
|
{
|
2020-04-19 00:20:18 +03:00
|
|
|
throw std::runtime_error("local OP_LIST failed");
|
|
|
|
}
|
2020-05-11 02:58:13 +03:00
|
|
|
add_bs_subop_stats(op);
|
2020-04-19 00:20:18 +03:00
|
|
|
printf(
|
|
|
|
"[PG %u] Got object list from OSD %lu (local): %d object versions (%lu of them stable)\n",
|
|
|
|
ps->pg_num, role_osd, bs_op->retval, bs_op->version
|
|
|
|
);
|
|
|
|
ps->list_results[role_osd] = {
|
|
|
|
.buf = (obj_ver_id*)op->bs_op->buf,
|
|
|
|
.total_count = (uint64_t)op->bs_op->retval,
|
|
|
|
.stable_count = op->bs_op->version,
|
2020-01-24 02:23:27 +03:00
|
|
|
};
|
2020-04-19 00:20:18 +03:00
|
|
|
ps->list_ops.erase(role_osd);
|
2020-05-25 15:09:55 +03:00
|
|
|
delete op->bs_op;
|
|
|
|
op->bs_op = NULL;
|
2020-04-19 00:20:18 +03:00
|
|
|
delete op;
|
|
|
|
};
|
|
|
|
bs->enqueue_op(op->bs_op);
|
|
|
|
ps->list_ops[role_osd] = op;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Peer
|
|
|
|
osd_op_t *op = new osd_op_t();
|
|
|
|
op->op_type = OSD_OP_OUT;
|
|
|
|
op->send_list.push_back(op->req.buf, OSD_PACKET_SIZE);
|
2020-05-26 21:23:01 +03:00
|
|
|
op->peer_fd = c_cli.osd_peer_fds[role_osd];
|
2020-04-19 00:20:18 +03:00
|
|
|
op->req = {
|
|
|
|
.sec_list = {
|
|
|
|
.header = {
|
|
|
|
.magic = SECONDARY_OSD_OP_MAGIC,
|
2020-05-26 21:23:01 +03:00
|
|
|
.id = c_cli.next_subop_id++,
|
2020-04-19 00:20:18 +03:00
|
|
|
.opcode = OSD_OP_SECONDARY_LIST,
|
2020-02-11 02:30:46 +03:00
|
|
|
},
|
2020-04-19 00:20:18 +03:00
|
|
|
.list_pg = ps->pg_num,
|
|
|
|
.pg_count = pg_count,
|
|
|
|
.pg_stripe_size = pg_stripe_size,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
op->callback = [this, ps, role_osd](osd_op_t *op)
|
|
|
|
{
|
|
|
|
if (op->reply.hdr.retval < 0)
|
2020-02-11 02:30:46 +03:00
|
|
|
{
|
2020-04-19 00:20:18 +03:00
|
|
|
printf("Failed to get object list from OSD %lu (retval=%ld), disconnecting peer\n", role_osd, op->reply.hdr.retval);
|
2020-02-11 02:30:46 +03:00
|
|
|
ps->list_ops.erase(role_osd);
|
2020-05-26 21:23:01 +03:00
|
|
|
c_cli.stop_client(op->peer_fd);
|
2020-02-11 02:30:46 +03:00
|
|
|
delete op;
|
2020-04-19 00:20:18 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
printf(
|
|
|
|
"[PG %u] Got object list from OSD %lu: %ld object versions (%lu of them stable)\n",
|
|
|
|
ps->pg_num, role_osd, op->reply.hdr.retval, op->reply.sec_list.stable_count
|
|
|
|
);
|
|
|
|
ps->list_results[role_osd] = {
|
|
|
|
.buf = (obj_ver_id*)op->buf,
|
|
|
|
.total_count = (uint64_t)op->reply.hdr.retval,
|
|
|
|
.stable_count = op->reply.sec_list.stable_count,
|
2020-02-11 02:30:46 +03:00
|
|
|
};
|
2020-04-19 00:20:18 +03:00
|
|
|
// set op->buf to NULL so it doesn't get freed
|
|
|
|
op->buf = NULL;
|
|
|
|
ps->list_ops.erase(role_osd);
|
|
|
|
delete op;
|
|
|
|
};
|
2020-05-26 21:23:01 +03:00
|
|
|
c_cli.outbox_push(op);
|
2020-04-19 00:20:18 +03:00
|
|
|
ps->list_ops[role_osd] = op;
|
2020-01-22 02:36:14 +03:00
|
|
|
}
|
|
|
|
}
|
2020-04-03 13:03:42 +03:00
|
|
|
|
2020-04-27 14:32:59 +03:00
|
|
|
void osd_t::discard_list_subop(osd_op_t *list_op)
|
|
|
|
{
|
|
|
|
if (list_op->peer_fd == 0)
|
|
|
|
{
|
|
|
|
// Self
|
|
|
|
list_op->bs_op->callback = [list_op](blockstore_op_t *bs_op)
|
|
|
|
{
|
|
|
|
if (list_op->bs_op->buf)
|
|
|
|
free(list_op->bs_op->buf);
|
2020-05-25 15:09:55 +03:00
|
|
|
delete list_op->bs_op;
|
|
|
|
list_op->bs_op = NULL;
|
2020-04-27 14:32:59 +03:00
|
|
|
delete list_op;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Peer
|
|
|
|
list_op->callback = [](osd_op_t *list_op)
|
|
|
|
{
|
|
|
|
delete list_op;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-03 13:03:42 +03:00
|
|
|
bool osd_t::stop_pg(pg_num_t pg_num)
|
|
|
|
{
|
|
|
|
auto pg_it = pgs.find(pg_num);
|
|
|
|
if (pg_it == pgs.end())
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
auto & pg = pg_it->second;
|
2020-04-27 14:32:59 +03:00
|
|
|
if (pg.peering_state)
|
|
|
|
{
|
|
|
|
// Stop peering
|
|
|
|
for (auto it = pg.peering_state->list_ops.begin(); it != pg.peering_state->list_ops.end();)
|
|
|
|
{
|
|
|
|
discard_list_subop(it->second);
|
|
|
|
}
|
|
|
|
for (auto it = pg.peering_state->list_results.begin(); it != pg.peering_state->list_results.end();)
|
|
|
|
{
|
|
|
|
if (it->second.buf)
|
|
|
|
{
|
|
|
|
free(it->second.buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
delete pg.peering_state;
|
|
|
|
pg.peering_state = NULL;
|
|
|
|
}
|
2020-04-03 13:03:42 +03:00
|
|
|
if (!(pg.state & PG_ACTIVE))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
pg.state = pg.state & ~PG_ACTIVE | PG_STOPPING;
|
2020-04-27 14:32:59 +03:00
|
|
|
if (pg.inflight == 0 && !pg.flush_batch)
|
2020-04-03 13:03:42 +03:00
|
|
|
{
|
|
|
|
finish_stop_pg(pg);
|
|
|
|
}
|
2020-04-27 14:32:59 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
report_pg_state(pg);
|
|
|
|
}
|
2020-04-03 13:03:42 +03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void osd_t::finish_stop_pg(pg_t & pg)
|
|
|
|
{
|
|
|
|
pg.state = PG_OFFLINE;
|
2020-04-27 14:32:59 +03:00
|
|
|
report_pg_state(pg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void osd_t::report_pg_state(pg_t & pg)
|
|
|
|
{
|
|
|
|
pg.print_state();
|
|
|
|
this->pg_state_dirty.insert(pg.pg_num);
|
2020-05-04 01:32:24 +03:00
|
|
|
if (pg.state == PG_ACTIVE && (pg.target_history.size() > 0 || pg.all_peers.size() > pg.target_set.size()))
|
|
|
|
{
|
|
|
|
// Clear history of active+clean PGs
|
|
|
|
pg.history_changed = true;
|
|
|
|
pg.target_history.clear();
|
|
|
|
pg.all_peers = pg.target_set;
|
|
|
|
pg.cur_peers = pg.target_set;
|
|
|
|
}
|
|
|
|
else if (pg.state == (PG_ACTIVE|PG_LEFT_ON_DEAD))
|
|
|
|
{
|
|
|
|
// Clear history of active+left_on_dead PGs, but leave dead OSDs in all_peers
|
|
|
|
pg.history_changed = true;
|
|
|
|
pg.target_history.clear();
|
|
|
|
std::set<osd_num_t> dead_peers;
|
|
|
|
for (auto pg_osd: pg.all_peers)
|
|
|
|
{
|
|
|
|
dead_peers.insert(pg_osd);
|
|
|
|
}
|
|
|
|
for (auto pg_osd: pg.cur_peers)
|
|
|
|
{
|
|
|
|
dead_peers.erase(pg_osd);
|
|
|
|
}
|
|
|
|
for (auto pg_osd: pg.target_set)
|
|
|
|
{
|
|
|
|
if (pg_osd)
|
|
|
|
{
|
|
|
|
dead_peers.insert(pg_osd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pg.all_peers.clear();
|
|
|
|
pg.all_peers.insert(pg.all_peers.begin(), dead_peers.begin(), dead_peers.end());
|
|
|
|
pg.cur_peers.clear();
|
|
|
|
for (auto pg_osd: pg.target_set)
|
|
|
|
{
|
|
|
|
if (pg_osd)
|
|
|
|
{
|
|
|
|
pg.cur_peers.push_back(pg_osd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-27 14:32:59 +03:00
|
|
|
if (pg.state == PG_OFFLINE && !this->pg_config_applied)
|
|
|
|
{
|
|
|
|
apply_pg_config();
|
|
|
|
}
|
|
|
|
report_pg_states();
|
2020-04-03 13:03:42 +03:00
|
|
|
}
|