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