if (entry->list) {
if (entry->list->unique && entry->name)
- hashmap_remove(entry->list->unique_entries, entry->name);
+ hashmap_remove_value(entry->list->unique_entries, entry->name, entry);
if (!entry->list->unique || entry->list->uptodate)
LIST_REMOVE(entries, entry->list->entries, entry);
return NULL;
if (list->unique) {
- udev_list_entry_free(hashmap_get(list->unique_entries, entry->name));
+ struct udev_list_entry *old;
- if (hashmap_ensure_put(&list->unique_entries, &udev_list_entry_hash_ops, entry->name, entry) < 0)
+ /* Replace the entry for an already known name in a single step. hashmap_replace() reuses the
+ * existing bucket and hence never allocates, so an existing entry is never dropped, not even
+ * under memory pressure. Allocating may only fail when adding a genuinely new name, in which
+ * case there is nothing to lose. */
+ old = hashmap_get(list->unique_entries, entry->name);
+
+ if (hashmap_ensure_replace(&list->unique_entries, &udev_list_entry_hash_ops, entry->name, entry) < 0)
return NULL;
+ udev_list_entry_free(old);
+
list->uptodate = false;
} else
LIST_APPEND(entries, list->entries, entry);