Handle allocation and I/O failures gracefully in simulation
Replace assert(0) with proper error handling for: - malloc failures in client write operations - binary_read failures during message parsing - WAL append failures in metadata server - Chunk server timeout (now drops unresponsive servers) This fixes crashes exposed by fault injection testing.
This commit is contained in:
+16
-11
@@ -1538,8 +1538,9 @@ static void process_event_for_write(ToastyFS *toasty,
|
|||||||
toasty->operations[opidx].num_chunks = num_all_hasehs;
|
toasty->operations[opidx].num_chunks = num_all_hasehs;
|
||||||
toasty->operations[opidx].num_hashes = num_hashes; // TODO: overflow
|
toasty->operations[opidx].num_hashes = num_hashes; // TODO: overflow
|
||||||
toasty->operations[opidx].hashes = malloc(num_hashes * sizeof(SHA256));
|
toasty->operations[opidx].hashes = malloc(num_hashes * sizeof(SHA256));
|
||||||
if (toasty->operations[opidx].hashes == NULL) {
|
if (toasty->operations[opidx].hashes == NULL && num_hashes > 0) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
toasty->operations[opidx].uploads = NULL;
|
toasty->operations[opidx].uploads = NULL;
|
||||||
@@ -1880,19 +1881,19 @@ static void process_event_for_write(ToastyFS *toasty,
|
|||||||
|
|
||||||
// version
|
// version
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint16_t))) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t type;
|
uint16_t type;
|
||||||
if (!binary_read(&reader, &type, sizeof(uint16_t))) {
|
if (!binary_read(&reader, &type, sizeof(uint16_t))) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// length
|
// length
|
||||||
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
if (!binary_read(&reader, NULL, sizeof(uint32_t))) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1909,13 +1910,13 @@ static void process_event_for_write(ToastyFS *toasty,
|
|||||||
|
|
||||||
SHA256 hash;
|
SHA256 hash;
|
||||||
if (!binary_read(&reader, &hash, sizeof(hash))) {
|
if (!binary_read(&reader, &hash, sizeof(hash))) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that there is nothing else to read
|
// Check that there is nothing else to read
|
||||||
if (binary_read(&reader, NULL, 1)) {
|
if (binary_read(&reader, NULL, 1)) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1961,8 +1962,9 @@ static void process_event_for_write(ToastyFS *toasty,
|
|||||||
|
|
||||||
int num_upload_results = toasty->operations[opidx].num_chunks;
|
int num_upload_results = toasty->operations[opidx].num_chunks;
|
||||||
ChunkUploadResult *upload_results = malloc(num_upload_results * sizeof(ChunkUploadResult));
|
ChunkUploadResult *upload_results = malloc(num_upload_results * sizeof(ChunkUploadResult));
|
||||||
if (upload_results == NULL) {
|
if (upload_results == NULL && num_upload_results > 0) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < num_upload_results; i++) {
|
for (int i = 0; i < num_upload_results; i++) {
|
||||||
@@ -2008,7 +2010,9 @@ static void process_event_for_write(ToastyFS *toasty,
|
|||||||
uint32_t flags = toasty->operations[opidx].flags;
|
uint32_t flags = toasty->operations[opidx].flags;
|
||||||
|
|
||||||
if (path.len > UINT16_MAX) {
|
if (path.len > UINT16_MAX) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
|
free(upload_results);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
uint16_t path_len = path.len;
|
uint16_t path_len = path.len;
|
||||||
uint64_t expect_gen = toasty->operations[opidx].expect_gen;
|
uint64_t expect_gen = toasty->operations[opidx].expect_gen;
|
||||||
@@ -2046,7 +2050,8 @@ static void process_event_for_write(ToastyFS *toasty,
|
|||||||
free(upload_results);
|
free(upload_results);
|
||||||
|
|
||||||
if (metadata_server_request_end(toasty, &writer, opidx, TAG_COMMIT_WRITE) < 0) {
|
if (metadata_server_request_end(toasty, &writer, opidx, TAG_COMMIT_WRITE) < 0) {
|
||||||
assert(0); // TODO
|
toasty->operations[opidx].result = (ToastyResult) { .type=TOASTY_RESULT_WRITE_ERROR, .user=toasty->operations[opidx].user };
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-8
@@ -185,7 +185,7 @@ process_client_create(MetadataServer *state, int conn_idx, ByteView msg)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (wal_append_create(&state->wal, path, is_dir, chunk_size) < 0) {
|
if (wal_append_create(&state->wal, path, is_dir, chunk_size) < 0) {
|
||||||
assert(0); // TODO
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t gen;
|
uint64_t gen;
|
||||||
@@ -253,7 +253,7 @@ process_client_delete(MetadataServer *state, int conn_idx, ByteView msg)
|
|||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (wal_append_delete(&state->wal, path, expect_gen) < 0) {
|
if (wal_append_delete(&state->wal, path, expect_gen) < 0) {
|
||||||
assert(0); // TODO
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: return unused hashes and add them to the ms_rem_list of holder chunk servers
|
// TODO: return unused hashes and add them to the ms_rem_list of holder chunk servers
|
||||||
@@ -659,7 +659,7 @@ process_client_write(MetadataServer *state, int conn_idx, ByteView msg)
|
|||||||
new_hashes[i] = results[i].hash;
|
new_hashes[i] = results[i].hash;
|
||||||
|
|
||||||
if (wal_append_write(&state->wal, path, offset, length, num_chunks, expect_gen, new_hashes) < 0) {
|
if (wal_append_write(&state->wal, path, offset, length, num_chunks, expect_gen, new_hashes) < 0) {
|
||||||
assert(0); // TODO
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract flag values
|
// Extract flag values
|
||||||
@@ -682,7 +682,7 @@ process_client_write(MetadataServer *state, int conn_idx, ByteView msg)
|
|||||||
|
|
||||||
// Log the creation in the WAL
|
// Log the creation in the WAL
|
||||||
if (wal_append_create(&state->wal, path, false, chunk_size) < 0) {
|
if (wal_append_create(&state->wal, path, false, chunk_size) < 0) {
|
||||||
assert(0); // TODO
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t create_gen;
|
uint64_t create_gen;
|
||||||
@@ -859,7 +859,7 @@ static int process_chunk_server_auth(MetadataServer *state,
|
|||||||
// of this chunk server. If we do, tell it.
|
// of this chunk server. If we do, tell it.
|
||||||
|
|
||||||
if (!message_writer_free(&writer)) {
|
if (!message_writer_free(&writer)) {
|
||||||
assert(0); // TODO
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -905,7 +905,7 @@ static int process_chunk_server_sync(MetadataServer *state,
|
|||||||
|
|
||||||
if (num_holders <= state->replication_factor) {
|
if (num_holders <= state->replication_factor) {
|
||||||
if (hash_set_insert(&chunk_server->ms_add_list, hash) < 0) {
|
if (hash_set_insert(&chunk_server->ms_add_list, hash) < 0) {
|
||||||
assert(0); // TODO
|
return -1;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1115,7 +1115,8 @@ int metadata_server_init(void *state_, int argc, char **argv,
|
|||||||
|
|
||||||
if (wal_open(&state->wal, &state->file_tree, wal_file, wal_limit) < 0) {
|
if (wal_open(&state->wal, &state->file_tree, wal_file, wal_limit) < 0) {
|
||||||
fprintf(stderr, "metadata server :: Couldn't setup WAL\n");
|
fprintf(stderr, "metadata server :: Couldn't setup WAL\n");
|
||||||
assert(0); // TODO
|
tcp_context_free(&state->tcp);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Metadata server set up (local=%.*s:%d)\n",
|
printf("Metadata server set up (local=%.*s:%d)\n",
|
||||||
@@ -1251,7 +1252,9 @@ int metadata_server_tick(void *state_, void **ctxs,
|
|||||||
|
|
||||||
Time response_timeout = chunk_server->last_response_time + (Time) RESPONSE_TIME_LIMIT * 1000000000;
|
Time response_timeout = chunk_server->last_response_time + (Time) RESPONSE_TIME_LIMIT * 1000000000;
|
||||||
if (current_time > response_timeout) {
|
if (current_time > response_timeout) {
|
||||||
assert(0); // TODO: drop the chunk server
|
// Drop unresponsive chunk server
|
||||||
|
chunk_server->used = false;
|
||||||
|
state->num_chunk_servers--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
nearest_deadline(&next_wakeup, response_timeout);
|
nearest_deadline(&next_wakeup, response_timeout);
|
||||||
|
|||||||
Reference in New Issue
Block a user