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);