From a62da4eeed042e0ec5c2de0aa4e33b3dd98fc359 Mon Sep 17 00:00:00 2001 From: Vladislav Shpilevoy <v.shpilevoy@tarantool.org> Date: Tue, 9 Jul 2024 22:19:56 +0200 Subject: [PATCH] box: make instance_vclock const No code besides box.cc can now update instance's vclock explicitly. That is a protection against hacks like #9916. Closes #10113 NO_DOC=refactoring NO_TEST=refactoring NO_CHANGELOG=refactoring (cherry picked from commit 19b2cc20df269e31026041c247319aaacf3dd4ff) --- src/box/applier.cc | 8 ++++++-- src/box/box.cc | 17 +++++++++++++++-- src/box/box.h | 14 +++++++++++++- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/box/applier.cc b/src/box/applier.cc index 0e621f6f89..0d0c3c54e1 100644 --- a/src/box/applier.cc +++ b/src/box/applier.cc @@ -788,7 +788,9 @@ applier_wait_snapshot(struct applier *applier) * Used to initialize the replica's initial * vclock in bootstrap_from_master() */ - xrow_decode_vclock_xc(&row, instance_vclock); + struct vclock vclock; + xrow_decode_vclock_xc(&row, &vclock); + box_init_instance_vclock(&vclock); } coio_read_xrow(io, ibuf, &row); @@ -844,7 +846,9 @@ applier_wait_snapshot(struct applier *applier) * vclock yet, do it now. In 1.7+ * this vclock is not used. */ - xrow_decode_vclock_xc(&row, instance_vclock); + struct vclock vclock; + xrow_decode_vclock_xc(&row, &vclock); + box_init_instance_vclock(&vclock); } break; /* end of stream */ } else if (iproto_type_is_error(row.type)) { diff --git a/src/box/box.cc b/src/box/box.cc index 3e09ddcf24..9e3c5c098f 100644 --- a/src/box/box.cc +++ b/src/box/box.cc @@ -119,7 +119,7 @@ struct rlist box_on_shutdown_trigger_list = RLIST_HEAD_INITIALIZER(box_on_shutdown_trigger_list); const struct vclock *box_vclock = instance_vclock; -struct vclock *instance_vclock = &instance_vclock_storage; +const struct vclock *instance_vclock = &instance_vclock_storage; const char *box_auth_type; @@ -4571,7 +4571,12 @@ bootstrap_from_master(struct replica *master) return false; } assert(applier->state == APPLIER_READY); - + /* + * In case of rejoin the vclock could be already set to send it in the + * ballot and for other global things. Make it unset again so the + * applier could "init" it again. + */ + vclock_clear(&instance_vclock_storage); say_info("bootstrapping replica from %s at %s", tt_uuid_str(&master->uuid), sio_strfaddr(&applier->addr, applier->addr_len)); @@ -5530,6 +5535,14 @@ box_init(void) sizeof(struct sync_trigger_data)); } +void +box_init_instance_vclock(const struct vclock *vclock) +{ + if (vclock_is_set(&instance_vclock_storage)) + panic("Instance vclock can be initialized only once"); + vclock_copy(&instance_vclock_storage, vclock); +} + void box_free(void) { diff --git a/src/box/box.h b/src/box/box.h index 9cea1360c8..28825e3877 100644 --- a/src/box/box.h +++ b/src/box/box.h @@ -68,7 +68,7 @@ extern const struct vclock *box_vclock; * recovery this vclock points to the end of WAL, not to the current recovery * position. */ -extern struct vclock *instance_vclock; +extern const struct vclock *instance_vclock; /** * Name of the authentication method that is currently used on @@ -106,6 +106,18 @@ extern bool box_is_force_recovery; void box_init(void); +/** + * Set instance's vclock to the given value. Works only if the instance vclock + * isn't already set. It must be initialized manually and explicitly this way + * when the instance boots from a snapshot - snapshot rows have no LSNs, so + * setting the instance vclock manually is the only way. + * + * It has to be a "public" API of box, because the snapshot can be remote, i.e. + * coming from the applier. + */ +void +box_init_instance_vclock(const struct vclock *vclock); + /** * Cleanup box library */ -- GitLab