From 7f1f0b9048cc2c0dc1dbe792951af4a4c2ca50dc Mon Sep 17 00:00:00 2001 From: LoveSy Date: Tue, 22 Mar 2022 02:43:14 +0800 Subject: [PATCH] Proper support multiple modules adding same dir --- native/jni/core/module.cpp | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/native/jni/core/module.cpp b/native/jni/core/module.cpp index 6b3ae4fc4..ecc32f5ea 100644 --- a/native/jni/core/module.cpp +++ b/native/jni/core/module.cpp @@ -56,6 +56,8 @@ public: bool is_reg() { return file_type() == DT_REG; } uint8_t type() { return node_type; } const string &name() { return _name; } + + // Don't call the following two functions before prepare const string &node_path(); string mirror_path() { return mirror_dir + node_path(); } @@ -95,7 +97,7 @@ private: dir_node *_parent = nullptr; - // Cache + // Cache, it should only be used within prepare string _node_path; }; @@ -247,6 +249,7 @@ private: const char *module; }; +// Don't create the following two nodes before prepare class mirror_node : public node_entry { public: explicit mirror_node(dirent *entry) : node_entry(entry->d_name, entry->d_type, this) {} @@ -370,7 +373,7 @@ tmpfs_node::tmpfs_node(node_entry *node) : dir_node(node, this) { } else { // It is actually possible that mirror does not exist (nested mount points) // Set self to non exist so this node will be ignored at mount - set_exist(false); + // Keep it the same as `node` return; } @@ -402,16 +405,21 @@ bool dir_node::prepare() { if (should_be_tmpfs(it->second)) { if (node_type > type_id()) { // Upgrade will fail, remove the unsupported child node + LOGW("Unable to add: %s, skipped\n", it->second->node_path().data()); delete it->second; it = children.erase(it); continue; } // Tell parent to upgrade self to tmpfs to_tmpfs = true; - // If child is inter_node, upgrade to module - if (auto nit = upgrade(it); nit != children.end()) { - it = nit; - goto next_node; + // If child is inter_node and it does not (need to) exist, upgrade to module + if (auto dn = dyn_cast(it->second); dn) { + if (!dn->exist()) { + if (auto nit = upgrade(it); nit != children.end()) { + it = nit; + goto next_node; + } + } } } if (auto dn = dyn_cast(it->second); dn && dn->is_dir() && !dn->prepare()) { @@ -440,8 +448,10 @@ bool dir_node::collect_files(const char *module, int dfd) { if (auto it = children.find(entry->d_name); it == children.end()) { dn = emplace(entry->d_name, entry->d_name, module); } else { - dn = iterator_to_node(upgrade(it)); - dn->set_exist(true); + dn = dyn_cast(it->second); + // it has been accessed by at least two modules, it must be guarantee to exist + // set it so that it won't be upgrade to module_node but tmpfs_node + if (dn) dn->set_exist(true); } if (dn && !dn->collect_files(module, dirfd(dir.get()))) { upgrade(dn->name(), module); @@ -618,7 +628,6 @@ void magic_mount() { } } } - root->prepare(); root->mount(); }