* 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:
parent
0cd3ea3e50
commit
52ecda6ecf
@ -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);
|
||||||
|
|
||||||
|
154
src/system/kernel/cache/file_map.cpp
vendored
154
src/system/kernel/cache/file_map.cpp
vendored
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user