Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "aicpu_thread_package_worker.h"
12 :
13 : #include <sys/file.h>
14 : #include <fcntl.h>
15 : #include <unistd.h>
16 : #include "tsd_util_func.h"
17 : #include "tsd_path_mgr.h"
18 : #include "aicpu_package_process.h"
19 : #include "package_worker_utils.h"
20 : #include "package_worker_factory.h"
21 :
22 : namespace tsd {
23 : namespace {
24 : const std::string ENV_NAME_HOME = "HOME";
25 : constexpr size_t VERIFY_FILE_CONTENT_LEN = 15UL;
26 : } // namespace
27 :
28 10 : TSD_StatusT AicpuThreadPackageWorker::LoadPackage(const std::string& packagePath, const std::string& packageName)
29 : {
30 10 : const std::lock_guard<std::mutex> lk(packageMtx_);
31 :
32 10 : PreProcessPackage(packagePath, packageName);
33 :
34 10 : TSD_StatusT ret = TSD_OK;
35 0 : const ScopeGuard fdGuard([this, &ret]() {
36 10 : (void)flock(fd_, LOCK_UN);
37 10 : (void)close(fd_);
38 10 : fd_ = -1;
39 10 : PackageWorkerUtils::RemoveFile(decomPackagePath_.realPath);
40 10 : if (ret != TSD_OK) {
41 2 : Clear();
42 : }
43 10 : });
44 :
45 10 : if (!IsNeedLoadPackage()) {
46 3 : SetDecompressTimeToNow();
47 3 : TSD_INFO("No need decompress package.");
48 3 : return TSD_OK;
49 : }
50 :
51 7 : TSD_RUN_INFO(
52 : "Start load package, originPkg=%s, decomPkg=%s, checkCode=%lu, pkgSize=%lu",
53 : originPackagePath_.realPath.c_str(), decomPackagePath_.realPath.c_str(), GetCheckCode(),
54 : GetOriginPackageSize());
55 :
56 7 : ret = MoveOriginPackageToDecompressDir();
57 7 : if (ret != TSD_OK) {
58 0 : TSD_ERROR("Move package to decompress dir failed");
59 0 : return ret;
60 : }
61 :
62 7 : ret = PackageWorkerUtils::VerifyPackage(decomPackagePath_.realPath);
63 7 : if (ret != TSD_OK) {
64 1 : TSD_ERROR("Verify package failed, ret=%u", ret);
65 1 : return ret;
66 : }
67 :
68 6 : ret = DecompressPackage();
69 6 : if (ret != TSD_OK) {
70 0 : TSD_ERROR("Decompress package failed, ret=%u", ret);
71 0 : return ret;
72 : }
73 :
74 6 : ret = PostProcessPackage();
75 6 : if (ret != TSD_OK) {
76 1 : TSD_ERROR("Post process package failed, ret=%u", ret);
77 1 : return ret;
78 : }
79 :
80 5 : TSD_RUN_INFO(
81 : "Load package success, originPkg=%s, decomPkg=%s, checkCode=%lu", originPackagePath_.realPath.c_str(),
82 : decomPackagePath_.realPath.c_str(), GetCheckCode());
83 :
84 5 : return TSD_OK;
85 10 : }
86 :
87 11 : void AicpuThreadPackageWorker::PreProcessPackage(const std::string& packagePath, const std::string& packageName)
88 : {
89 11 : DefaultPreProcessPackage(packagePath, packageName);
90 :
91 11 : verifyFilePath_ = decomPackagePath_.path + verifyFileName_;
92 11 : soInstallRootPath_ = TsdPathMgr::BuildKernelSoRootPath(uniqueVfId_, decomPackagePath_.path);
93 :
94 11 : const TSD_StatusT ret = OpenVerifyFile();
95 11 : if (ret != TSD_OK) {
96 0 : TSD_ERROR("Open verify file failed.");
97 : }
98 :
99 11 : return;
100 : }
101 :
102 11 : void AicpuThreadPackageWorker::SetDecompressPackagePath()
103 : {
104 11 : std::string pathEnv("");
105 11 : GetScheduleEnv(ENV_NAME_HOME.c_str(), pathEnv);
106 11 : if (pathEnv.empty()) {
107 1 : TSD_ERROR("Get env %s is empty", ENV_NAME_HOME.c_str());
108 1 : return;
109 : }
110 :
111 10 : if (!CheckValidatePath(pathEnv)) {
112 0 : TSD_ERROR("Env %s invalid, val=%s", ENV_NAME_HOME.c_str(), pathEnv.c_str());
113 0 : return;
114 : }
115 :
116 10 : if (!CheckRealPath(pathEnv)) {
117 2 : TSD_ERROR("Cannot get realpath of env %s, val=%s", ENV_NAME_HOME.c_str(), pathEnv.c_str());
118 2 : return;
119 : }
120 :
121 8 : std::string dstPath = pathEnv + "/";
122 :
123 8 : decomPackagePath_ = PackagePath(dstPath, originPackagePath_.name);
124 :
125 8 : return;
126 11 : }
127 :
128 11 : TSD_StatusT AicpuThreadPackageWorker::OpenVerifyFile()
129 : {
130 11 : fd_ = open(verifyFilePath_.c_str(), O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
131 11 : if (fd_ < 0) {
132 4 : TSD_RUN_INFO("Create verify file end, path=%s, reason=%s", verifyFilePath_.c_str(), SafeStrerror().c_str());
133 4 : fd_ = open(verifyFilePath_.c_str(), O_RDWR);
134 4 : if (fd_ < 0) {
135 0 : TSD_ERROR(
136 : "Create and open verify file failed, path=%s, reason=%s", verifyFilePath_.c_str(),
137 : SafeStrerror().c_str());
138 0 : return TSD_INTERNAL_ERROR;
139 : }
140 : }
141 :
142 11 : TSD_RUN_INFO("Create or open verify file success, path=%s", verifyFilePath_.c_str());
143 :
144 11 : return TSD_OK;
145 : }
146 :
147 8 : bool AicpuThreadPackageWorker::IsNeedLoadPackage()
148 : {
149 8 : uint64_t savedCheckCode = 0UL;
150 8 : TSD_StatusT ret = GetSavedCheckCodeShared(savedCheckCode);
151 8 : if (ret != TSD_OK) {
152 1 : TSD_ERROR("Get shared check code failed, will not decompress package");
153 1 : return false;
154 : }
155 :
156 7 : if (savedCheckCode == GetOriginPackageSize()) {
157 3 : TSD_INFO("No need to decompress package by shared lock, checkCode=%lu", savedCheckCode);
158 3 : return false;
159 : }
160 :
161 4 : ret = GetSavedCheckCodeUnshared(savedCheckCode);
162 4 : if (ret != TSD_OK) {
163 0 : TSD_ERROR("Get unshared check code failed, will not decompress package");
164 0 : return false;
165 : }
166 :
167 4 : if (savedCheckCode == GetOriginPackageSize()) {
168 0 : TSD_INFO("No need to decompress package by unshared lock, checkCode=%lu", savedCheckCode);
169 0 : return false;
170 : }
171 :
172 4 : SetCheckCode(savedCheckCode);
173 :
174 4 : return true;
175 : }
176 :
177 8 : TSD_StatusT AicpuThreadPackageWorker::GetSavedCheckCodeShared(uint64_t& savedCheckCode) const
178 : {
179 8 : if (fd_ < 0) {
180 1 : TSD_ERROR("Verify file not open, fd is less than 0");
181 1 : return TSD_INTERNAL_ERROR;
182 : }
183 :
184 : // used read lock for faster process when parallel case
185 7 : int32_t ret = flock(fd_, LOCK_SH);
186 7 : if (ret == -1) {
187 0 : TSD_ERROR("Lock verify file was not successful, reason=%s", SafeStrerror().c_str());
188 0 : return TSD_INTERNAL_ERROR;
189 : }
190 :
191 7 : (void)ReadCheckCode(savedCheckCode);
192 :
193 7 : ret = flock(fd_, LOCK_UN);
194 7 : if (ret == -1) {
195 0 : TSD_ERROR("Unlock verify file was not successful, reason=%s", SafeStrerror().c_str());
196 0 : return TSD_INTERNAL_ERROR;
197 : }
198 :
199 7 : return TSD_OK;
200 : }
201 :
202 4 : TSD_StatusT AicpuThreadPackageWorker::GetSavedCheckCodeUnshared(uint64_t& savedCheckCode) const
203 : {
204 4 : const int32_t ret = flock(fd_, LOCK_EX);
205 4 : if (ret == -1) {
206 0 : TSD_ERROR("Lock verify file failed, reason=%s", SafeStrerror().c_str());
207 0 : return TSD_INTERNAL_ERROR;
208 : }
209 :
210 4 : (void)ReadCheckCode(savedCheckCode);
211 :
212 : // File lock released after write check code end
213 :
214 4 : return TSD_OK;
215 : }
216 :
217 11 : TSD_StatusT AicpuThreadPackageWorker::ReadCheckCode(uint64_t& savedCheckCode) const
218 : {
219 11 : savedCheckCode = 0UL;
220 : char_t buf[VERIFY_FILE_CONTENT_LEN + 1U];
221 11 : const int32_t eRet = memset_s(
222 : &buf[0], sizeof(char_t) * (VERIFY_FILE_CONTENT_LEN + 1U), 0, sizeof(char_t) * (VERIFY_FILE_CONTENT_LEN + 1U));
223 11 : if (eRet != 0) {
224 0 : TSD_ERROR("Memset failed in read check code, ret=%d", eRet);
225 0 : return TSD_INTERNAL_ERROR;
226 : }
227 :
228 11 : const ssize_t ret = static_cast<ssize_t>(read(fd_, &buf[0], VERIFY_FILE_CONTENT_LEN));
229 11 : if (ret < 0) {
230 0 : TSD_RUN_WARN("Reading check code in verify file was not successful, reason=%s", SafeStrerror().c_str());
231 0 : return TSD_OK;
232 : }
233 :
234 11 : buf[ret] = '\0';
235 11 : int32_t result = 0;
236 11 : (void)TransStrToInt(std::string(&buf[0]), result);
237 11 : if (result > 0) {
238 0 : savedCheckCode = static_cast<uint64_t>(result);
239 : }
240 :
241 11 : return TSD_OK;
242 : }
243 :
244 8 : std::string AicpuThreadPackageWorker::GetMovePackageToDecompressDirCmd() const
245 : {
246 8 : std::string cmd("");
247 8 : cmd.append("cp '").append(originPackagePath_.realPath).append("' '").append(decomPackagePath_.realPath).append("'");
248 8 : return cmd;
249 0 : }
250 :
251 7 : std::string AicpuThreadPackageWorker::GetDecompressPackageCmd() const
252 : {
253 7 : std::string cmd("");
254 7 : cmd.append("mkdir -p ")
255 7 : .append(soInstallRootPath_)
256 7 : .append(" ; tar --no-same-owner -ozxf ")
257 7 : .append(decomPackagePath_.realPath)
258 7 : .append(" -C ")
259 7 : .append(soInstallRootPath_);
260 7 : return cmd;
261 0 : }
262 :
263 2 : TSD_StatusT AicpuThreadPackageWorker::PostProcessPackage()
264 : {
265 2 : const std::string soInstallPath = TsdPathMgr::BuildKernelSoPath(soInstallRootPath_);
266 2 : TSD_StatusT ret = AicpuPackageProcess::CheckPackageName(soInstallPath, decomPackagePath_.name);
267 2 : if (ret != TSD_OK) {
268 0 : TSD_ERROR(
269 : "Check package name failed, ret=%u, soInstallPath=%s, name=%s", ret, soInstallPath.c_str(),
270 : decomPackagePath_.name.c_str());
271 0 : return ret;
272 : }
273 :
274 2 : ret = AicpuPackageProcess::MoveSoToSandBox(soInstallPath);
275 2 : if (ret != TSD_OK) {
276 1 : TSD_RUN_WARN("Move tf so to sandbox failed, ret=%u, path=%s", ret, soInstallRootPath_.c_str());
277 : }
278 :
279 2 : (void)BasePackageWorker::PostProcessPackage();
280 :
281 2 : (void)WriteCheckCode(fd_, GetCheckCode());
282 :
283 2 : (void)ResetExtendVerifyFile();
284 :
285 2 : TSD_INFO("Post process of aicpu thread package success");
286 :
287 2 : return TSD_OK;
288 2 : }
289 :
290 4 : TSD_StatusT AicpuThreadPackageWorker::WriteCheckCode(const int32_t fd, const uint64_t checkCode) const
291 : {
292 4 : (void)lseek(fd, 0, SEEK_SET);
293 4 : const std::string writeCode = std::to_string(checkCode);
294 4 : const ssize_t ret = write(fd, writeCode.c_str(), writeCode.length());
295 4 : if (ret < 0) {
296 2 : TSD_ERROR("Writing check code to verify file was not successful, reason=%s", SafeStrerror().c_str());
297 2 : return TSD_INTERNAL_ERROR;
298 : }
299 :
300 2 : return TSD_OK;
301 4 : }
302 :
303 2 : TSD_StatusT AicpuThreadPackageWorker::ResetExtendVerifyFile() const
304 : {
305 2 : const std::string extendVerifyFile = decomPackagePath_.path + EXTEND_VERIFY_FILE_NAME;
306 2 : const int32_t fd = open(extendVerifyFile.c_str(), O_RDWR);
307 2 : if (fd < 0) {
308 2 : TSD_INFO(
309 : "Opening extend verify file was not successful, path=%s, reason=%s", extendVerifyFile.c_str(),
310 : SafeStrerror().c_str());
311 2 : return TSD_OK;
312 : }
313 0 : const ScopeGuard fdGuard([fd]() { (void)close(fd); });
314 :
315 0 : if (WriteCheckCode(fd, 0UL) == TSD_OK) {
316 0 : TSD_RUN_INFO("Clear extend verify file success, path=%s", extendVerifyFile.c_str());
317 : } else {
318 0 : TSD_RUN_WARN("Clearing extend verify file was not successful, path=%s", extendVerifyFile.c_str());
319 : }
320 :
321 0 : return TSD_OK;
322 2 : }
323 :
324 3 : TSD_StatusT AicpuThreadPackageWorker::UnloadPackage()
325 : {
326 3 : const std::lock_guard<std::mutex> lk(packageMtx_);
327 3 : return TSD_OK;
328 3 : }
329 :
330 3 : TSD_StatusT ExtendThreadPackageWorker::PostProcessPackage()
331 : {
332 3 : const TSD_StatusT ret = AicpuPackageProcess::CopyExtendSoToCommonSoPath(soInstallRootPath_, IsAsanMode());
333 3 : if (ret != TSD_OK) {
334 1 : TSD_ERROR("Move extend so to common so path failed, ret=%u", ret);
335 1 : return ret;
336 : }
337 :
338 2 : (void)BasePackageWorker::PostProcessPackage();
339 :
340 2 : (void)WriteCheckCode(fd_, GetCheckCode());
341 :
342 2 : TSD_INFO("Post process of extend thread package success");
343 :
344 2 : return TSD_OK;
345 : }
346 :
347 8 : REGISTER_PACKAGE_WORKER(PackageWorkerType::PACKAGE_WORKER_AICPU_THREAD, AicpuThreadPackageWorker);
348 1 : REGISTER_PACKAGE_WORKER(PackageWorkerType::PACKAGE_WORKER_EXTEND_THREAD, ExtendThreadPackageWorker);
349 : } // namespace tsd
|