Fix OSDs still crashing when the cluster is full with EC

ENOSPC handling was introduced in 1.6.0 but it was not complete; now it is

P.S: See also client_retry_enospc (true by default)
This commit is contained in:
Vitaliy Filippov
2024-12-26 01:56:33 +03:00
parent cef98052f5
commit 42eebfc1bd
2 changed files with 10 additions and 8 deletions
+2 -2
View File
@@ -744,7 +744,7 @@ void osd_t::submit_primary_rollback_subops(osd_op_t *cur_op, const uint64_t* osd
for (int role = 0; role < op_data->pg_size; role++) for (int role = 0; role < op_data->pg_size; role++)
{ {
if (osd_set[role] != 0 && !stripes[role].read_error && if (osd_set[role] != 0 && !stripes[role].read_error &&
msgr.osd_peer_fds.find(osd_set[role]) != msgr.osd_peer_fds.end()) (osd_set[role] == this->osd_num || msgr.osd_peer_fds.find(osd_set[role]) != msgr.osd_peer_fds.end()))
{ {
n_subops++; n_subops++;
} }
@@ -761,7 +761,7 @@ void osd_t::submit_primary_rollback_subops(osd_op_t *cur_op, const uint64_t* osd
for (int role = 0; role < op_data->pg_size; role++) for (int role = 0; role < op_data->pg_size; role++)
{ {
if (osd_set[role] != 0 && !stripes[role].read_error && if (osd_set[role] != 0 && !stripes[role].read_error &&
msgr.osd_peer_fds.find(osd_set[role]) != msgr.osd_peer_fds.end()) (osd_set[role] == this->osd_num || msgr.osd_peer_fds.find(osd_set[role]) != msgr.osd_peer_fds.end()))
{ {
osd_op_t *subop = &op_data->subops[i]; osd_op_t *subop = &op_data->subops[i];
op_data->unstable_writes[i] = (obj_ver_id){ op_data->unstable_writes[i] = (obj_ver_id){
+8 -6
View File
@@ -260,11 +260,6 @@ resume_4:
op_data->st = 4; op_data->st = 4;
return; return;
resume_5: resume_5:
if (op_data->scheme != POOL_SCHEME_REPLICATED)
{
// Remove version override just after the write, but before stabilizing
pg.ver_override.erase(op_data->oid);
}
if (op_data->errors > 0) if (op_data->errors > 0)
{ {
// Handle ENOSPC/EDOM/ERANGE/EIO. If some subops fail, but others succeed, // Handle ENOSPC/EDOM/ERANGE/EIO. If some subops fail, but others succeed,
@@ -276,7 +271,7 @@ resume_5:
{ {
if (op_data->scheme != POOL_SCHEME_REPLICATED) if (op_data->scheme != POOL_SCHEME_REPLICATED)
{ {
submit_primary_rollback_subops(cur_op, op_data->prev_set); submit_primary_rollback_subops(cur_op, pg.cur_set.data());
resume_11: resume_11:
op_data->st = 11; op_data->st = 11;
return; return;
@@ -287,15 +282,22 @@ resume_12:
} }
else else
{ {
pg.ver_override.erase(op_data->oid);
mark_partial_write(pg, op_data->oid, op_data->object_state, op_data->stripes, true); mark_partial_write(pg, op_data->oid, op_data->object_state, op_data->stripes, true);
pg_cancel_write_queue(pg, cur_op, op_data->oid, op_data->errcode); pg_cancel_write_queue(pg, cur_op, op_data->oid, op_data->errcode);
return; return;
} }
} }
pg.ver_override.erase(op_data->oid);
deref_object_state(pg, &op_data->object_state, true); deref_object_state(pg, &op_data->object_state, true);
pg_cancel_write_queue(pg, cur_op, op_data->oid, op_data->errcode); pg_cancel_write_queue(pg, cur_op, op_data->oid, op_data->errcode);
return; return;
} }
if (op_data->scheme != POOL_SCHEME_REPLICATED)
{
// Remove version override just after the write, but before stabilizing
pg.ver_override.erase(op_data->oid);
}
if (op_data->object_state) if (op_data->object_state)
{ {
// We must forget the unclean state of the object before deleting it // We must forget the unclean state of the object before deleting it