1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <fstream>
17 #include <string>
18 
19 #include "xml_helper.h"
20 #include "memmgr_config_manager.h"
21 
22 namespace OHOS {
23 namespace Memory {
24 namespace {
25     const std::string TAG = "MemmgrConfigManager";
26     const std::string XML_PATH = "/etc/memmgr/";
27     const std::string MEMCG_PATH = KernelInterface::MEMCG_BASE_PATH;
28 } // namespace
29 IMPLEMENT_SINGLE_INSTANCE(MemmgrConfigManager);
30 
Init()31 bool MemmgrConfigManager::Init()
32 {
33     killConfig_.ClearKillLevelsMap();
34     ReadParamFromXml();
35     WriteReclaimRatiosConfigToKernel();
36     return this->xmlLoaded_;
37 }
38 
MemmgrConfigManager()39 MemmgrConfigManager::MemmgrConfigManager()
40 {
41     InitDefaultConfig();
42 }
43 
~MemmgrConfigManager()44 MemmgrConfigManager::~MemmgrConfigManager()
45 {
46     ClearReclaimConfigSet();
47     killConfig_.ClearKillLevelsMap();
48 }
49 
InitDefaultConfig()50 void MemmgrConfigManager::InitDefaultConfig()
51 {
52     availBufferConfig_.SetDefaultConfig(AVAIL_BUFFER, MIN_AVAIL_BUFFER, HIGH_AVAIL_BUFFER, SWAP_RESERVE);
53     reclaimConfig_.SetDefaultConfig(RECLAIM_PRIORITY_MIN, RECLAIM_PRIORITY_MAX,
54                                     MEMCG_MEM_2_ZRAM_RATIO, MEMCG_ZRAM_2_UFS_RATIO, MEMCG_REFAULT_THRESHOLD);
55 }
56 
GetXmlLoaded()57 bool MemmgrConfigManager::GetXmlLoaded()
58 {
59     return xmlLoaded_;
60 }
61 
ClearExistConfig()62 void MemmgrConfigManager::ClearExistConfig()
63 {
64     ClearReclaimConfigSet();
65 }
66 
ReadParamFromXml()67 bool MemmgrConfigManager::ReadParamFromXml()
68 {
69     std::string path = KernelInterface::GetInstance().JoinPath(XML_PATH, "memmgr_config.xml");
70     char absPatch[PATH_MAX] = {0};
71     HILOGI(":%{public}s", path.c_str());
72     if (path.length() > PATH_MAX || realpath(path.c_str(), absPatch) == NULL) {
73             return false;
74     }
75     if (!XmlHelper::CheckPathExist(path.c_str())) {
76         HILOGE("bad profile path! path:%{public}s", path.c_str());
77         return false;
78     }
79     std::unique_ptr<xmlDoc, decltype(&xmlFreeDoc)> docPtr(
80         xmlReadFile(path.c_str(), nullptr, XML_PARSE_NOBLANKS), xmlFreeDoc);
81     if (docPtr == nullptr) {
82         HILOGE("xmlReadFile error!");
83         return false;
84     }
85     ClearExistConfig();
86     xmlNodePtr rootNodePtr = xmlDocGetRootElement(docPtr.get());
87     this->xmlLoaded_ = ParseXmlRootNode(rootNodePtr);
88     return this->xmlLoaded_;
89 }
90 
ParseXmlRootNode(const xmlNodePtr & rootNodePtr)91 bool MemmgrConfigManager::ParseXmlRootNode(const xmlNodePtr &rootNodePtr)
92 {
93     for (xmlNodePtr currNode = rootNodePtr->xmlChildrenNode; currNode != nullptr; currNode = currNode->next) {
94         std::string name = std::string(reinterpret_cast<const char *>(currNode->name));
95         if (name.compare("availBufferConfig") == 0) {
96             availBufferConfig_.ParseConfig(currNode);
97             continue;
98         }
99 
100         if (name.compare("reclaimConfig") == 0) {
101             reclaimConfig_.ParseConfig(currNode);
102             continue;
103         }
104 
105         if (name.compare("killConfig") == 0) {
106             killConfig_.ParseConfig(currNode);
107             continue;
108         }
109         if (name.compare("systemMemoryLevelConfig") == 0) {
110             systemMemoryLevelConfig_.ParseConfig(currNode);
111             continue;
112         }
113         if (name.compare("reclaimPriorityConfig") == 0) {
114             reclaimPriorityConfig_.ParseConfig(currNode);
115             continue;
116         }
117         if (name.compare("nandLifeConfig") == 0) {
118             nandLifeConfig_.ParseConfig(currNode);
119             continue;
120         }
121         if (name.compare("switchConfig") == 0) {
122             switchConfig_.ParseConfig(currNode);
123             continue;
124         }
125         if (name.compare("purgeablememConfig") == 0) {
126             purgeablememConfig_.ParseConfig(currNode);
127             continue;
128         }
129         HILOGW("unknown node :<%{public}s>", name.c_str());
130         return false;
131     }
132     return true;
133 }
134 
ClearReclaimConfigSet()135 void MemmgrConfigManager::ClearReclaimConfigSet()
136 {
137     reclaimConfig_.ClearReclaimConfigSet();
138 }
139 
GetNandLifeConfig()140 const NandLifeConfig &MemmgrConfigManager::GetNandLifeConfig()
141 {
142     return nandLifeConfig_;
143 }
144 
GetSwitchConfig()145 const SwitchConfig &MemmgrConfigManager::GetSwitchConfig()
146 {
147     return switchConfig_;
148 }
149 
GetReclaimPriorityConfig()150 const ReclaimPriorityConfig& MemmgrConfigManager::GetReclaimPriorityConfig()
151 {
152     return reclaimPriorityConfig_;
153 }
154 
GetKillLevelsMap()155 const KillConfig::KillLevelsMap& MemmgrConfigManager::GetKillLevelsMap()
156 {
157     return killConfig_.GetKillLevelsMap();
158 }
159 
WriteReclaimRatiosConfigToKernel()160 bool MemmgrConfigManager::WriteReclaimRatiosConfigToKernel()
161 {
162     std::string path = KernelInterface::GetInstance().JoinPath(MEMCG_PATH, "memory.zswapd_memcgs_param");
163     std::string content;
164 
165     unsigned int paramNum = reclaimConfig_.GetReclaimConfigSet().size();
166     content = std::to_string(paramNum);
167     for (auto i = reclaimConfig_.GetReclaimConfigSet().begin(); i != reclaimConfig_.GetReclaimConfigSet().end(); ++i) {
168         content += " " + std::to_string((*i)->GetMinScore());
169         content += " " + std::to_string((*i)->GetMaxScore());
170         content += " " + std::to_string((*i)->GetMem2zramRatio());
171         content += " " + std::to_string((*i)->GetZram2ufsRatio());
172         content += " " + std::to_string((*i)->GetRefaultThreshold());
173     }
174 
175     HILOGI("Write to kernel: <%{public}s>", content.c_str());
176     return KernelInterface::GetInstance().WriteToFile(path, content);
177 }
178 
GetAvailBufferConfig()179 AvailBufferConfig MemmgrConfigManager::GetAvailBufferConfig()
180 {
181     return availBufferConfig_;
182 }
183 
GetReclaimConfigSet()184 const ReclaimConfig::ReclaimConfigSet& MemmgrConfigManager::GetReclaimConfigSet()
185 {
186     return reclaimConfig_.GetReclaimConfigSet();
187 }
188 
GetKillConfig()189 const KillConfig& MemmgrConfigManager::GetKillConfig()
190 {
191     return killConfig_;
192 }
193 
GetSystemMemoryLevelConfig()194 SystemMemoryLevelConfig MemmgrConfigManager::GetSystemMemoryLevelConfig()
195 {
196     return systemMemoryLevelConfig_;
197 }
198 
GetPurgeablememConfig()199 const PurgeablememConfig& MemmgrConfigManager::GetPurgeablememConfig()
200 {
201     return purgeablememConfig_;
202 }
203 
Dump(int fd)204 void MemmgrConfigManager::Dump(int fd)
205 {
206     availBufferConfig_.Dump(fd);
207     killConfig_.Dump(fd);
208     reclaimConfig_.Dump(fd);
209     nandLifeConfig_.Dump(fd);
210     systemMemoryLevelConfig_.Dump(fd);
211     switchConfig_.Dump(fd);
212     reclaimPriorityConfig_.Dump(fd);
213     purgeablememConfig_.Dump(fd);
214 }
215 } // namespace Memory
216 } // namespace OHOS
217