1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 09:57:35 +00:00

Kernel+ProfileViewer: Display additional filesystem events

This commit is contained in:
Jakub Berkop 2023-08-25 23:47:42 +02:00 committed by Andrew Kaster
parent c184a0786f
commit 54e79aa1d9
16 changed files with 655 additions and 135 deletions

View file

@ -24,10 +24,10 @@ PerformanceEventBuffer::PerformanceEventBuffer(NonnullOwnPtr<KBuffer> buffer)
{
}
NEVER_INLINE ErrorOr<void> PerformanceEventBuffer::append(int type, FlatPtr arg1, FlatPtr arg2, StringView arg3, Thread* current_thread, FlatPtr arg4, u64 arg5, ErrorOr<FlatPtr> const& arg6)
NEVER_INLINE ErrorOr<void> PerformanceEventBuffer::append(int type, FlatPtr arg1, FlatPtr arg2, StringView arg3, Thread* current_thread, FilesystemEvent filesystem_event)
{
FlatPtr base_pointer = (FlatPtr)__builtin_frame_address(0);
return append_with_ip_and_bp(current_thread->pid(), current_thread->tid(), 0, base_pointer, type, 0, arg1, arg2, arg3, arg4, arg5, arg6);
return append_with_ip_and_bp(current_thread->pid(), current_thread->tid(), 0, base_pointer, type, 0, arg1, arg2, arg3, filesystem_event);
}
static Vector<FlatPtr, PerformanceEvent::max_stack_frame_count> raw_backtrace(FlatPtr bp, FlatPtr ip)
@ -68,13 +68,13 @@ static Vector<FlatPtr, PerformanceEvent::max_stack_frame_count> raw_backtrace(Fl
}
ErrorOr<void> PerformanceEventBuffer::append_with_ip_and_bp(ProcessID pid, ThreadID tid, RegisterState const& regs,
int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FlatPtr arg4, u64 arg5, ErrorOr<FlatPtr> const& arg6)
int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FilesystemEvent filesystem_event)
{
return append_with_ip_and_bp(pid, tid, regs.ip(), regs.bp(), type, lost_samples, arg1, arg2, arg3, arg4, arg5, arg6);
return append_with_ip_and_bp(pid, tid, regs.ip(), regs.bp(), type, lost_samples, arg1, arg2, arg3, filesystem_event);
}
ErrorOr<void> PerformanceEventBuffer::append_with_ip_and_bp(ProcessID pid, ThreadID tid,
FlatPtr ip, FlatPtr bp, int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FlatPtr arg4, u64 arg5, ErrorOr<FlatPtr> const& arg6)
FlatPtr ip, FlatPtr bp, int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FilesystemEvent filesystem_event)
{
if (count() >= capacity())
return ENOBUFS;
@ -160,12 +160,8 @@ ErrorOr<void> PerformanceEventBuffer::append_with_ip_and_bp(ProcessID pid, Threa
event.data.signpost.arg1 = arg1;
event.data.signpost.arg2 = arg2;
break;
case PERF_EVENT_READ:
event.data.read.fd = arg1;
event.data.read.size = arg2;
event.data.read.filename_index = arg4;
event.data.read.start_timestamp = arg5;
event.data.read.success = !arg6.is_error();
case PERF_EVENT_FILESYSTEM:
event.data.filesystem = filesystem_event;
break;
default:
return EINVAL;
@ -295,13 +291,51 @@ ErrorOr<void> PerformanceEventBuffer::to_json_impl(Serializer& object) const
TRY(event_object.add("arg1"sv, event.data.signpost.arg1));
TRY(event_object.add("arg2"sv, event.data.signpost.arg2));
break;
case PERF_EVENT_READ:
TRY(event_object.add("type"sv, "read"));
TRY(event_object.add("fd"sv, event.data.read.fd));
TRY(event_object.add("size"sv, event.data.read.size));
TRY(event_object.add("filename_index"sv, event.data.read.filename_index));
TRY(event_object.add("start_timestamp"sv, event.data.read.start_timestamp));
TRY(event_object.add("success"sv, event.data.read.success));
case PERF_EVENT_FILESYSTEM:
TRY(event_object.add("type"sv, "filesystem"sv));
TRY(event_object.add("durationNs"sv, event.data.filesystem.durationNs));
switch (event.data.filesystem.type) {
case FilesystemEventType::Open: {
auto const& open = event.data.filesystem.data.open;
TRY(event_object.add("fs_event_type"sv, "open"sv));
TRY(event_object.add("dirfd"sv, open.dirfd));
TRY(event_object.add("filename_index"sv, open.filename_index));
TRY(event_object.add("options"sv, open.options));
TRY(event_object.add("mode"sv, open.mode));
break;
}
case FilesystemEventType::Close: {
auto const& close = event.data.filesystem.data.close;
TRY(event_object.add("fs_event_type"sv, "close"sv));
TRY(event_object.add("fd"sv, close.fd));
TRY(event_object.add("filename_index"sv, close.filename_index));
break;
}
case FilesystemEventType::Readv: {
auto const& readv = event.data.filesystem.data.readv;
TRY(event_object.add("fs_event_type"sv, "readv"sv));
TRY(event_object.add("fd"sv, readv.fd));
TRY(event_object.add("filename_index"sv, readv.filename_index));
break;
}
case FilesystemEventType::Read: {
auto const& read = event.data.filesystem.data.read;
TRY(event_object.add("fs_event_type"sv, "read"sv));
TRY(event_object.add("fd"sv, read.fd));
TRY(event_object.add("filename_index"sv, read.filename_index));
break;
}
case FilesystemEventType::Pread: {
auto const& pread = event.data.filesystem.data.pread;
TRY(event_object.add("fs_event_type"sv, "pread"sv));
TRY(event_object.add("fd"sv, pread.fd));
TRY(event_object.add("filename_index"sv, pread.filename_index));
TRY(event_object.add("buffer_ptr"sv, pread.buffer_ptr));
TRY(event_object.add("size"sv, pread.size));
TRY(event_object.add("offset"sv, pread.offset));
break;
}
}
break;
}
TRY(event_object.add("pid"sv, event.pid));

View file

@ -77,6 +77,66 @@ struct [[gnu::packed]] ReadPerformanceEvent {
bool success;
};
enum class FilesystemEventType : u8 {
Open,
Close,
Readv,
Read,
Pread
};
struct [[gnu::packed]] OpenEventData {
int dirfd;
size_t filename_index;
int options;
u64 mode;
};
struct [[gnu::packed]] CloseEventData {
int fd;
size_t filename_index;
};
struct [[gnu::packed]] ReadvEventData {
int fd;
size_t filename_index;
// struct iovec* iov; // TODO: Implement
// int iov_count; // TODO: Implement
};
struct [[gnu::packed]] ReadEventData {
int fd;
size_t filename_index;
};
struct [[gnu::packed]] PreadEventData {
int fd;
size_t filename_index;
FlatPtr buffer_ptr;
size_t size;
off_t offset;
};
// FIXME: This is a hack to make the compiler pack this struct correctly.
struct [[gnu::packed]] PackedErrorOr {
bool is_error;
FlatPtr value;
};
struct [[gnu::packed]] FilesystemEvent {
FilesystemEventType type;
u64 durationNs;
PackedErrorOr result;
union {
OpenEventData open;
CloseEventData close;
ReadvEventData readv;
ReadEventData read;
PreadEventData pread;
} data;
};
struct [[gnu::packed]] PerformanceEvent {
u32 type { 0 };
u8 stack_size { 0 };
@ -96,7 +156,7 @@ struct [[gnu::packed]] PerformanceEvent {
KMallocPerformanceEvent kmalloc;
KFreePerformanceEvent kfree;
SignpostPerformanceEvent signpost;
ReadPerformanceEvent read;
FilesystemEvent filesystem;
} data;
static constexpr size_t max_stack_frame_count = 64;
FlatPtr stack[max_stack_frame_count];
@ -111,11 +171,11 @@ class PerformanceEventBuffer {
public:
static OwnPtr<PerformanceEventBuffer> try_create_with_size(size_t buffer_size);
ErrorOr<void> append(int type, FlatPtr arg1, FlatPtr arg2, StringView arg3, Thread* current_thread = Thread::current(), FlatPtr arg4 = 0, u64 arg5 = 0, ErrorOr<FlatPtr> const& arg6 = 0);
ErrorOr<void> append(int type, FlatPtr arg1, FlatPtr arg2, StringView arg3, Thread* current_thread = Thread::current(), FilesystemEvent filesystem_event = {});
ErrorOr<void> append_with_ip_and_bp(ProcessID pid, ThreadID tid, FlatPtr eip, FlatPtr ebp,
int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FlatPtr arg4 = 0, u64 arg5 = {}, ErrorOr<FlatPtr> const& arg6 = 0);
int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FilesystemEvent filesystem_event = {});
ErrorOr<void> append_with_ip_and_bp(ProcessID pid, ThreadID tid, RegisterState const& regs,
int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FlatPtr arg4 = 0, u64 arg5 = {}, ErrorOr<FlatPtr> const& arg6 = 0);
int type, u32 lost_samples, FlatPtr arg1, FlatPtr arg2, StringView arg3, FilesystemEvent filesystem_event = {});
void clear()
{

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2021, Brian Gianforcaro <bgianf@serenityos.org>
* Copyright (c) 2023, Jakub Berkop <jakub.berkop@gmail.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -128,40 +129,6 @@ public:
}
}
static void add_read_event(Thread& thread, int fd, size_t size, OpenFileDescription const& file_description, u64 start_timestamp, ErrorOr<FlatPtr> const& result)
{
if (thread.is_profiling_suppressed())
return;
auto* event_buffer = thread.process().current_perf_events_buffer();
if (event_buffer == nullptr)
return;
size_t filepath_string_index;
if (auto path = file_description.original_absolute_path(); !path.is_error()) {
auto registered_result = event_buffer->register_string(move(path.value()));
if (registered_result.is_error())
return;
filepath_string_index = registered_result.value();
} else if (auto pseudo_path = file_description.pseudo_path(); !pseudo_path.is_error()) {
auto registered_result = event_buffer->register_string(move(pseudo_path.value()));
if (registered_result.is_error())
return;
filepath_string_index = registered_result.value();
} else {
auto invalid_path_string = KString::try_create("<INVALID_FILE_PATH>"sv); // TODO: Performance, unnecessary allocations.
if (invalid_path_string.is_error())
return;
auto registered_result = event_buffer->register_string(move(invalid_path_string.value()));
if (registered_result.is_error())
return;
filepath_string_index = registered_result.value();
}
[[maybe_unused]] auto rc = event_buffer->append(PERF_EVENT_READ, fd, size, {}, &thread, filepath_string_index, start_timestamp, result); // wrong arguments
}
static void timer_tick(RegisterState const& regs)
{
static UnixDateTime last_wakeup;

View file

@ -690,7 +690,11 @@ private:
ErrorOr<void> remap_range_as_stack(FlatPtr address, size_t size);
ErrorOr<FlatPtr> open_impl(Userspace<Syscall::SC_open_params const*>);
ErrorOr<FlatPtr> close_impl(int fd);
ErrorOr<FlatPtr> read_impl(int fd, Userspace<u8*> buffer, size_t size);
ErrorOr<FlatPtr> pread_impl(int fd, Userspace<u8*>, size_t, off_t);
ErrorOr<FlatPtr> readv_impl(int fd, Userspace<const struct iovec*> iov, int iov_count);
public:
ErrorOr<void> traverse_as_directory(FileSystemID, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const;