-
Notifications
You must be signed in to change notification settings - Fork 509
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
obj: ensure zones are reclaimed prior to free
This patch fixes a bug where free prior to any allocs, combined with reservations, could have led to overlapping allocations - which ultimately was causing corrupted heap and incorrect statistics. This problem is caused by lazy heap runtime state reclamation. Heap runtime state is rebuilt lazily whenever required to serve allocation requests. Deallocations (free) simply update persistent metadata and, in case of huge allocations, inserts the freed chunk into a container of free chunks. On reclaim, all free chunks not already deallocated are inserted into a freelist. This would have been fine, but libpmemobj's allocator enables software to reserve a chunk, removing it from the heap runtime state without updating the persistent on-media layout. This means that software can deallocate a chunk, reserve that same chunk, allocate something normally - triggering heap zone reclamation, and then it can finally publish (actually persistently allocate) that reserved chunk. This can lead to the same chunk being potentially allocated twice... This patch fixes this problem by ensuring that object's zone is fully processed and reclaimed prior to deallocation. Reported-by: @jolivier23
- Loading branch information
Showing
11 changed files
with
297 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
obj_heap_reopen |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# SPDX-License-Identifier: BSD-3-Clause | ||
# Copyright 2022, Intel Corporation | ||
|
||
# | ||
# src/test/obj_heap_reopen/Makefile -- build obj_heap_reopen test | ||
# | ||
TARGET = obj_heap_reopen | ||
OBJS = obj_heap_reopen.o | ||
|
||
LIBPMEMOBJ=y | ||
|
||
include ../Makefile.inc | ||
INCS += -I../../libpmemobj |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
#!../env.py | ||
# SPDX-License-Identifier: BSD-3-Clause | ||
# Copyright 2022, Intel Corporation | ||
|
||
|
||
import testframework as t | ||
from testframework import granularity as g | ||
|
||
|
||
class BASIC(t.Test): | ||
test_type = t.Medium | ||
|
||
def run(self, ctx): | ||
filepath = ctx.create_holey_file(16 * t.MiB, 'testfile1') | ||
ctx.exec('obj_heap_reopen', filepath) | ||
|
||
|
||
@g.require_granularity(g.BYTE, g.CACHELINE) | ||
class TEST0(BASIC): | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// SPDX-License-Identifier: BSD-3-Clause | ||
/* Copyright 2022, Intel Corporation */ | ||
|
||
/* | ||
* obj_heap_reopen.c -- test for reopening an existing heap and deallocating | ||
* objects prior to any allocations to validate the memory reclamation process. | ||
*/ | ||
|
||
#include <stddef.h> | ||
|
||
#include "libpmemobj/action_base.h" | ||
#include "libpmemobj/atomic_base.h" | ||
#include "out.h" | ||
#include "unittest.h" | ||
#include "obj.h" | ||
|
||
#define TEST_OBJECT_SIZE (4 << 20) | ||
|
||
int | ||
main(int argc, char *argv[]) | ||
{ | ||
START(argc, argv, "obj_heap_reopen"); | ||
|
||
if (argc < 2) | ||
UT_FATAL("usage: %s file-name", argv[0]); | ||
|
||
const char *path = argv[1]; | ||
PMEMobjpool *pop = NULL; | ||
|
||
if ((pop = pmemobj_create(path, POBJ_LAYOUT_NAME(basic), | ||
0, S_IWUSR | S_IRUSR)) == NULL) | ||
UT_FATAL("!pmemobj_create: %s", path); | ||
|
||
PMEMoid oid; | ||
pmemobj_alloc(pop, &oid, 4 << 20, 0, NULL, NULL); | ||
|
||
pmemobj_close(pop); | ||
|
||
if ((pop = pmemobj_open(path, POBJ_LAYOUT_NAME(basic))) == NULL) | ||
UT_FATAL("!pmemobj_open: %s", path); | ||
|
||
uint64_t freed_oid_off = oid.off; | ||
pmemobj_free(&oid); | ||
|
||
struct pobj_action act; | ||
oid = pmemobj_reserve(pop, &act, TEST_OBJECT_SIZE, 0); | ||
UT_ASSERTeq(oid.off, freed_oid_off); | ||
|
||
for (;;) { | ||
PMEMoid oid2; | ||
if (pmemobj_alloc(pop, &oid2, 1, 0, NULL, NULL) != 0) | ||
break; | ||
UT_ASSERT(!(oid2.off >= oid.off && | ||
oid2.off <= oid.off + TEST_OBJECT_SIZE)); | ||
} | ||
|
||
pmemobj_publish(pop, &act, 1); | ||
|
||
pmemobj_close(pop); | ||
|
||
DONE(NULL); | ||
} |
Oops, something went wrong.