bonefish+mmlr:
* Add file descriptor and IO context tracing. * Some minor cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36272 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -26,6 +26,10 @@
|
|||||||
#define BLOCK_CACHE_BLOCK_TRACING 0
|
#define BLOCK_CACHE_BLOCK_TRACING 0
|
||||||
#define BLOCK_CACHE_TRANSACTION_TRACING 0
|
#define BLOCK_CACHE_TRANSACTION_TRACING 0
|
||||||
#define BMESSAGE_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 KERNEL_HEAP_TRACING 0
|
||||||
#define KTRACE_PRINTF_STACK_TRACE 0 /* stack trace depth */
|
#define KTRACE_PRINTF_STACK_TRACE 0 /* stack trace depth */
|
||||||
#define NET_BUFFER_TRACING 0
|
#define NET_BUFFER_TRACING 0
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
#include <vfs.h>
|
#include <vfs.h>
|
||||||
#include <wait_for_objects.h>
|
#include <wait_for_objects.h>
|
||||||
|
|
||||||
|
#include "vfs_tracing.h"
|
||||||
|
|
||||||
|
|
||||||
//#define TRACE_FD
|
//#define TRACE_FD
|
||||||
#ifdef TRACE_FD
|
#ifdef TRACE_FD
|
||||||
@@ -168,6 +170,8 @@ new_fd_etc(struct io_context* context, struct file_descriptor* descriptor,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TFD(NewFD(context, fd, descriptor));
|
||||||
|
|
||||||
context->fds[fd] = descriptor;
|
context->fds[fd] = descriptor;
|
||||||
context->num_used_fds++;
|
context->num_used_fds++;
|
||||||
atomic_add(&descriptor->open_count, 1);
|
atomic_add(&descriptor->open_count, 1);
|
||||||
@@ -194,6 +198,8 @@ put_fd(struct file_descriptor* descriptor)
|
|||||||
{
|
{
|
||||||
int32 previous = atomic_add(&descriptor->ref_count, -1);
|
int32 previous = atomic_add(&descriptor->ref_count, -1);
|
||||||
|
|
||||||
|
TFD(PutFD(descriptor));
|
||||||
|
|
||||||
TRACE(("put_fd(descriptor = %p [ref = %ld, cookie = %p])\n",
|
TRACE(("put_fd(descriptor = %p [ref = %ld, cookie = %p])\n",
|
||||||
descriptor, descriptor->ref_count, descriptor->cookie));
|
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
|
// Disconnected descriptors cannot be accessed anymore
|
||||||
if (descriptor->open_mode & O_DISCONNECTED)
|
if (descriptor->open_mode & O_DISCONNECTED)
|
||||||
descriptor = NULL;
|
descriptor = NULL;
|
||||||
else
|
else {
|
||||||
|
TFD(GetFD(context, fd, descriptor));
|
||||||
inc_fd_ref_count(descriptor);
|
inc_fd_ref_count(descriptor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return descriptor;
|
return descriptor;
|
||||||
@@ -341,8 +349,10 @@ remove_fd(struct io_context* context, int fd)
|
|||||||
select_info* selectInfos = NULL;
|
select_info* selectInfos = NULL;
|
||||||
bool disconnected = false;
|
bool disconnected = false;
|
||||||
|
|
||||||
if (descriptor) {
|
if (descriptor != NULL) {
|
||||||
// fd is valid
|
// fd is valid
|
||||||
|
TFD(RemoveFD(context, fd, descriptor));
|
||||||
|
|
||||||
context->fds[fd] = NULL;
|
context->fds[fd] = NULL;
|
||||||
fd_set_close_on_exec(context, fd, false);
|
fd_set_close_on_exec(context, fd, false);
|
||||||
context->num_used_fds--;
|
context->num_used_fds--;
|
||||||
@@ -427,6 +437,8 @@ dup2_fd(int oldfd, int newfd, bool kernel)
|
|||||||
select_info* selectInfos = NULL;
|
select_info* selectInfos = NULL;
|
||||||
if (oldfd != newfd) {
|
if (oldfd != newfd) {
|
||||||
// Now do the work
|
// Now do the work
|
||||||
|
TFD(Dup2FD(context, oldfd, newfd));
|
||||||
|
|
||||||
evicted = context->fds[newfd];
|
evicted = context->fds[newfd];
|
||||||
selectInfos = context->select_infos[newfd];
|
selectInfos = context->select_infos[newfd];
|
||||||
context->select_infos[newfd] = NULL;
|
context->select_infos[newfd] = NULL;
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#include "fifo.h"
|
#include "fifo.h"
|
||||||
#include "IORequest.h"
|
#include "IORequest.h"
|
||||||
#include "unused_vnodes.h"
|
#include "unused_vnodes.h"
|
||||||
|
#include "vfs_tracing.h"
|
||||||
#include "Vnode.h"
|
#include "Vnode.h"
|
||||||
#include "../cache/vnode_store.h"
|
#include "../cache/vnode_store.h"
|
||||||
|
|
||||||
@@ -4740,17 +4741,18 @@ vfs_exec_io_context(io_context* context)
|
|||||||
io_context*
|
io_context*
|
||||||
vfs_new_io_context(io_context* parentContext, bool purgeCloseOnExec)
|
vfs_new_io_context(io_context* parentContext, bool purgeCloseOnExec)
|
||||||
{
|
{
|
||||||
size_t tableSize;
|
io_context* context = (io_context*)malloc(sizeof(io_context));
|
||||||
struct io_context* context;
|
|
||||||
|
|
||||||
context = (io_context*)malloc(sizeof(struct io_context));
|
|
||||||
if (context == NULL)
|
if (context == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
memset(context, 0, sizeof(struct io_context));
|
TIOC(NewIOContext(context, parentContext));
|
||||||
|
|
||||||
|
memset(context, 0, sizeof(io_context));
|
||||||
context->ref_count = 1;
|
context->ref_count = 1;
|
||||||
|
|
||||||
MutexLocker parentLocker;
|
MutexLocker parentLocker;
|
||||||
|
|
||||||
|
size_t tableSize;
|
||||||
if (parentContext) {
|
if (parentContext) {
|
||||||
parentLocker.SetTo(parentContext->io_mutex, false);
|
parentLocker.SetTo(parentContext->io_mutex, false);
|
||||||
tableSize = parentContext->table_size;
|
tableSize = parentContext->table_size;
|
||||||
@@ -4799,6 +4801,8 @@ vfs_new_io_context(io_context* parentContext, bool purgeCloseOnExec)
|
|||||||
if (closeOnExec && purgeCloseOnExec)
|
if (closeOnExec && purgeCloseOnExec)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
TFD(InheritFD(context, i, descriptor, parentContext));
|
||||||
|
|
||||||
context->fds[i] = descriptor;
|
context->fds[i] = descriptor;
|
||||||
context->num_used_fds++;
|
context->num_used_fds++;
|
||||||
atomic_add(&descriptor->ref_count, 1);
|
atomic_add(&descriptor->ref_count, 1);
|
||||||
@@ -4835,6 +4839,8 @@ vfs_free_io_context(io_context* context)
|
|||||||
{
|
{
|
||||||
uint32 i;
|
uint32 i;
|
||||||
|
|
||||||
|
TIOC(FreeIOContext(context));
|
||||||
|
|
||||||
if (context->root)
|
if (context->root)
|
||||||
put_vnode(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)
|
if (newSize <= 0 || newSize > MAX_FD_TABLE_SIZE)
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
|
TIOC(ResizeIOContext(context, newSize));
|
||||||
|
|
||||||
MutexLocker _(context->io_mutex);
|
MutexLocker _(context->io_mutex);
|
||||||
|
|
||||||
int oldSize = context->table_size;
|
int oldSize = context->table_size;
|
||||||
|
|||||||
@@ -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 <fs/fd.h>
|
||||||
|
#include <tracing.h>
|
||||||
|
#include <vfs.h>
|
||||||
|
|
||||||
|
|
||||||
|
// #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
|
||||||
Reference in New Issue
Block a user