diff --git a/build/config_headers/tracing_config.h b/build/config_headers/tracing_config.h index b1bc2e5a95..926b69e1d5 100644 --- a/build/config_headers/tracing_config.h +++ b/build/config_headers/tracing_config.h @@ -26,6 +26,10 @@ #define BLOCK_CACHE_BLOCK_TRACING 0 #define BLOCK_CACHE_TRANSACTION_TRACING 0 #define BMESSAGE_TRACING 0 +#define FILE_DESCRIPTOR_TRACING 0 +#define FILE_DESCRIPTOR_TRACING_STACK_TRACE 0 /* stack trace depth */ +#define IO_CONTEXT_TRACING 0 +#define IO_CONTEXT_TRACING_STACK_TRACE 0 /* stack trace depth */ #define KERNEL_HEAP_TRACING 0 #define KTRACE_PRINTF_STACK_TRACE 0 /* stack trace depth */ #define NET_BUFFER_TRACING 0 diff --git a/src/system/kernel/fs/fd.cpp b/src/system/kernel/fs/fd.cpp index 0319c6052f..10359e71e0 100644 --- a/src/system/kernel/fs/fd.cpp +++ b/src/system/kernel/fs/fd.cpp @@ -23,6 +23,8 @@ #include #include +#include "vfs_tracing.h" + //#define TRACE_FD #ifdef TRACE_FD @@ -168,6 +170,8 @@ new_fd_etc(struct io_context* context, struct file_descriptor* descriptor, goto err; } + TFD(NewFD(context, fd, descriptor)); + context->fds[fd] = descriptor; context->num_used_fds++; atomic_add(&descriptor->open_count, 1); @@ -194,6 +198,8 @@ put_fd(struct file_descriptor* descriptor) { int32 previous = atomic_add(&descriptor->ref_count, -1); + TFD(PutFD(descriptor)); + TRACE(("put_fd(descriptor = %p [ref = %ld, cookie = %p])\n", descriptor, descriptor->ref_count, descriptor->cookie)); @@ -291,8 +297,10 @@ get_fd_locked(struct io_context* context, int fd) // Disconnected descriptors cannot be accessed anymore if (descriptor->open_mode & O_DISCONNECTED) descriptor = NULL; - else + else { + TFD(GetFD(context, fd, descriptor)); inc_fd_ref_count(descriptor); + } } return descriptor; @@ -341,8 +349,10 @@ remove_fd(struct io_context* context, int fd) select_info* selectInfos = NULL; bool disconnected = false; - if (descriptor) { + if (descriptor != NULL) { // fd is valid + TFD(RemoveFD(context, fd, descriptor)); + context->fds[fd] = NULL; fd_set_close_on_exec(context, fd, false); context->num_used_fds--; @@ -427,6 +437,8 @@ dup2_fd(int oldfd, int newfd, bool kernel) select_info* selectInfos = NULL; if (oldfd != newfd) { // Now do the work + TFD(Dup2FD(context, oldfd, newfd)); + evicted = context->fds[newfd]; selectInfos = context->select_infos[newfd]; context->select_infos[newfd] = NULL; diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index a40cdead46..c6bcd46c47 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -58,6 +58,7 @@ #include "fifo.h" #include "IORequest.h" #include "unused_vnodes.h" +#include "vfs_tracing.h" #include "Vnode.h" #include "../cache/vnode_store.h" @@ -4740,17 +4741,18 @@ vfs_exec_io_context(io_context* context) io_context* vfs_new_io_context(io_context* parentContext, bool purgeCloseOnExec) { - size_t tableSize; - struct io_context* context; - - context = (io_context*)malloc(sizeof(struct io_context)); + io_context* context = (io_context*)malloc(sizeof(io_context)); if (context == NULL) return NULL; - memset(context, 0, sizeof(struct io_context)); + TIOC(NewIOContext(context, parentContext)); + + memset(context, 0, sizeof(io_context)); context->ref_count = 1; MutexLocker parentLocker; + + size_t tableSize; if (parentContext) { parentLocker.SetTo(parentContext->io_mutex, false); tableSize = parentContext->table_size; @@ -4799,6 +4801,8 @@ vfs_new_io_context(io_context* parentContext, bool purgeCloseOnExec) if (closeOnExec && purgeCloseOnExec) continue; + TFD(InheritFD(context, i, descriptor, parentContext)); + context->fds[i] = descriptor; context->num_used_fds++; atomic_add(&descriptor->ref_count, 1); @@ -4835,6 +4839,8 @@ vfs_free_io_context(io_context* context) { uint32 i; + TIOC(FreeIOContext(context)); + if (context->root) put_vnode(context->root); @@ -4881,6 +4887,8 @@ vfs_resize_fd_table(struct io_context* context, const int newSize) if (newSize <= 0 || newSize > MAX_FD_TABLE_SIZE) return EINVAL; + TIOC(ResizeIOContext(context, newSize)); + MutexLocker _(context->io_mutex); int oldSize = context->table_size; diff --git a/src/system/kernel/fs/vfs_tracing.h b/src/system/kernel/fs/vfs_tracing.h new file mode 100644 index 0000000000..2358a7c1fb --- /dev/null +++ b/src/system/kernel/fs/vfs_tracing.h @@ -0,0 +1,311 @@ +/* + * Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2010, Michael Lotz, mmlr@mlotz.ch. + * Distributed under the terms of the MIT License. + */ +#ifndef VFS_TRACING_H +#define VFS_TRACING_H + + +#include +#include +#include + + +// #pragma mark - File Descriptor Tracing + + +#if FILE_DESCRIPTOR_TRACING + +namespace FileDescriptorTracing { + + +class FDTraceEntry : public AbstractTraceEntry { +public: + FDTraceEntry(file_descriptor* descriptor) + : + fDescriptor(descriptor), + fReferenceCount(descriptor->ref_count) + { +#if FILE_DESCRIPTOR_TRACING_STACK_TRACE + fStackTrace = capture_tracing_stack_trace( + FILE_DESCRIPTOR_TRACING_STACK_TRACE, 0, false); +#endif + } + +#if FILE_DESCRIPTOR_TRACING_STACK_TRACE + virtual void DumpStackTrace(TraceOutput& out) + { + out.PrintStackTrace(fStackTrace); + } +#endif + +protected: + file_descriptor* fDescriptor; + int32 fReferenceCount; +#if FILE_DESCRIPTOR_TRACING_STACK_TRACE + tracing_stack_trace* fStackTrace; +#endif +}; + + +class NewFD : public FDTraceEntry { +public: + NewFD(io_context* context, int fd, file_descriptor* descriptor) + : + FDTraceEntry(descriptor), + fContext(context), + fFD(fd) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("fd new: descriptor: %p (%" B_PRId32 "), context: %p, " + "fd: %d", fDescriptor, fReferenceCount, fContext, fFD); + } + +private: + io_context* fContext; + int fFD; +}; + + +class PutFD : public FDTraceEntry { +public: + PutFD(file_descriptor* descriptor) + : + FDTraceEntry(descriptor) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("fd put: descriptor: %p (%" B_PRId32 ")", fDescriptor, + fReferenceCount); + } +}; + + +class GetFD : public FDTraceEntry { +public: + GetFD(io_context* context, int fd, file_descriptor* descriptor) + : + FDTraceEntry(descriptor), + fContext(context), + fFD(fd) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("fd get: descriptor: %p (%" B_PRId32 "), context: %p, " + "fd: %d", fDescriptor, fReferenceCount, fContext, fFD); + } + +private: + io_context* fContext; + int fFD; +}; + + +class RemoveFD : public FDTraceEntry { +public: + RemoveFD(io_context* context, int fd, file_descriptor* descriptor) + : + FDTraceEntry(descriptor), + fContext(context), + fFD(fd) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("fd remove: descriptor: %p (%" B_PRId32 "), context: %p, " + "fd: %d", fDescriptor, fReferenceCount, fContext, fFD); + } + +private: + io_context* fContext; + int fFD; +}; + + +class Dup2FD : public FDTraceEntry { +public: + Dup2FD(io_context* context, int oldFD, int newFD) + : + FDTraceEntry(context->fds[oldFD]), + fContext(context), + fEvictedDescriptor(context->fds[newFD]), + fEvictedReferenceCount( + fEvictedDescriptor != NULL ? fEvictedDescriptor->ref_count : 0), + fOldFD(oldFD), + fNewFD(newFD) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("fd dup2: descriptor: %p (%" B_PRId32 "), context: %p, " + "fd: %d -> %d, evicted: %p (%" B_PRId32 ")", fDescriptor, + fReferenceCount, fContext, fOldFD, fNewFD, fEvictedDescriptor, + fEvictedReferenceCount); + } + +private: + io_context* fContext; + file_descriptor* fEvictedDescriptor; + int32 fEvictedReferenceCount; + int fOldFD; + int fNewFD; +}; + + +class InheritFD : public FDTraceEntry { +public: + InheritFD(io_context* context, int fd, file_descriptor* descriptor, + io_context* parentContext) + : + FDTraceEntry(descriptor), + fContext(context), + fParentContext(parentContext), + fFD(fd) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("fd inherit: descriptor: %p (%" B_PRId32 "), context: %p, " + "fd: %d, parentContext: %p", fDescriptor, fReferenceCount, fContext, + fFD, fParentContext); + } + +private: + io_context* fContext; + io_context* fParentContext; + int fFD; +}; + + +} // namespace FileDescriptorTracing + +# define TFD(x) new(std::nothrow) FileDescriptorTracing::x + +#else +# define TFD(x) +#endif // FILE_DESCRIPTOR_TRACING + + +// #pragma mark - IO Context Tracing + + + +#if IO_CONTEXT_TRACING + +namespace IOContextTracing { + + +class IOContextTraceEntry : public AbstractTraceEntry { +public: + IOContextTraceEntry(io_context* context) + : + fContext(context) + { +#if IO_CONTEXT_TRACING_STACK_TRACE + fStackTrace = capture_tracing_stack_trace( + IO_CONTEXT_TRACING_STACK_TRACE, 0, false); +#endif + } + +#if IO_CONTEXT_TRACING_STACK_TRACE + virtual void DumpStackTrace(TraceOutput& out) + { + out.PrintStackTrace(fStackTrace); + } +#endif + +protected: + io_context* fContext; +#if IO_CONTEXT_TRACING_STACK_TRACE + tracing_stack_trace* fStackTrace; +#endif +}; + + +class NewIOContext : public IOContextTraceEntry { +public: + NewIOContext(io_context* context, io_context* parentContext) + : + IOContextTraceEntry(context), + fParentContext(parentContext) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("iocontext new: context: %p, parent: %p", fContext, + fParentContext); + } + +private: + io_context* fParentContext; +}; + + +class FreeIOContext : public IOContextTraceEntry { +public: + FreeIOContext(io_context* context) + : + IOContextTraceEntry(context) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("iocontext free: context: %p", fContext); + } +}; + + +class ResizeIOContext : public IOContextTraceEntry { +public: + ResizeIOContext(io_context* context, uint32 newTableSize) + : + IOContextTraceEntry(context), + fOldTableSize(context->table_size), + fNewTableSize(newTableSize) + { + Initialized(); + } + + virtual void AddDump(TraceOutput& out) + { + out.Print("iocontext resize: context: %p, size: %" B_PRIu32 " -> %" + B_PRIu32, fContext, fOldTableSize, fNewTableSize); + } + +private: + uint32 fOldTableSize; + uint32 fNewTableSize; +}; + + +} // namespace IOContextTracing + +# define TIOC(x) new(std::nothrow) IOContextTracing::x + +#else +# define TIOC(x) +#endif // IO_CONTEXT_TRACING + + +#endif // VFS_TRACING_H