* Added some optional KDL command and statistics to the file map implementation.

* Turned them on for now.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26291 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2008-07-07 12:02:24 +00:00
parent 0cd3ea3e50
commit 52ecda6ecf
3 changed files with 150 additions and 10 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
*/ */
#ifndef _KERNEL_FILE_CACHE_H #ifndef _KERNEL_FILE_CACHE_H
@ -44,6 +44,8 @@ extern void cache_node_closed(struct vnode *vnode, int32 fdType, vm_cache *cache
extern void cache_node_launched(size_t argCount, char * const *args); extern void cache_node_launched(size_t argCount, char * const *args);
extern void cache_prefetch_vnode(struct vnode *vnode, off_t offset, size_t size); extern void cache_prefetch_vnode(struct vnode *vnode, off_t offset, size_t size);
extern void cache_prefetch(dev_t mountID, ino_t vnodeID, off_t offset, size_t size); extern void cache_prefetch(dev_t mountID, ino_t vnodeID, off_t offset, size_t size);
extern status_t file_map_init(void);
extern status_t file_cache_init_post_boot_device(void); extern status_t file_cache_init_post_boot_device(void);
extern status_t file_cache_init(void); extern status_t file_cache_init(void);

View File

@ -15,7 +15,7 @@
#include <file_cache.h> #include <file_cache.h>
#include <generic_syscall.h> #include <generic_syscall.h>
#include <util/AutoLock.h> #include <util/AutoLock.h>
#include <util/kernel_cpp.h> #include <util/DoublyLinkedList.h>
#include <vfs.h> #include <vfs.h>
#include <vm.h> #include <vm.h>
#include <vm_page.h> #include <vm_page.h>
@ -35,6 +35,8 @@
// for the whole map. // for the whole map.
// TODO: it would be nice if we could free a file map in low memory situations. // TODO: it would be nice if we could free a file map in low memory situations.
#define DEBUG_FILE_MAP
#define CACHED_FILE_EXTENTS 2 #define CACHED_FILE_EXTENTS 2
// must be smaller than MAX_FILE_IO_VECS // must be smaller than MAX_FILE_IO_VECS
// TODO: find out how much of these are typically used // TODO: find out how much of these are typically used
@ -49,7 +51,11 @@ struct file_extent_array {
size_t max_count; size_t max_count;
}; };
class FileMap { class FileMap
#ifdef DEBUG_FILE_MAP
: public DoublyLinkedListLinkImpl<FileMap>
#endif
{
public: public:
FileMap(struct vnode* vnode, off_t size); FileMap(struct vnode* vnode, off_t size);
~FileMap(); ~FileMap();
@ -61,12 +67,13 @@ public:
status_t Translate(off_t offset, size_t size, status_t Translate(off_t offset, size_t size,
file_io_vec* vecs, size_t* _count); file_io_vec* vecs, size_t* _count);
file_extent* ExtentAt(uint32 index);
size_t Count() const { return fCount; } size_t Count() const { return fCount; }
struct vnode* Vnode() const { return fVnode; } struct vnode* Vnode() const { return fVnode; }
off_t Size() const { return fSize; } off_t Size() const { return fSize; }
private: private:
file_extent* _ExtentAt(uint32 index);
file_extent* _FindExtent(off_t offset, uint32* _index); file_extent* _FindExtent(off_t offset, uint32* _index);
status_t _MakeSpace(size_t count); status_t _MakeSpace(size_t count);
status_t _Add(file_io_vec* vecs, size_t vecCount, status_t _Add(file_io_vec* vecs, size_t vecCount,
@ -81,23 +88,40 @@ private:
off_t fSize; off_t fSize;
}; };
#ifdef DEBUG_FILE_MAP
typedef DoublyLinkedList<FileMap> FileMapList;
static FileMapList sList;
static mutex sLock;
#endif
FileMap::FileMap(struct vnode* vnode, off_t size) FileMap::FileMap(struct vnode* vnode, off_t size)
{ {
fCount = 0; fCount = 0;
fVnode = vnode; fVnode = vnode;
fSize = size; fSize = size;
#ifdef DEBUG_FILE_MAP
MutexLocker _(sLock);
sList.Add(this);
#endif
} }
FileMap::~FileMap() FileMap::~FileMap()
{ {
Free(); Free();
#ifdef DEBUG_FILE_MAP
MutexLocker _(sLock);
sList.Remove(this);
#endif
} }
file_extent* file_extent*
FileMap::_ExtentAt(uint32 index) FileMap::ExtentAt(uint32 index)
{ {
if (index >= fCount) if (index >= fCount)
return NULL; return NULL;
@ -117,7 +141,7 @@ FileMap::_FindExtent(off_t offset, uint32 *_index)
while (left <= right) { while (left <= right) {
int32 index = (left + right) / 2; int32 index = (left + right) / 2;
file_extent* extent = _ExtentAt(index); file_extent* extent = ExtentAt(index);
if (extent->offset > offset) { if (extent->offset > offset) {
// search in left part // search in left part
@ -199,7 +223,7 @@ FileMap::_Add(file_io_vec* vecs, size_t vecCount, off_t& lastOffset)
file_extent* lastExtent = NULL; file_extent* lastExtent = NULL;
if (start != 0) { if (start != 0) {
lastExtent = _ExtentAt(start - 1); lastExtent = ExtentAt(start - 1);
offset = lastExtent->offset + lastExtent->disk.length; offset = lastExtent->offset + lastExtent->disk.length;
} }
@ -215,7 +239,7 @@ FileMap::_Add(file_io_vec* vecs, size_t vecCount, off_t& lastOffset)
} }
} }
file_extent* extent = _ExtentAt(start + i); file_extent* extent = ExtentAt(start + i);
extent->offset = offset; extent->offset = offset;
extent->disk = vecs[i]; extent->disk = vecs[i];
@ -225,7 +249,7 @@ FileMap::_Add(file_io_vec* vecs, size_t vecCount, off_t& lastOffset)
#ifdef TRACE_FILE_MAP #ifdef TRACE_FILE_MAP
for (uint32 i = 0; i < fCount; i++) { for (uint32 i = 0; i < fCount; i++) {
file_extent* extent = _ExtentAt(i); file_extent* extent = ExtentAt(i);
dprintf("[%ld] extent offset %Ld, disk offset %Ld, length %Ld\n", dprintf("[%ld] extent offset %Ld, disk offset %Ld, length %Ld\n",
i, extent->offset, extent->disk.offset, extent->disk.length); i, extent->offset, extent->disk.offset, extent->disk.length);
} }
@ -296,7 +320,7 @@ FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count)
file_extent* lastExtent = NULL; file_extent* lastExtent = NULL;
if (fCount > 0) if (fCount > 0)
lastExtent = _ExtentAt(fCount - 1); lastExtent = ExtentAt(fCount - 1);
off_t mapOffset = 0; off_t mapOffset = 0;
if (lastExtent != NULL) if (lastExtent != NULL)
@ -365,6 +389,118 @@ FileMap::Translate(off_t offset, size_t size, file_io_vec* vecs, size_t* _count)
} }
// #pragma mark -
#ifdef DEBUG_FILE_MAP
static int
dump_file_map(int argc, char** argv)
{
if (argc < 2) {
print_debugger_command_usage(argv[0]);
return 0;
}
bool printExtents = false;
if (argc > 2 && !strcmp(argv[1], "-p"))
printExtents = true;
FileMap* map = (FileMap*)parse_expression(argv[argc - 1]);
if (map == NULL) {
kprintf("invalid file map!\n");
return 0;
}
kprintf("FileMap %p\n", map);
kprintf(" size %Ld\n", map->Size());
kprintf(" count %lu\n", map->Count());
if (!printExtents)
return 0;
for (uint32 i = 0; i < map->Count(); i++) {
file_extent* extent = map->ExtentAt(i);
kprintf(" [%lu] offset %Ld, disk offset %Ld, length %Ld\n",
i, extent->offset, extent->disk.offset, extent->disk.length);
}
return 0;
}
static int
dump_file_map_stats(int argc, char** argv)
{
off_t minSize = 0;
off_t maxSize = -1;
if (argc == 2) {
maxSize = parse_expression(argv[1]);
} else if (argc > 2) {
minSize = parse_expression(argv[1]);
maxSize = parse_expression(argv[2]);
}
FileMapList::Iterator iterator = sList.GetIterator();
off_t size = 0;
off_t mapSize = 0;
uint32 extents = 0;
uint32 count = 0;
uint32 emptyCount = 0;
while (iterator.HasNext()) {
FileMap* map = iterator.Next();
if (minSize > map->Size() || (maxSize != -1 && maxSize < map->Size()))
continue;
if (map->Count() != 0) {
file_extent* extent = map->ExtentAt(map->Count() - 1);
if (extent != NULL)
mapSize += extent->offset + extent->disk.length;
extents += map->Count();
} else
emptyCount++;
size += map->Size();
count++;
}
kprintf("%ld file maps (%ld empty), %Ld file bytes in total, %Ld bytes "
"cached, %lu extents\n", count, emptyCount, size, mapSize, extents);
kprintf("average %lu extents per map for %Ld bytes.\n",
extents / (count - emptyCount), mapSize / (count - emptyCount));
return 0;
}
#endif // DEBUG_FILE_MAP
// #pragma mark - private kernel API
extern "C" status_t
file_map_init(void)
{
#ifdef DEBUG_FILE_MAP
add_debugger_command_etc("file_map", &dump_file_map,
"Dumps the specified file map.",
"[-p] <file-map>\n"
" -p - causes the file extents to be printed as well.\n"
" <file-map> - pointer to the file map.\n", 0);
add_debugger_command("file_map_stats", &dump_file_map_stats,
"Dumps some file map statistics.");
mutex_init(&sLock, "file map list");
#endif
return B_OK;
}
// #pragma mark - public FS API // #pragma mark - public FS API

View File

@ -4394,6 +4394,8 @@ vfs_init(kernel_args *args)
register_low_memory_handler(&vnode_low_memory_handler, NULL, 0); register_low_memory_handler(&vnode_low_memory_handler, NULL, 0);
file_map_init();
return file_cache_init(); return file_cache_init();
} }