diff --git a/src/tests/system/kernel/cache/Jamfile b/src/tests/system/kernel/cache/Jamfile index 3a1f3a29d5..d1c935b6ab 100644 --- a/src/tests/system/kernel/cache/Jamfile +++ b/src/tests/system/kernel/cache/Jamfile @@ -21,7 +21,12 @@ SimpleTest block_cache_test : block_cache_test.cpp : libkernelland_emu.so ; +SimpleTest file_map_test : + file_map_test.cpp + file_map.cpp + : libkernelland_emu.so ; + SimpleTest pages_io_test : pages_io_test.cpp - ; +; diff --git a/src/tests/system/kernel/cache/file_map_test.cpp b/src/tests/system/kernel/cache/file_map_test.cpp new file mode 100644 index 0000000000..dd75b56a64 --- /dev/null +++ b/src/tests/system/kernel/cache/file_map_test.cpp @@ -0,0 +1,318 @@ +/* + * Copyright 2009, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include +#include + +#include +#include + +#include + + +#define MAX_VECS 32 + + +class Map { +public: + Map(const char* name, off_t size); + ~Map(); + + void SetTo(const char* name, off_t size); + + Map& Add(off_t offset, off_t length, off_t diskOffset); + Map& Clear(); + Map& SetSize(off_t size); + void Invalidate(off_t start, off_t size); + void SetMode(uint32 mode); + void Test(); + + status_t GetFileMap(off_t offset, off_t length, file_io_vec* vecs, + size_t* _vecCount); + +private: + void _Error(const char* format, ...); + void _Verbose(const char* format, ...); + int32 _IndexFor(off_t offset); + + const char* fName; + uint32 fTest; + void* fMap; + off_t fOffsets[MAX_VECS]; + file_io_vec fVecs[MAX_VECS]; + file_io_vec fTestVecs[MAX_VECS]; + uint32 fCount; + uint32 fTestCount; + off_t fTestOffset; + off_t fTestLength; + off_t fSize; +}; + + +static bool sVerbose; + + +Map::Map(const char* name, off_t size) + : + fName(NULL), + fMap(NULL), + fCount(0), + fSize(0) +{ + SetTo(name, size); +} + + +Map::~Map() +{ + file_map_delete(fMap); +} + + +void +Map::SetTo(const char* name, off_t size) +{ + file_map_delete(fMap); + + fMap = file_map_create((dev_t)this, 0, size); + if (fMap == NULL) + _Error("Creating file map failed."); + + fName = name; + fSize = size; + fCount = 0; + fTest = 0; + + printf("Running %s\n", fName); +} + + +Map& +Map::Add(off_t offset, off_t length, off_t diskOffset) +{ + _Verbose(" Add(): offset %lld, length %lld, diskOffset %lld", offset, + length, diskOffset); + + if (fCount < MAX_VECS) { + fOffsets[fCount] = offset; + fVecs[fCount].offset = diskOffset; + fVecs[fCount].length = length; + fCount++; + } + + return *this; +} + + +Map& +Map::Clear() +{ + _Verbose(" Clear()"); + fCount = 0; + return *this; +} + + +Map& +Map::SetSize(off_t size) +{ + _Verbose(" SetSize(): size %lld", size); + file_map_set_size(fMap, size); + fSize = size; + return *this; +} + + +void +Map::Invalidate(off_t start, off_t size) +{ + _Verbose(" Invalidate(): start %lld, size %lld", start, size); + file_map_invalidate(fMap, start, size); +} + + +void +Map::SetMode(uint32 mode) +{ + file_map_set_mode(fMap, mode); +} + + +void +Map::Test() +{ + printf(" Test %lu\n", ++fTest); + + for (off_t offset = 0; offset < fSize; offset += 256) { + fTestOffset = offset; + fTestLength = 256; + fTestCount = MAX_VECS; + status_t status = file_map_translate(fMap, offset, fTestLength, + fTestVecs, &fTestCount, 0); + if (status != B_OK) { + _Error("file_map_translate(offset %lld) failed: %s", offset, + strerror(status)); + } + + int32 index = _IndexFor(offset); + if (index < 0) + _Error("index for offset %lld not found!", offset); + + off_t diff = offset - fOffsets[index]; + + if (fTestVecs[0].length > fSize - diff) { + _Error("size too large: got %lld, size is %lld", + fTestVecs[0].length, fSize); + } + if (fTestVecs[0].offset != fVecs[index].offset + diff) { + _Error("offset mismatch: got %lld, should be %lld", + fTestVecs[0].offset, fVecs[index].offset + diff); + } + } + + fTestCount = 0; +} + + +status_t +Map::GetFileMap(off_t offset, off_t length, file_io_vec* vecs, + size_t* _vecCount) +{ + int32 index = _IndexFor(offset); + if (index < 0) + _Error("No vec for offset %lld\n", offset); + + _Verbose(" GetFileMap(): offset: %lld, length: %lld, index %ld", offset, + length, index); + + uint32 count = 0; + + while (length > 0) { + if (count >= *_vecCount) + return B_BUFFER_OVERFLOW; + if ((uint32)index >= fCount) + return B_OK; + + off_t diff = offset - fOffsets[index]; + vecs[count].offset = fVecs[index].offset + diff; + vecs[count].length = fVecs[index].length - diff; + _Verbose(" [%lu] offset %lld, length %lld", count, + vecs[count].offset, vecs[count].length); + + length -= vecs[count].length; + offset += vecs[count].length; + index++; + count++; + } + + return B_OK; +} + + +void +Map::_Error(const char* format, ...) +{ + va_list args; + va_start(args, format); + + fprintf(stderr, "ERROR %s: ", fName); + vfprintf(stderr, format, args); + fputc('\n', stderr); + + va_end(args); + + fprintf(stderr, " size %lld\n", fSize); + + for (uint32 i = 0; i < fCount; i++) { + fprintf(stderr, " [%lu] offset %lld, length %lld, disk offset %lld\n", + i, fOffsets[i], fVecs[i].length, fVecs[i].offset); + } + + if (fTestCount > 0) { + fprintf(stderr, "got for offset %lld, length %lld:\n", + fTestOffset, fTestLength); + } + + for (uint32 i = 0; i < fTestCount; i++) { + fprintf(stderr, " [%lu] offset %lld, length %lld\n", + i, fTestVecs[i].offset, fTestVecs[i].length); + } + + fflush(stderr); + + debugger("file map error"); + exit(1); +} + + +void +Map::_Verbose(const char* format, ...) +{ + if (!sVerbose) + return; + + va_list args; + va_start(args, format); + + vprintf(format, args); + putchar('\n'); + + va_end(args); + fflush(stdout); +} + + +int32 +Map::_IndexFor(off_t offset) +{ + for (uint32 i = 0; i < fCount; i++) { + if (offset >= fOffsets[i] && offset < fOffsets[i] + fVecs[i].length) + return i; + } + + return -1; +} + + +// #pragma mark - VFS support functions + + +extern "C" status_t +vfs_get_file_map(struct vnode* vnode, off_t offset, uint32 length, + file_io_vec* vecs, size_t* _vecCount) +{ + Map* map = (Map*)vnode; + return map->GetFileMap(offset, length, vecs, _vecCount); +} + + +extern "C" status_t +vfs_lookup_vnode(dev_t mountID, ino_t vnodeID, struct vnode** _vnode) +{ + *_vnode = (struct vnode*)mountID; + return B_OK; +} + + +// #pragma mark - + + +int +main(int argc, char** argv) +{ + file_map_init(); + sVerbose = true; + + Map map("shrink1", 4096); + map.Add(0, 1024, 4096).Add(1024, 3072, 8192); + map.Test(); + map.SetSize(0).Clear(); + map.Test(); + map.Add(0, 8192, 1000).SetSize(7777); + map.Test(); + + return 0; +}