- update_rec_t *next = update->next;
- if (next != NULL) {
- uint64_t min_active_version = (uint64_t)sl_min_key(active_);
- if (next->version < min_active_version) {
- next = SYNC_SWAP(&update->next, NULL);
- while (next != NULL) {
- update = next;
- next = NULL;
- if (update->next != NULL) {
- next = SYNC_SWAP(&update->next, NULL);
- }
- nbd_free(update);
+ version_t min_active_version = UNDETERMINED_VERSION;
+ update_t *next_update = NULL;
+ if (IS_TAGGED(update->next, TAG2)) {
+ next_update = VAL_TO_PTR(update->next);
+
+ // If <next_update> (and all update records following it [execpt if it is aborted]) is old enough
+ // that it is not visible to any active transaction we can safely free it.
+ min_active_version = (version_t)sl_min_key(active_);
+ if (next_update->version < min_active_version) {
+
+ // If the <next_update> is aborted, skip over it to look for more recent ones that may follow
+ update_t *temp = next_update;
+ while (temp->version == ABORTED_VERSION) {
+ assert(!IS_TAGGED(temp->version, TAG1));
+ map_val_t next = temp->next;
+ if (!IS_TAGGED(next, TAG2))
+ break;
+
+ // Bail out of garbage collection if we find a record that might still be accessed by an
+ // ongoing transaction.
+ if (VAL_TO_PTR(next)->version >= min_active_version)
+ return value;
+
+ temp = VAL_TO_PTR(next);