pdr: Handle removal of the last contained entity from EA PDR
After removing the contained entity from the entity association
PDR, if there is no other contained entity present, we need to
remove the entity association PDR.
Also modified the testcase to delete all the entities from the entity
association PDR.
Fixes: b31e4c6c4663 ("pdr: Remove contained entity from PDR repo")
Change-Id: If426314a571e91d178e8ae802a49bb7a3746080e
Signed-off-by: Archana Kakani <archana.kakani@ibm.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index af2ec0d..0e04e0e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -69,6 +69,7 @@
1. dsp: platform: Fix location of closing paren in overflow detection
2. libpldm: Install api header, update changelog
+3. pdr: Remove PDR if the contained entity to be removed is the last one
## [0.10.0] 2024-11-01
diff --git a/src/dsp/pdr.c b/src/dsp/pdr.c
index 0ef1686..142c4f7 100644
--- a/src/dsp/pdr.c
+++ b/src/dsp/pdr.c
@@ -35,6 +35,14 @@
} pldm_pdr;
LIBPLDM_CC_NONNULL
+static pldm_pdr_record *pldm_pdr_get_prev_record(pldm_pdr *repo,
+ pldm_pdr_record *record);
+
+LIBPLDM_CC_NONNULL_ARGS(1, 2)
+static int pldm_pdr_remove_record(pldm_pdr *repo, pldm_pdr_record *record,
+ pldm_pdr_record *prev);
+
+LIBPLDM_CC_NONNULL
static inline uint32_t get_next_record_handle(const pldm_pdr *repo,
const pldm_pdr_record *record)
{
@@ -1852,8 +1860,9 @@
// Initialize new PDR record with data from original PDR record.
// Start with adding the header of original PDR
- rc = pldm_msgbuf_init_errno(dst, PDR_ENTITY_ASSOCIATION_MIN_SIZE,
- new_record->data, new_record->size);
+ rc = pldm_msgbuf_init_errno(
+ dst, (PDR_ENTITY_ASSOCIATION_MIN_SIZE - sizeof(pldm_entity)),
+ new_record->data, new_record->size);
if (rc) {
goto cleanup_new_record_data;
}
@@ -1885,9 +1894,9 @@
goto cleanup_new_record_data;
}
if (num_children == 1) {
- prev->next = record->next;
- free(record->data);
- free(record);
+ // This is the last child which is getting removed so we need to delete the Entity Association PDR.
+ pldm_pdr_remove_record(repo, record,
+ pldm_pdr_get_prev_record(repo, record));
goto cleanup_new_record_data;
} else if (num_children < 1) {
rc = -EOVERFLOW;
diff --git a/tests/dsp/pdr.cpp b/tests/dsp/pdr.cpp
index 30ea9ea..2ca79b7 100644
--- a/tests/dsp/pdr.cpp
+++ b/tests/dsp/pdr.cpp
@@ -1,6 +1,7 @@
#include <endian.h>
#include <libpldm/pdr.h>
#include <libpldm/platform.h>
+#include <msgbuf.h>
#include <array>
#include <cstdint>
@@ -2102,15 +2103,34 @@
EXPECT_EQ(pldm_pdr_get_record_count(repo), 1u);
+ // Remove first contained entity from the entity association PDR
uint32_t removed_record_handle{};
struct pldm_entity entity[1] = {
- {.entity_type = 2, .entity_instance_num = 1, .entity_container_id = 2}};
+ {.entity_type = 4, .entity_instance_num = 1, .entity_container_id = 2}};
EXPECT_EQ(pldm_entity_association_pdr_remove_contained_entity(
repo, entity, false, &removed_record_handle),
0);
EXPECT_EQ(removed_record_handle, 3);
+ // Remove second contained entity from the entity association PDR
+ removed_record_handle = 0;
+ EXPECT_EQ(pldm_entity_association_pdr_remove_contained_entity(
+ repo, &entities[1], false, &removed_record_handle),
+ 0);
+ EXPECT_EQ(removed_record_handle, 3);
+
+ // Remove third contained entity from the entity association PDR
+ removed_record_handle = 0;
+ EXPECT_EQ(pldm_entity_association_pdr_remove_contained_entity(
+ repo, &entities[2], false, &removed_record_handle),
+ 0);
+ EXPECT_EQ(removed_record_handle, 3);
+
+ // As all the contained entities are removed the entity association PDR
+ // also gets deleted
+ EXPECT_EQ(pldm_pdr_get_record_count(repo), 0u);
+
pldm_pdr_destroy(repo);
pldm_entity_association_tree_destroy(tree);
}