mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-16 15:29:57 +00:00
parent
cdb44850d3
commit
1b4f894e2d
49
repos/os/run/vfs_stress_fs.run
Normal file
49
repos/os/run/vfs_stress_fs.run
Normal file
@ -0,0 +1,49 @@
|
||||
#
|
||||
# \brief VFS stress test
|
||||
# \author Emery Hemingway
|
||||
# \date 2015-08-30
|
||||
#
|
||||
|
||||
build "core init drivers/timer server/ram_fs test/vfs_stress"
|
||||
|
||||
create_boot_directory
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<affinity-space width="3" height="2" />
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="vfs_stress">
|
||||
<resource name="RAM" quantum="8M"/>
|
||||
<config depth="16"> <vfs> <fs/> </vfs> </config>
|
||||
</start>
|
||||
<start name="ram_fs">
|
||||
<resource name="RAM" quantum="1G"/>
|
||||
<provides><service name="File_system"/></provides>
|
||||
<config>
|
||||
<policy label="" root="/" writeable="yes"/>
|
||||
</config>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
build_boot_image "core init ld.lib.so timer ram_fs vfs_stress"
|
||||
|
||||
append qemu_args "-nographic -smp cpus=6"
|
||||
|
||||
run_genode_until ".*child \"vfs_stress\" exited with exit value 0.*" 180
|
42
repos/os/run/vfs_stress_ram.run
Normal file
42
repos/os/run/vfs_stress_ram.run
Normal file
@ -0,0 +1,42 @@
|
||||
#
|
||||
# \brief VFS stress test
|
||||
# \author Emery Hemingway
|
||||
# \date 2015-08-30
|
||||
#
|
||||
|
||||
build "core init drivers/timer test/vfs_stress"
|
||||
|
||||
create_boot_directory
|
||||
|
||||
install_config {
|
||||
<config>
|
||||
<affinity-space width="3" height="2" />
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="RAM"/>
|
||||
<service name="CAP"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
<service name="SIGNAL"/>
|
||||
</parent-provides>
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
<start name="vfs_stress">
|
||||
<resource name="RAM" quantum="1G"/>
|
||||
<config depth="16"> <vfs> <ram/> </vfs> </config>
|
||||
</start>
|
||||
</config>
|
||||
}
|
||||
|
||||
build_boot_image "core init ld.lib.so timer vfs_stress"
|
||||
|
||||
append qemu_args "-nographic -smp cpus=6"
|
||||
|
||||
run_genode_until ".*child \"vfs_stress\" exited with exit value 0.*" 600
|
7
repos/os/src/test/vfs_stress/README
Normal file
7
repos/os/src/test/vfs_stress/README
Normal file
@ -0,0 +1,7 @@
|
||||
Vfs_stress populates, writes, and reads a file system using multiple threads.
|
||||
The following attributes on the <config> node control test behaviour:
|
||||
* depth - maximum tree depth, defaults to sixteen
|
||||
* threads - number of threads to start, defaults to six
|
||||
* write - perform write test
|
||||
* read - perform read test
|
||||
* unlink - unlink all generated files
|
659
repos/os/src/test/vfs_stress/main.cc
Normal file
659
repos/os/src/test/vfs_stress/main.cc
Normal file
@ -0,0 +1,659 @@
|
||||
/*
|
||||
* \brief File system stress tester
|
||||
* \author Emery Hemingway
|
||||
* \date 2015-08-29
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU General Public License version 2.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This test populates the VFS as follows:
|
||||
*
|
||||
* A directory is created at root for each thread with
|
||||
* sequential names. For each of these directories, a
|
||||
* subtree is generated until the maximum path depth
|
||||
* is reached at each branch. The subtree is layed out
|
||||
* like this:
|
||||
*
|
||||
* a
|
||||
* |\
|
||||
* a b
|
||||
* |\ \
|
||||
* a b b
|
||||
* |\ \ \
|
||||
* a b b b
|
||||
* |\ \ \ \
|
||||
* . . . . .
|
||||
*
|
||||
*/
|
||||
|
||||
/* Genode includes */
|
||||
#include <vfs/file_system_factory.h>
|
||||
#include <vfs/dir_file_system.h>
|
||||
#include <timer_session/connection.h>
|
||||
#include <base/process.h>
|
||||
#include <os/config.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/snprintf.h>
|
||||
#include <base/exception.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
inline void assert_mkdir(Vfs::Directory_service::Mkdir_result r)
|
||||
{
|
||||
typedef Vfs::Directory_service::Mkdir_result Result;
|
||||
|
||||
switch (r) {
|
||||
case Result::MKDIR_OK: return;
|
||||
case Result::MKDIR_ERR_EXISTS:
|
||||
PERR("MKDIR_ERR_EXISTS"); break;
|
||||
case Result::MKDIR_ERR_NO_ENTRY:
|
||||
PERR("MKDIR_ERR_NO_ENTRY"); break;
|
||||
case Result::MKDIR_ERR_NO_SPACE:
|
||||
PERR("MKDIR_ERR_NO_SPACE"); break;
|
||||
case Result::MKDIR_ERR_NO_PERM:
|
||||
PERR("MKDIR_ERR_NO_PERM"); break;
|
||||
case Result::MKDIR_ERR_NAME_TOO_LONG:
|
||||
PERR("MKDIR_ERR_NAME_TOO_LONG"); break;
|
||||
}
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
inline void assert_open(Vfs::Directory_service::Open_result r)
|
||||
{
|
||||
typedef Vfs::Directory_service::Open_result Result;
|
||||
switch (r) {
|
||||
case Result::OPEN_OK: return;
|
||||
case Result::OPEN_ERR_NAME_TOO_LONG:
|
||||
PERR("OPEN_ERR_NAME_TOO_LONG"); break;
|
||||
case Result::OPEN_ERR_UNACCESSIBLE:
|
||||
PERR("OPEN_ERR_UNACCESSIBLE"); break;
|
||||
case Result::OPEN_ERR_NO_SPACE:
|
||||
PERR("OPEN_ERR_NO_SPACE"); break;
|
||||
case Result::OPEN_ERR_NO_PERM:
|
||||
PERR("OPEN_ERR_NO_PERM"); break;
|
||||
case Result::OPEN_ERR_EXISTS:
|
||||
PERR("OPEN_ERR_EXISTS"); break;
|
||||
}
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
inline void assert_write(Vfs::File_io_service::Write_result r)
|
||||
{
|
||||
typedef Vfs::File_io_service::Write_result Result;
|
||||
switch (r) {
|
||||
case Result::WRITE_OK: return;
|
||||
case Result::WRITE_ERR_AGAIN:
|
||||
PERR("WRITE_ERR_AGAIN"); break;
|
||||
case Result::WRITE_ERR_WOULD_BLOCK:
|
||||
PERR("WRITE_ERR_WOULD_BLOCK"); break;
|
||||
case Result::WRITE_ERR_INVALID:
|
||||
PERR("WRITE_ERR_INVALID"); break;
|
||||
case Result::WRITE_ERR_IO:
|
||||
PERR("WRITE_ERR_IO"); break;
|
||||
case Result::WRITE_ERR_INTERRUPT:
|
||||
PERR("WRITE_ERR_INTERRUPT"); break;
|
||||
}
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
inline void assert_read(Vfs::File_io_service::Read_result r)
|
||||
{
|
||||
typedef Vfs::File_io_service::Read_result Result;
|
||||
switch (r) {
|
||||
case Result::READ_OK: return;
|
||||
case Result::READ_ERR_AGAIN:
|
||||
PERR("READ_ERR_AGAIN"); break;
|
||||
case Result::READ_ERR_WOULD_BLOCK:
|
||||
PERR("READ_ERR_WOULD_BLOCK"); break;
|
||||
case Result::READ_ERR_INVALID:
|
||||
PERR("READ_ERR_INVALID"); break;
|
||||
case Result::READ_ERR_IO:
|
||||
PERR("READ_ERR_IO"); break;
|
||||
case Result::READ_ERR_INTERRUPT:
|
||||
PERR("READ_ERR_INTERRUPT"); break;
|
||||
}
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
inline void assert_unlink(Vfs::Directory_service::Unlink_result r)
|
||||
{
|
||||
typedef Vfs::Directory_service::Unlink_result Result;
|
||||
switch (r) {
|
||||
case Result::UNLINK_OK: return;
|
||||
case Result::UNLINK_ERR_NO_ENTRY:
|
||||
PERR("UNLINK_ERR_NO_ENTRY"); break;
|
||||
case Result::UNLINK_ERR_NO_PERM:
|
||||
PERR("UNLINK_ERR_NO_PERM"); break;
|
||||
}
|
||||
throw Exception();
|
||||
}
|
||||
|
||||
static int MAX_DEPTH;
|
||||
|
||||
typedef Genode::Path<Vfs::MAX_PATH_LEN> Path;
|
||||
|
||||
|
||||
struct Stress_thread : public Genode::Thread<4*1024*sizeof(Genode::addr_t)>
|
||||
{
|
||||
::Path path;
|
||||
Vfs::file_size count;
|
||||
Vfs::File_system &vfs;
|
||||
|
||||
Stress_thread(Vfs::File_system &vfs, char const *parent)
|
||||
: Thread(parent), path(parent), count(0), vfs(vfs) { }
|
||||
};
|
||||
|
||||
|
||||
struct Mkdir_thread : public Stress_thread
|
||||
{
|
||||
Mkdir_thread(Vfs::File_system &vfs, char const *parent)
|
||||
: Stress_thread(vfs, parent) { start(); }
|
||||
|
||||
void mkdir_b(int depth)
|
||||
{
|
||||
if (++depth > MAX_DEPTH) return;
|
||||
|
||||
path.append("/b");
|
||||
assert_mkdir(vfs.mkdir(path.base(), 0));
|
||||
++count;
|
||||
mkdir_b(depth);
|
||||
}
|
||||
|
||||
void mkdir_a(int depth)
|
||||
{
|
||||
if (++depth > MAX_DEPTH) return;
|
||||
|
||||
size_t path_len = strlen(path.base());
|
||||
|
||||
path.append("/b");
|
||||
assert_mkdir(vfs.mkdir(path.base(), 0));
|
||||
++count;
|
||||
mkdir_b(depth);
|
||||
|
||||
path.base()[path_len] = '\0';
|
||||
|
||||
path.append("/a");
|
||||
assert_mkdir(vfs.mkdir(path.base(), 0));
|
||||
++count;
|
||||
mkdir_a(depth);
|
||||
}
|
||||
|
||||
void entry()
|
||||
{
|
||||
try { mkdir_a(1); } catch (...) {
|
||||
PERR("failed at %s after %llu directories", path.base(), count);
|
||||
}
|
||||
}
|
||||
|
||||
int wait()
|
||||
{
|
||||
join();
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Populate_thread : public Stress_thread
|
||||
{
|
||||
Populate_thread(Vfs::File_system &vfs, char const *parent)
|
||||
: Stress_thread(vfs, parent) { start(); }
|
||||
|
||||
|
||||
void populate(int depth)
|
||||
{
|
||||
if (++depth > MAX_DEPTH) return;
|
||||
|
||||
using namespace Vfs;
|
||||
|
||||
size_t path_len = 1+strlen(path.base());
|
||||
char dir_type = *(path.base()+(path_len-2));
|
||||
|
||||
path.append("/c");
|
||||
{
|
||||
Vfs_handle *handle = nullptr;
|
||||
assert_open(vfs.open(
|
||||
path.base(), Directory_service::OPEN_MODE_CREATE, &handle));
|
||||
Vfs_handle::Guard guard(handle);
|
||||
++count;
|
||||
}
|
||||
|
||||
switch (dir_type) {
|
||||
case 'a':
|
||||
path.base()[path_len] = '\0';
|
||||
path.append("a");
|
||||
populate(depth);
|
||||
|
||||
case 'b':
|
||||
path.base()[path_len] = '\0';
|
||||
path.append("b");
|
||||
populate(depth);
|
||||
return;
|
||||
|
||||
default:
|
||||
PERR("bad directory %c at the end of %s", dir_type, path.base());
|
||||
throw Exception();
|
||||
}
|
||||
}
|
||||
|
||||
void entry()
|
||||
{
|
||||
::Path start_path(path.base());
|
||||
try {
|
||||
path.append("/a");
|
||||
populate(1);
|
||||
|
||||
path.import(start_path.base());
|
||||
path.append("/b");
|
||||
populate(1);
|
||||
} catch (...) {
|
||||
PERR("failed at %s after %llu files", path.base(), count);
|
||||
}
|
||||
}
|
||||
|
||||
int wait()
|
||||
{
|
||||
join();
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Write_thread : public Stress_thread
|
||||
{
|
||||
Write_thread(Vfs::File_system &vfs, char const *parent)
|
||||
: Stress_thread(vfs, parent) { start(); }
|
||||
|
||||
void write(int depth)
|
||||
{
|
||||
if (++depth > MAX_DEPTH) return;
|
||||
|
||||
size_t path_len = 1+strlen(path.base());
|
||||
char dir_type = *(path.base()+(path_len-2));
|
||||
|
||||
using namespace Vfs;
|
||||
|
||||
path.append("/c");
|
||||
{
|
||||
Vfs_handle *handle = nullptr;
|
||||
assert_open(vfs.open(
|
||||
path.base(), Directory_service::OPEN_MODE_WRONLY, &handle));
|
||||
Vfs_handle::Guard guard(handle);
|
||||
|
||||
file_size n;
|
||||
assert_write(handle->fs().write(
|
||||
handle, path.base(), path_len, n));
|
||||
count += n;
|
||||
}
|
||||
|
||||
switch (dir_type) {
|
||||
case 'a':
|
||||
path.base()[path_len] = '\0';
|
||||
path.append("a");
|
||||
write(depth);
|
||||
|
||||
case 'b':
|
||||
path.base()[path_len] = '\0';
|
||||
path.append("b");
|
||||
write(depth);
|
||||
return;
|
||||
|
||||
default:
|
||||
PERR("bad directory %c at the end of %s", dir_type, path.base());
|
||||
throw Exception();
|
||||
}
|
||||
}
|
||||
|
||||
void entry()
|
||||
{
|
||||
size_t path_len = strlen(path.base());
|
||||
try {
|
||||
path.append("/a");
|
||||
write(1);
|
||||
|
||||
path.base()[path_len] = '\0';
|
||||
path.append("/b");
|
||||
write(1);
|
||||
} catch (...) {
|
||||
PERR("failed at %s after writing %llu bytes", path.base(), count);
|
||||
}
|
||||
}
|
||||
|
||||
Vfs::file_size wait()
|
||||
{
|
||||
join();
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Read_thread : public Stress_thread
|
||||
{
|
||||
Read_thread(Vfs::File_system &vfs, char const *parent)
|
||||
: Stress_thread(vfs, parent) { start(); }
|
||||
|
||||
void read(int depth)
|
||||
{
|
||||
if (++depth > MAX_DEPTH) return;
|
||||
|
||||
size_t path_len = 1+strlen(path.base());
|
||||
char dir_type = *(path.base()+(path_len-2));
|
||||
|
||||
using namespace Vfs;
|
||||
|
||||
path.append("/c");
|
||||
{
|
||||
Vfs_handle *handle = nullptr;
|
||||
assert_open(vfs.open(
|
||||
path.base(), Directory_service::OPEN_MODE_RDONLY, &handle));
|
||||
Vfs_handle::Guard guard(handle);
|
||||
|
||||
char tmp[MAX_PATH_LEN];
|
||||
file_size n;
|
||||
assert_read(handle->fs().read(handle, tmp, sizeof(tmp), n));
|
||||
if (strcmp(path.base(), tmp, n))
|
||||
PERR("read returned bad data");
|
||||
count += n;
|
||||
}
|
||||
|
||||
switch (dir_type) {
|
||||
case 'a':
|
||||
path.base()[path_len] = '\0';
|
||||
path.append("a");
|
||||
read(depth);
|
||||
|
||||
case 'b':
|
||||
path.base()[path_len] = '\0';
|
||||
path.append("/b");
|
||||
read(depth);
|
||||
return;
|
||||
|
||||
default:
|
||||
PERR("bad directory %c at the end of %s", dir_type, path.base());
|
||||
throw Exception();
|
||||
}
|
||||
}
|
||||
|
||||
void entry()
|
||||
{
|
||||
size_t path_len = strlen(path.base());
|
||||
try {
|
||||
path.append("/a");
|
||||
read(1);
|
||||
|
||||
path.base()[path_len] = '\0';
|
||||
path.append("/b");
|
||||
read(1);
|
||||
} catch (...) {
|
||||
PERR("failed at %s after reading %llu bytes", path.base(), count);
|
||||
}
|
||||
}
|
||||
|
||||
Vfs::file_size wait()
|
||||
{
|
||||
join();
|
||||
return count;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
struct Unlink_thread : public Stress_thread
|
||||
{
|
||||
Unlink_thread(Vfs::File_system &vfs, char const *parent)
|
||||
: Stress_thread(vfs, parent) { start(); }
|
||||
|
||||
void empty_dir(char const *path)
|
||||
{
|
||||
::Path subpath(path);
|
||||
subpath.append("/");
|
||||
|
||||
Vfs::Directory_service::Dirent dirent;
|
||||
for (Vfs::file_size i = vfs.num_dirent(path); i;) {
|
||||
vfs.dirent(path, --i, dirent);
|
||||
subpath.append(dirent.name);
|
||||
switch (dirent.type) {
|
||||
case Vfs::Directory_service::DIRENT_TYPE_END:
|
||||
PERR("reached the end prematurely");
|
||||
throw Exception();
|
||||
|
||||
case Vfs::Directory_service::DIRENT_TYPE_DIRECTORY:
|
||||
empty_dir(subpath.base());
|
||||
|
||||
default:
|
||||
try {
|
||||
assert_unlink(vfs.unlink(subpath.base()));
|
||||
} catch (...) {
|
||||
PERR("unlink %s failed", subpath.base());
|
||||
throw;
|
||||
}
|
||||
subpath.strip_last_element();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void entry()
|
||||
{
|
||||
try {
|
||||
empty_dir(path.base());
|
||||
vfs.unlink(path.base());
|
||||
} catch (...) { }
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
/* look for dynamic linker */
|
||||
try {
|
||||
static Genode::Rom_connection rom("ld.lib.so");
|
||||
Genode::Process::dynamic_linker(rom.dataspace());
|
||||
} catch (...) { }
|
||||
|
||||
static Vfs::Dir_file_system vfs_root(config()->xml_node().sub_node("vfs"),
|
||||
Vfs::global_file_system_factory());
|
||||
static char path[Vfs::MAX_PATH_LEN];
|
||||
|
||||
MAX_DEPTH = config()->xml_node().attribute_value("depth", 16U);
|
||||
unsigned thread_count =
|
||||
config()->xml_node().attribute_value("threads", 6U);
|
||||
|
||||
unsigned long elapsed_ms;
|
||||
Timer::Connection timer;
|
||||
|
||||
/* populate the directory file system at / */
|
||||
vfs_root.num_dirent("/");
|
||||
|
||||
size_t initial_consumption = env()->ram_session()->used();
|
||||
|
||||
/**************************
|
||||
** Generate directories **
|
||||
**************************/
|
||||
{
|
||||
int count = 0;
|
||||
Mkdir_thread *threads[thread_count];
|
||||
PLOG("generating directory surface...");
|
||||
elapsed_ms = timer.elapsed_ms();
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
snprintf(path, 3, "/%lu", i);
|
||||
vfs_root.mkdir(path, 0);
|
||||
threads[i] = new (Genode::env()->heap())
|
||||
Mkdir_thread(vfs_root, path);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
count += threads[i]->wait();
|
||||
destroy(Genode::env()->heap(), threads[i]);
|
||||
}
|
||||
elapsed_ms = timer.elapsed_ms() - elapsed_ms;
|
||||
|
||||
vfs_root.sync("/");
|
||||
|
||||
PINF("created %d empty directories, %luμs/op , %luKB consumed",
|
||||
count, (elapsed_ms*1000)/count, env()->ram_session()->used()/1024);
|
||||
}
|
||||
|
||||
|
||||
/********************
|
||||
** Generate files **
|
||||
********************/
|
||||
{
|
||||
int count = 0;
|
||||
Populate_thread *threads[thread_count];
|
||||
PLOG("generating files...");
|
||||
elapsed_ms = timer.elapsed_ms();
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
snprintf(path, 3, "/%lu", i);
|
||||
vfs_root.mkdir(path, 0);
|
||||
threads[i] = new (Genode::env()->heap())
|
||||
Populate_thread(vfs_root, path);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
count += threads[i]->wait();
|
||||
destroy(Genode::env()->heap(), threads[i]);
|
||||
}
|
||||
|
||||
elapsed_ms = timer.elapsed_ms() - elapsed_ms;
|
||||
|
||||
vfs_root.sync("/");
|
||||
|
||||
PINF("created %d empty files, %luμs/op, %luKB consumed",
|
||||
count, (elapsed_ms*1000)/count, env()->ram_session()->used()/1024);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Write files **
|
||||
*****************/
|
||||
|
||||
if (!config()->xml_node().attribute_value("write", true)) {
|
||||
elapsed_ms = timer.elapsed_ms();
|
||||
|
||||
PINF("total: %lums, %luK consumed",
|
||||
elapsed_ms, env()->ram_session()->used()/1024);
|
||||
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Vfs::file_size count = 0;
|
||||
Write_thread *threads[thread_count];
|
||||
PLOG("writing files...");
|
||||
elapsed_ms = timer.elapsed_ms();
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
snprintf(path, 3, "/%lu", i);
|
||||
vfs_root.mkdir(path, 0);
|
||||
threads[i] = new (Genode::env()->heap())
|
||||
Write_thread(vfs_root, path);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
count += threads[i]->wait();
|
||||
destroy(Genode::env()->heap(), threads[i]);
|
||||
}
|
||||
|
||||
elapsed_ms = timer.elapsed_ms() - elapsed_ms;
|
||||
|
||||
vfs_root.sync("/");
|
||||
|
||||
PINF("wrote %llu bytes %llukB/s, %luKB consumed",
|
||||
count, count/elapsed_ms, env()->ram_session()->used()/1024);
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
** Read files **
|
||||
*****************/
|
||||
|
||||
if (!config()->xml_node().attribute_value("read", true)) {
|
||||
elapsed_ms = timer.elapsed_ms();
|
||||
|
||||
PINF("total: %lums, %luKB consumed",
|
||||
elapsed_ms, env()->ram_session()->used()/1024);
|
||||
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Vfs::file_size count = 0;
|
||||
Read_thread *threads[thread_count];
|
||||
PLOG("reading files...");
|
||||
elapsed_ms = timer.elapsed_ms();
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
snprintf(path, 3, "/%lu", i);
|
||||
vfs_root.mkdir(path, 0);
|
||||
threads[i] = new (Genode::env()->heap())
|
||||
Read_thread(vfs_root, path);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
count += threads[i]->wait();
|
||||
destroy(Genode::env()->heap(), threads[i]);
|
||||
}
|
||||
|
||||
elapsed_ms = timer.elapsed_ms() - elapsed_ms;
|
||||
|
||||
vfs_root.sync("/");
|
||||
|
||||
PINF("read %llu bytes, %llukB/s, %luKB consumed",
|
||||
count, count/elapsed_ms, env()->ram_session()->used()/1024);
|
||||
}
|
||||
|
||||
|
||||
/******************
|
||||
** Unlink files **
|
||||
******************/
|
||||
|
||||
if (!config()->xml_node().attribute_value("unlink", true)) {
|
||||
elapsed_ms = timer.elapsed_ms();
|
||||
|
||||
PINF("total: %lums, %luKB consumed",
|
||||
elapsed_ms, env()->ram_session()->used()/1024);
|
||||
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
Unlink_thread *threads[thread_count];
|
||||
PLOG("unlink files...");
|
||||
elapsed_ms = timer.elapsed_ms();
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
snprintf(path, 3, "/%lu", i);
|
||||
vfs_root.mkdir(path, 0);
|
||||
threads[i] = new (Genode::env()->heap())
|
||||
Unlink_thread(vfs_root, path);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < thread_count; ++i) {
|
||||
threads[i]->join();
|
||||
destroy(Genode::env()->heap(), threads[i]);
|
||||
}
|
||||
|
||||
elapsed_ms = timer.elapsed_ms() - elapsed_ms;
|
||||
|
||||
vfs_root.sync("/");
|
||||
|
||||
PINF("unlink in %lums, %luKB consumed",
|
||||
elapsed_ms, env()->ram_session()->used()/1024);
|
||||
}
|
||||
|
||||
PINF("total: %lums, %luKB consumed",
|
||||
timer.elapsed_ms(), env()->ram_session()->used()/1024);
|
||||
|
||||
size_t outstanding = env()->ram_session()->used() - initial_consumption;
|
||||
if (outstanding) {
|
||||
if (outstanding < 1024)
|
||||
PERR("%luB not freed after unlink and sync!", outstanding);
|
||||
else
|
||||
PERR("%luKB not freed after unlink and sync!", outstanding/1024);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
3
repos/os/src/test/vfs_stress/target.mk
Normal file
3
repos/os/src/test/vfs_stress/target.mk
Normal file
@ -0,0 +1,3 @@
|
||||
TARGET = vfs_stress
|
||||
SRC_CC = main.cc
|
||||
LIBS = base vfs
|
Loading…
x
Reference in New Issue
Block a user