From 7d67489b0c040c633a800e47f07911a867e24607 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Tue, 16 Mar 2021 11:52:18 -0700 Subject: [PATCH] Handle resent initial client greetings The very first greeting a client sends is unique becuase it doesn't yet have a server_term field set and tells the server to create items to track the client. A server processing this request can create the items and then shut down before the client is able to receive the reply. They'll resend the greeting without server_term but then the next server will get -EEXIST errors as it tries to create items for the client. This causes the connection to break, which the client tries to reestablish, and the pattern repeats indefinitely. The fix is to simply recognize that -EEXIST is acceptable during item creation. Server message handlers always have to address the case where a resent message was already processed by a previous server but it's response didn't make it to the client. Signed-off-by: Zach Brown --- kmod/src/lock_server.c | 6 +++++- kmod/src/server.c | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/kmod/src/lock_server.c b/kmod/src/lock_server.c index 036bfcc4..0e04ac66 100644 --- a/kmod/src/lock_server.c +++ b/kmod/src/lock_server.c @@ -586,7 +586,9 @@ static void init_lock_clients_key(struct scoutfs_key *key, u64 rid) * the client had already talked to the server then we must find an * existing record for it and should begin recovery. If it doesn't have * a record then its timed out and we can't allow it to reconnect. If - * its connecting for the first time then we insert a new record. If + * we're creating a new record for a client we can see EEXIST if the + * greeting is resent to a new server after the record was committed but + * before the response was received by the client. * * This is running in concurrent client greeting processing contexts. */ @@ -611,6 +613,8 @@ int scoutfs_lock_server_greeting(struct super_block *sb, u64 rid, ret = scoutfs_btree_insert(sb, inf->alloc, inf->wri, &super->lock_clients, &key, NULL, 0); + if (ret == -EEXIST) + ret = 0; } mutex_unlock(&inf->mutex); diff --git a/kmod/src/server.c b/kmod/src/server.c index d7d16870..ce7840bd 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -1024,6 +1024,12 @@ static void init_mounted_client_key(struct scoutfs_key *key, u64 rid) }; } +/* + * Insert a new mounted client item for a client that is sending us a + * greeting that hasn't yet seen a response. The greeting can be + * retransmitted to a new server after the previous inserted the item so + * it's acceptable to see -EEXIST. + */ static int insert_mounted_client(struct super_block *sb, u64 rid, u64 gr_flags) { @@ -1042,6 +1048,8 @@ static int insert_mounted_client(struct super_block *sb, u64 rid, ret = scoutfs_btree_insert(sb, &server->alloc, &server->wri, &super->mounted_clients, &key, &mcv, sizeof(mcv)); + if (ret == -EEXIST) + ret = 0; mutex_unlock(&server->mounted_clients_mutex); return ret;