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