From 7f18616cc05b872da34b63d1c1ffe44d4b4731a9 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sat, 9 Oct 2021 02:15:03 -0700 Subject: [PATCH] Prune unused nodes from trie --- .../include/_system_properties.h | 2 +- .../include/system_properties/prop_area.h | 5 +- .../system_properties/system_properties.h | 2 +- .../external/systemproperties/prop_area.cpp | 48 ++++++++++++++++--- .../systemproperties/system_properties.cpp | 4 +- .../systemproperties/system_property_api.cpp | 4 +- native/jni/resetprop/resetprop.cpp | 4 +- 7 files changed, 54 insertions(+), 15 deletions(-) diff --git a/native/jni/external/systemproperties/include/_system_properties.h b/native/jni/external/systemproperties/include/_system_properties.h index 1cdf77132..0dc50363e 100644 --- a/native/jni/external/systemproperties/include/_system_properties.h +++ b/native/jni/external/systemproperties/include/_system_properties.h @@ -109,7 +109,7 @@ int __system_property_add(const char* __name, unsigned int __name_length, const ** ** Returns 0 on success, -1 if the property area is full. */ -int __system_property_delete(const char *__name); +int __system_property_delete(const char *__name, bool __trim_node); /* Update the value of a system property returned by ** __system_property_find. Can only be done by a single process diff --git a/native/jni/external/systemproperties/include/system_properties/prop_area.h b/native/jni/external/systemproperties/include/system_properties/prop_area.h index b1b50b5b4..3b1374f17 100644 --- a/native/jni/external/systemproperties/include/system_properties/prop_area.h +++ b/native/jni/external/systemproperties/include/system_properties/prop_area.h @@ -110,7 +110,7 @@ class prop_area { const prop_info* find(const char* name); bool add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen); - bool rm(const char *name); + bool rm(const char *name, bool trim_node); bool foreach (void (*propfn)(const prop_info* pi, void* cookie), void* cookie); @@ -140,6 +140,9 @@ class prop_area { /* resetprop new: traverse through the trie and find the node */ prop_bt *find_prop_bt(prop_bt *const bt, const char* name, bool alloc_if_needed); + /* resetprop new: trim unneeded nodes from trie */ + bool prune_node(prop_bt *const node); + prop_bt* find_prop_bt(prop_bt* const bt, const char* name, uint32_t namelen, bool alloc_if_needed); const prop_info* find_property(prop_bt* const trie, const char* name, uint32_t namelen, diff --git a/native/jni/external/systemproperties/include/system_properties/system_properties.h b/native/jni/external/systemproperties/include/system_properties/system_properties.h index 8182ebf83..a5324e4e9 100644 --- a/native/jni/external/systemproperties/include/system_properties/system_properties.h +++ b/native/jni/external/systemproperties/include/system_properties/system_properties.h @@ -67,7 +67,7 @@ class SystemProperties { int Get(const char* name, char* value); int Update(prop_info* pi, const char* value, unsigned int len); int Add(const char* name, unsigned int namelen, const char* value, unsigned int valuelen); - int Delete(const char *name); + int Delete(const char *name, bool trim_node); uint32_t Serial(const prop_info* pi); uint32_t WaitAny(uint32_t old_serial); bool Wait(const prop_info* pi, uint32_t old_serial, uint32_t* new_serial_ptr, diff --git a/native/jni/external/systemproperties/prop_area.cpp b/native/jni/external/systemproperties/prop_area.cpp index 1ee8794f2..77722bb08 100644 --- a/native/jni/external/systemproperties/prop_area.cpp +++ b/native/jni/external/systemproperties/prop_area.cpp @@ -380,7 +380,40 @@ bool prop_area::add(const char* name, unsigned int namelen, const char* value, return find_property(root_node(), name, namelen, value, valuelen, true); } -bool prop_area::rm(const char *name) { +bool prop_area::prune_node(prop_bt * const node) { + bool is_leaf = true; + if (atomic_load_explicit(&node->children, memory_order_relaxed) != 0) { + if (prune_node(to_prop_bt(&node->children))) { + atomic_store_explicit(&node->children, 0, memory_order_release); + } else { + is_leaf = false; + } + } + if (atomic_load_explicit(&node->left, memory_order_relaxed) != 0) { + if (prune_node(to_prop_bt(&node->left))) { + atomic_store_explicit(&node->left, 0, memory_order_release); + } else { + is_leaf = false; + } + } + if (atomic_load_explicit(&node->right, memory_order_relaxed) != 0) { + if (prune_node(to_prop_bt(&node->right))) { + atomic_store_explicit(&node->right, 0, memory_order_release); + } else { + is_leaf = false; + } + } + + if (is_leaf && atomic_load_explicit(&node->prop, memory_order_relaxed) == 0) { + // Wipe out this node + memset(node->name, 0, node->namelen); + memset(node, 0, sizeof(*node)); + return true; + } + return false; +} + +bool prop_area::rm(const char *name, bool trim_node) { prop_bt *node = find_prop_bt(root_node(), name, false); if (!node) return false; @@ -392,19 +425,22 @@ bool prop_area::rm(const char *name) { } // De-reference the existing property ASAP - uint_least32_t new_offset = 0; - atomic_store_explicit(&node->prop, new_offset, memory_order_release); + atomic_store_explicit(&node->prop, 0, memory_order_release); if (info) { - // Directly wipe out the old info + // Wipe out the old info if (info->is_long()) { char *value = const_cast(info->long_value()); - auto len = strlen(value); - memset(value, 0, len); + memset(value, 0, strlen(value)); } + memset(info->name, 0, strlen(info->name)); memset(info, 0, sizeof(*info)); } + if (trim_node) { + prune_node(root_node()); + } + return true; } diff --git a/native/jni/external/systemproperties/system_properties.cpp b/native/jni/external/systemproperties/system_properties.cpp index df39831bb..2f111e62e 100644 --- a/native/jni/external/systemproperties/system_properties.cpp +++ b/native/jni/external/systemproperties/system_properties.cpp @@ -295,7 +295,7 @@ int SystemProperties::Add(const char* name, unsigned int namelen, const char* va return 0; } -int SystemProperties::Delete(const char *name) { +int SystemProperties::Delete(const char *name, bool trim_node) { if (!initialized_) { return -1; } @@ -311,7 +311,7 @@ int SystemProperties::Delete(const char *name) { return -1; } - bool ret = pa->rm(name); + bool ret = pa->rm(name, trim_node); if (!ret) { return -1; } diff --git a/native/jni/external/systemproperties/system_property_api.cpp b/native/jni/external/systemproperties/system_property_api.cpp index 404b36646..a0ebdc38a 100644 --- a/native/jni/external/systemproperties/system_property_api.cpp +++ b/native/jni/external/systemproperties/system_property_api.cpp @@ -100,8 +100,8 @@ int __system_property_add(const char* name, unsigned int namelen, const char* va } __BIONIC_WEAK_FOR_NATIVE_BRIDGE -int __system_property_delete(const char* name) { - return system_properties.Delete(name); +int __system_property_delete(const char *name, bool trim_node) { + return system_properties.Delete(name, trim_node); } __BIONIC_WEAK_FOR_NATIVE_BRIDGE diff --git a/native/jni/resetprop/resetprop.cpp b/native/jni/resetprop/resetprop.cpp index 6ff53824a..31aa9bbe9 100644 --- a/native/jni/resetprop/resetprop.cpp +++ b/native/jni/resetprop/resetprop.cpp @@ -176,7 +176,7 @@ struct resetprop : public sysprop { // Always delete existing read-only properties, because they could be // long properties and cannot directly go through __system_property_update if (pi != nullptr && str_starts(name, "ro.")) { - delprop(name, false); + __system_property_delete(name, false /* Do NOT trim node */); pi = nullptr; } @@ -228,7 +228,7 @@ struct resetprop : public sysprop { return 1; LOGD("resetprop: delete prop [%s]\n", name); - int ret = __system_property_delete(name); + int ret = __system_property_delete(name, true); if (persist && str_starts(name, "persist.")) { if (persist_deleteprop(name)) ret = 0;