diff --git a/src/libpmemobj/memops.c b/src/libpmemobj/memops.c index 23153df24efd2c4a0a12ddc66bb49573ff24548b..fd5e7b5c013d542a725968f2a139092d86e98fcd 100644 --- a/src/libpmemobj/memops.c +++ b/src/libpmemobj/memops.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2019, Intel Corporation + * Copyright 2016-2020, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -430,6 +430,7 @@ operation_process_persistent_redo(struct operation_context *ctx) ulog_store(ctx->ulog, ctx->pshadow_ops.ulog, ctx->pshadow_ops.offset, ctx->ulog_base_nbytes, + ctx->ulog_capacity, &ctx->next, ctx->p_ops); ulog_process(ctx->pshadow_ops.ulog, OBJ_OFF_IS_VALID_FROM_CTX, diff --git a/src/libpmemobj/ulog.c b/src/libpmemobj/ulog.c index 7f821f12d94ff27d8ab0f593957defb5e8bad49b..2331759a88d441a38747ff0f238d875a643931f2 100644 --- a/src/libpmemobj/ulog.c +++ b/src/libpmemobj/ulog.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2019, Intel Corporation + * Copyright 2015-2020, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -292,8 +292,8 @@ ulog_checksum(struct ulog *ulog, size_t ulog_base_bytes, int insert) */ void ulog_store(struct ulog *dest, struct ulog *src, size_t nbytes, - size_t ulog_base_nbytes, struct ulog_next *next, - const struct pmem_ops *p_ops) + size_t ulog_base_nbytes, size_t ulog_total_capacity, + struct ulog_next *next, const struct pmem_ops *p_ops) { /* * First, store all entries over the base capacity of the ulog in @@ -312,9 +312,16 @@ ulog_store(struct ulog *dest, struct ulog *src, size_t nbytes, * If the nbytes is aligned, an entire cacheline needs to be addtionally * zeroed. * But the checksum must be calculated based solely on actual data. + * If the ulog total capacity is equal to the size of the + * ulog being stored (nbytes == ulog_total_capacity), then there's + * nothing to invalidate because the entire log data will + * be overwritten. */ size_t checksum_nbytes = MIN(ulog_base_nbytes, nbytes); - nbytes = CACHELINE_ALIGN(nbytes + sizeof(struct ulog_entry_base)); + if (nbytes != ulog_total_capacity) + nbytes = CACHELINE_ALIGN(nbytes + + sizeof(struct ulog_entry_base)); + ASSERT(nbytes <= ulog_total_capacity); size_t base_nbytes = MIN(ulog_base_nbytes, nbytes); size_t next_nbytes = nbytes - base_nbytes; diff --git a/src/libpmemobj/ulog.h b/src/libpmemobj/ulog.h index 0287519310d7712b5e17d10c82d8cc4a328995bd..ef19a05fb932cc3822b3480d75317c710d80dea7 100644 --- a/src/libpmemobj/ulog.h +++ b/src/libpmemobj/ulog.h @@ -1,5 +1,5 @@ /* - * Copyright 2015-2018, Intel Corporation + * Copyright 2015-2020, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -126,6 +126,7 @@ int ulog_reserve(struct ulog *ulog, void ulog_store(struct ulog *dest, struct ulog *src, size_t nbytes, size_t ulog_base_nbytes, + size_t ulog_total_capacity, struct ulog_next *next, const struct pmem_ops *p_ops); void ulog_clobber(struct ulog *dest, struct ulog_next *next, diff --git a/src/test/obj_list/obj_list_mocks.c b/src/test/obj_list/obj_list_mocks.c index 1e224961e13b20f9adc9ba96b6f0b2de4c9d87c4..25a5373f6e8bf81a05b359b3bfb5e5691e7830b4 100644 --- a/src/test/obj_list/obj_list_mocks.c +++ b/src/test/obj_list/obj_list_mocks.c @@ -1,5 +1,5 @@ /* - * Copyright 2015-2018, Intel Corporation + * Copyright 2015-2020, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -353,12 +353,14 @@ FUNC_MOCK_END FUNC_MOCK(ulog_store, void, struct ulog *dest, struct ulog *src, size_t nbytes, size_t redo_base_nbytes, + size_t ulog_base_capacity, struct ulog_next *next, const struct pmem_ops *p_ops) FUNC_MOCK_RUN_DEFAULT { switch (Ulog_fail) { case FAIL_AFTER_FINISH: _FUNC_REAL(ulog_store)(dest, src, nbytes, redo_base_nbytes, + ulog_base_capacity, next, p_ops); DONEW(NULL); break; @@ -368,6 +370,7 @@ FUNC_MOCK(ulog_store, void, default: _FUNC_REAL(ulog_store)(dest, src, nbytes, redo_base_nbytes, + ulog_base_capacity, next, p_ops); break; } diff --git a/src/test/obj_memops/obj_memops.c b/src/test/obj_memops/obj_memops.c index 185f1e667d21a0cc434c40b5ba27de3d4169722c..3dc635d6250c572bebb679d25ea08e4af3c1760f 100644 --- a/src/test/obj_memops/obj_memops.c +++ b/src/test/obj_memops/obj_memops.c @@ -1,5 +1,5 @@ /* - * Copyright 2019, Intel Corporation + * Copyright 2018-2020, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -179,6 +179,15 @@ test_redo(PMEMobjpool *pop, struct test_object *object) (struct ulog *)&object->redo, TEST_ENTRIES, pmalloc_redo_extend, NULL, &pop->p_ops, LOG_TYPE_REDO); + /* + * Keep this test first. + * It tests a situation where the number of objects being added + * is equal to the capacity of the log. + */ + test_set_entries(pop, ctx, object, TEST_ENTRIES - 1, + FAIL_NONE, LOG_PERSISTENT); + clear_test_values(object); + test_set_entries(pop, ctx, object, 10, FAIL_NONE, LOG_PERSISTENT); clear_test_values(object); test_merge_op(ctx, object);