1 /*
2 * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 #include "file_system_data_parser.h"
16 #include "process_filter.h"
17 #include "stat_filter.h"
18 #include "string_to_numerical.h"
19 #include <cinttypes>
20
21 namespace SysTuning {
22 namespace TraceStreamer {
FileSystemDataParser(TraceDataCache * dataCache,const TraceStreamerFilters * ctx)23 FileSystemDataParser::FileSystemDataParser(TraceDataCache *dataCache, const TraceStreamerFilters *ctx)
24 : EventParserBase(dataCache, ctx), EbpfBase(dataCache, ctx), timeParser_(std::make_unique<HtracePluginTimeParser>())
25 {
26 }
~FileSystemDataParser()27 FileSystemDataParser::~FileSystemDataParser()
28 {
29 TS_LOGI("EBPF FileSystem data ts MIN:%llu, MAX:%llu",
30 static_cast<unsigned long long>(timeParser_->GetPluginStartTime()),
31 static_cast<unsigned long long>(timeParser_->GetPluginEndTime()));
32 }
33
IpAndCallidFind(const FsFixedHeader * fsFixedHeadrAddr,bool & callIdExistFlag,const uint64_t * userIpsAddr)34 void FileSystemDataParser::IpAndCallidFind(const FsFixedHeader *fsFixedHeadrAddr,
35 bool &callIdExistFlag,
36 const uint64_t *userIpsAddr)
37 {
38 if (fsFixedHeadrAddr->nrUserIPs) {
39 std::string ipsToStr(reinterpret_cast<const char *>(userIpsAddr), fsFixedHeadrAddr->nrUserIPs * SINGLE_IP_SIZE);
40 auto ipsHashValue = hashFun_(ipsToStr);
41 auto value = pidAndipsToCallId_.Find(fsFixedHeadrAddr->pid, ipsHashValue);
42 if (value != INVALID_UINT32) {
43 callIdExistFlag = true;
44 currentCallId_ = value;
45 } else {
46 pidAndipsToCallId_.Insert(fsFixedHeadrAddr->pid, ipsHashValue, callChainId_);
47 currentCallId_ = callChainId_++;
48 }
49 } else {
50 currentCallId_ = INVALID_UINT32;
51 }
52 }
53
StartEndTime(const FsFixedHeader * fsFixedHeadrAddr,uint64_t newStartTs,uint64_t newEndTs,DataIndex & returnValue,DataIndex & errorCode)54 uint64_t FileSystemDataParser::StartEndTime(const FsFixedHeader *fsFixedHeadrAddr,
55 uint64_t newStartTs,
56 uint64_t newEndTs,
57 DataIndex &returnValue,
58 DataIndex &errorCode)
59 {
60 // When the data is invalid, calling the sub function under condition (newStartTs > newEndTs) ends the judgment
61 timeParser_->UpdatePluginTimeRange(clockId_, fsFixedHeadrAddr->startTime, newStartTs);
62 timeParser_->UpdatePluginTimeRange(clockId_, fsFixedHeadrAddr->endTime, newEndTs);
63 if (newStartTs > newEndTs) {
64 TS_LOGE("startTs = %" PRIu64 ", endTs = %" PRIu64 ", newStartTs = %" PRIu64 ", newEndTs = %" PRIu64 "",
65 fsFixedHeadrAddr->startTime, fsFixedHeadrAddr->endTime, newStartTs, newEndTs);
66 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_FILE_SYSTEM, STAT_EVENT_DATA_INVALID);
67 // When the data is invalid, the maximum value returned is uint64_t(numeric_limits<uint64_t>::max());
68 return std::numeric_limits<uint64_t>::max();
69 }
70 uint64_t duration = newEndTs - newStartTs;
71 if (fsFixedHeadrAddr->ret < 0) {
72 returnValue = ConvertToHexTextIndex(0);
73 errorCode = ConvertToHexTextIndex(-fsFixedHeadrAddr->ret);
74 } else {
75 returnValue = ConvertToHexTextIndex(fsFixedHeadrAddr->ret);
76 }
77 return duration;
78 }
79
80 template <typename TracerEventToStrIndexMap>
FileWriteOperation(TracerEventToStrIndexMap & tracerEventToStrIndexMap,const FsFixedHeader * fsFixedHeadrAddr,uint32_t itid,uint64_t & filePathId,uint16_t type)81 size_t FileSystemDataParser::FileWriteOperation(TracerEventToStrIndexMap &tracerEventToStrIndexMap,
82 const FsFixedHeader *fsFixedHeadrAddr,
83 uint32_t itid,
84 uint64_t &filePathId,
85 uint16_t type)
86 {
87 filePathId =
88 tracerEventToStrIndexMap.Find(ITEM_EVENT_FS, fsFixedHeadrAddr->type, itid, fsFixedHeadrAddr->startTime);
89 if (filePathId != INVALID_UINT64) {
90 tracerEventToStrIndexMap.Erase(ITEM_EVENT_FS, fsFixedHeadrAddr->type, itid, fsFixedHeadrAddr->startTime);
91 }
92
93 // get read or writ size
94 size_t size = MAX_SIZE_T;
95 if ((type == READ || type == WRITE) && fsFixedHeadrAddr->ret >= 0) {
96 size = fsFixedHeadrAddr->ret;
97 }
98 return size;
99 }
100
ParseFileSystemEvent()101 void FileSystemDataParser::ParseFileSystemEvent()
102 {
103 auto &tracerEventToStrIndexMap = reader_->GetTracerEventToStrIndexMap();
104 for (auto mapItor = reader_->GetFileSystemEventMap().begin(); mapItor != reader_->GetFileSystemEventMap().end();
105 mapItor++) {
106 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_FILE_SYSTEM, STAT_EVENT_RECEIVED);
107 auto fsFixedHeadrAddr = mapItor->second;
108 bool callIdExistFlag = false;
109 auto userIpsAddr = reinterpret_cast<const uint64_t *>(fsFixedHeadrAddr + 1);
110 // Find the corresponding callId for the number of user IP addresses
111 IpAndCallidFind(fsFixedHeadrAddr, callIdExistFlag, userIpsAddr);
112 uint16_t type = INVALID_UINT16;
113 auto tmp = fucSubToSummaryType.find(fsFixedHeadrAddr->type);
114 if (tmp == fucSubToSummaryType.end()) {
115 return;
116 }
117 type = fucSubToSummaryType.at(fsFixedHeadrAddr->type);
118 // Init process name data
119 auto processName = const_cast<char *>(fsFixedHeadrAddr->processName);
120 processName[MAX_PROCESS_NAME_SZIE - 1] = '\0';
121 uint32_t ipid =
122 streamFilters_->processFilter_->UpdateOrCreateProcessWithName(fsFixedHeadrAddr->pid, processName);
123 uint32_t itid =
124 streamFilters_->processFilter_->GetOrCreateThreadWithPid(fsFixedHeadrAddr->tid, fsFixedHeadrAddr->pid);
125 auto newStartTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, fsFixedHeadrAddr->startTime);
126 auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, fsFixedHeadrAddr->endTime);
127 DataIndex returnValue = INVALID_UINT64;
128 DataIndex errorCode = INVALID_UINT64;
129 //(newStartTs > newEndTs), When the data is invalid, the maximum value returned is uint64_t(size_t size
130 //=numeric_limits<uint64_t>::max());
131 uint64_t duration = StartEndTime(fsFixedHeadrAddr, newStartTs, newEndTs, returnValue, errorCode);
132 if (newStartTs > newEndTs) {
133 return;
134 }
135 int32_t i = 0;
136 auto firstArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]);
137 auto secondArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]);
138 auto thirdArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]);
139 auto fourthArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i]);
140 // get file descriptor
141 uint64_t filePathId = INVALID_UINT64;
142 auto fd = GetFileDescriptor(fsFixedHeadrAddr, type);
143 size_t size = FileWriteOperation(tracerEventToStrIndexMap, fsFixedHeadrAddr, itid, filePathId, type);
144 FileSystemSampleRow fileSystemSampleRow = {
145 currentCallId_, type, ipid, itid, newStartTs, newEndTs, duration, returnValue,
146 errorCode, size, fd, filePathId, firstArgument, secondArgument, thirdArgument, fourthArgument};
147 traceDataCache_->GetFileSystemSample()->AppendNewData(fileSystemSampleRow);
148 if (!callIdExistFlag) {
149 ParseCallStackData(userIpsAddr, fsFixedHeadrAddr->nrUserIPs, fsFixedHeadrAddr->pid, currentCallId_);
150 }
151 }
152 }
153
GetFileDescriptor(const FsFixedHeader * fsFixedHeader,uint32_t fucType)154 int32_t FileSystemDataParser::GetFileDescriptor(const FsFixedHeader *fsFixedHeader, uint32_t fucType)
155 {
156 auto returnValue = fsFixedHeader->ret;
157 int32_t fd = INVALID_INT32;
158 if (fucType == OPEN and returnValue >= 0) {
159 fd = returnValue;
160 } else if (fucType == READ or fucType == WRITE) {
161 fd = fsFixedHeader->args[0];
162 } else if (fucType == CLOSE) {
163 fd = fsFixedHeader->args[1];
164 }
165 return fd;
166 }
167 } // namespace TraceStreamer
168 } // namespace SysTuning
169