From 8f46ca082653116c9c42a69e2535be1bb2f0a2a9 Mon Sep 17 00:00:00 2001 From: Marcio Barbosa Date: Wed, 21 Jun 2017 17:42:37 -0300 Subject: [PATCH] ubik: allow remote dbase relabel if up to date When a site is elected the sync-site, its database is not immediately relabeled. The database in question will be relabeled at the end of the first write transaction (in udisk_commit). To do so, the dbase->version is updated on the sync-site first (1) and then the versions of the remote sites are updated through SDISK_SetVersion() (2). In order to make sure that the remote site holds the same database as the sync-site, the SDISK_SetVersion() function checks if the current version held by the remote site (ubik_dbVersion) is equal to the original version stored by the sync-site (oldversionp). If ubik_dbVersion is not equal to oldversionp, SDISK_SetVersion() will fail with USYNC. However, ubik_dbVersion can be updated by the vote thread at any time. That is, if the sync site calls VOTE_Beacon() on the remote site between events (1) and (2), the remote site will set ubik_dbVersion to the new version, while ubik_dbase->version is still set to the old version. As a result, ubik_dbVersion will not be equal to oldversionp and SDISK_SetVersion() will fail with USYNC. This failure may cause a loss of quorum until another election is completed. To fix this problem, let SDISK_SetVersion() relabel the database when ubik_dbase->version is equal to oldversionp. In order to try to only affect the scenario described above, also check if ubik_dbVersion is equal to newversionp. Change-Id: I97e6f8cacd1c9bca0b4c72374c058c5fe5b638b3 Reviewed-on: https://gerrit.openafs.org/12613 Tested-by: BuildBot Reviewed-by: Benjamin Kaduk --- src/ubik/remote.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/ubik/remote.c b/src/ubik/remote.c index fe6ea2d3c..1c5a6afb5 100644 --- a/src/ubik/remote.c +++ b/src/ubik/remote.c @@ -742,8 +742,14 @@ SDISK_SetVersion(struct rx_call *rxcall, struct ubik_tid *atid, goto done; } - /* Set the label if its version matches the sync-site's */ - if (uvote_eq_dbVersion(*oldversionp)) { + /* Set the label if our version matches the sync-site's. Also set the label + * if our on-disk version matches the old version, and our view of the + * sync-site's version matches the new version. This suggests that + * ubik_dbVersion was updated while the sync-site was setting the new + * version, and it already told us via VOTE_Beacon. */ + if (uvote_eq_dbVersion(*oldversionp) + || (uvote_eq_dbVersion(*newversionp) + && vcmp(ubik_dbase->version, *oldversionp) == 0)) { UBIK_VERSION_LOCK; code = (*ubik_dbase->setlabel) (ubik_dbase, 0, newversionp); if (!code) { -- 2.39.5