1 /*
2 * Copyright (c) 2021 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 #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_UINT64) {
43 callIdExistFlag = true;
44 currentCallId_ = value;
45 } else {
46 pidAndipsToCallId_.Insert(fsFixedHeadrAddr->pid, ipsHashValue, callChainId_);
47 currentCallId_ = callChainId_++;
48 }
49 } else {
50 currentCallId_ = INVALID_UINT64;
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 if (!reader_->GetFileSystemEventMap().size()) {
104 return;
105 }
106 auto& tracerEventToStrIndexMap = reader_->GetTracerEventToStrIndexMap();
107 for (auto mapItor = reader_->GetFileSystemEventMap().begin(); mapItor != reader_->GetFileSystemEventMap().end();
108 mapItor++) {
109 streamFilters_->statFilter_->IncreaseStat(TRACE_EVENT_EBPF_FILE_SYSTEM, STAT_EVENT_RECEIVED);
110 auto fsFixedHeadrAddr = mapItor->second;
111 bool callIdExistFlag = false;
112 auto userIpsAddr = reinterpret_cast<const uint64_t*>(fsFixedHeadrAddr + 1);
113 // Find the corresponding callId for the number of user IP addresses
114 IpAndCallidFind(fsFixedHeadrAddr, callIdExistFlag, userIpsAddr);
115 uint16_t type = INVALID_UINT16;
116 auto tmp = fucSubToSummaryType.find(fsFixedHeadrAddr->type);
117 if (tmp == fucSubToSummaryType.end()) {
118 return;
119 }
120 type = fucSubToSummaryType.at(fsFixedHeadrAddr->type);
121 // Init process name data
122 auto processName = const_cast<char*>(fsFixedHeadrAddr->processName);
123 processName[MAX_PROCESS_NAME_SZIE - 1] = '\0';
124 uint32_t ipid =
125 streamFilters_->processFilter_->UpdateOrCreateProcessWithName(fsFixedHeadrAddr->pid, processName);
126 uint32_t itid =
127 streamFilters_->processFilter_->GetOrCreateThreadWithPid(fsFixedHeadrAddr->tid, fsFixedHeadrAddr->pid);
128 auto newStartTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, fsFixedHeadrAddr->startTime);
129 auto newEndTs = streamFilters_->clockFilter_->ToPrimaryTraceTime(clockId_, fsFixedHeadrAddr->endTime);
130 DataIndex returnValue = INVALID_UINT64;
131 DataIndex errorCode = INVALID_UINT64;
132 //(newStartTs > newEndTs), When the data is invalid, the maximum value returned is uint64_t(size_t size
133 //=numeric_limits<uint64_t>::max());
134 uint64_t duration = StartEndTime(fsFixedHeadrAddr, newStartTs, newEndTs, returnValue, errorCode);
135 if (newStartTs > newEndTs) {
136 return;
137 }
138 int32_t i = 0;
139 auto firstArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]);
140 auto secondArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]);
141 auto thirdArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i++]);
142 auto fourthArgument = ConvertToHexTextIndex(fsFixedHeadrAddr->args[i]);
143 // get file descriptor
144 uint64_t filePathId = INVALID_UINT64;
145 auto fd = GetFileDescriptor(fsFixedHeadrAddr, type);
146 size_t size = FileWriteOperation(tracerEventToStrIndexMap, fsFixedHeadrAddr, itid, filePathId, type);
147 traceDataCache_->GetFileSystemSample()->AppendNewData(
148 currentCallId_, type, ipid, itid, newStartTs, newEndTs, duration, returnValue, errorCode, size, fd,
149 filePathId, firstArgument, secondArgument, thirdArgument, fourthArgument);
150 if (!callIdExistFlag) {
151 ParseCallStackData(userIpsAddr, fsFixedHeadrAddr->nrUserIPs, fsFixedHeadrAddr->pid, currentCallId_);
152 }
153 }
154 }
155
GetFileDescriptor(const FsFixedHeader * fsFixedHeader,uint32_t fucType)156 int32_t FileSystemDataParser::GetFileDescriptor(const FsFixedHeader* fsFixedHeader, uint32_t fucType)
157 {
158 auto returnValue = fsFixedHeader->ret;
159 int32_t fd = INVALID_INT32;
160 if (fucType == OPEN and returnValue >= 0) {
161 fd = returnValue;
162 } else if (fucType == READ or fucType == WRITE) {
163 fd = fsFixedHeader->args[0];
164 } else if (fucType == CLOSE) {
165 fd = fsFixedHeader->args[1];
166 }
167 return fd;
168 }
169 } // namespace TraceStreamer
170 } // namespace SysTuning
171