mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-25 08:21:08 +00:00
Rump kernel VFS plugin
Tests at libc_vfs_ext2, libc_vfs_fs_ext2. Fix #1752 Ref #2224
This commit is contained in:
parent
ec6cff7ba8
commit
4c7ab07480
repos/dde_rump
lib/mk
run
src/lib/vfs/rump
tool
6
repos/dde_rump/lib/mk/vfs_rump.mk
Normal file
6
repos/dde_rump/lib/mk/vfs_rump.mk
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
SRC_CC = vfs_rump.cc random.cc
|
||||||
|
LIBS = rump rump_fs
|
||||||
|
INC_DIR += $(REP_DIR)/src/lib/vfs/rump
|
||||||
|
vpath %.cc $(REP_DIR)/src/lib/vfs/rump
|
||||||
|
|
||||||
|
SHARED_LIB = yes
|
99
repos/dde_rump/run/libc_vfs_ext2.run
Normal file
99
repos/dde_rump/run/libc_vfs_ext2.run
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
if {[have_spec arm]} {
|
||||||
|
assert_spec arm_v7
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check used commands
|
||||||
|
#
|
||||||
|
set mke2fs [check_installed mke2fs]
|
||||||
|
set dd [check_installed dd]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build
|
||||||
|
#
|
||||||
|
set build_components {
|
||||||
|
core init
|
||||||
|
drivers/timer
|
||||||
|
server/ram_blk
|
||||||
|
lib/vfs/rump
|
||||||
|
test/libc_vfs
|
||||||
|
}
|
||||||
|
|
||||||
|
build $build_components
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build EXT2-file-system image
|
||||||
|
#
|
||||||
|
catch { exec $dd if=/dev/zero of=bin/ext2.raw bs=1M count=16 }
|
||||||
|
catch { exec $mke2fs -F bin/ext2.raw }
|
||||||
|
|
||||||
|
create_boot_directory
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate config
|
||||||
|
#
|
||||||
|
append config {
|
||||||
|
<config>
|
||||||
|
<parent-provides>
|
||||||
|
<service name="CPU"/>
|
||||||
|
<service name="IO_MEM"/>
|
||||||
|
<service name="IO_PORT"/>
|
||||||
|
<service name="IRQ"/>
|
||||||
|
<service name="LOG"/>
|
||||||
|
<service name="PD"/>
|
||||||
|
<service name="RAM"/>
|
||||||
|
<service name="RM"/>
|
||||||
|
<service name="ROM"/>
|
||||||
|
</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="ram_blk">
|
||||||
|
<resource name="RAM" quantum="20M"/>
|
||||||
|
<provides><service name="Block"/></provides>
|
||||||
|
<config file="ext2.raw" block_size="512"/>
|
||||||
|
</start>
|
||||||
|
<start name="test-libc_vfs">
|
||||||
|
<resource name="RAM" quantum="10M"/>
|
||||||
|
<config>
|
||||||
|
<libc stdout="/dev/log">
|
||||||
|
<vfs>
|
||||||
|
<dir name="dev"> <log/> </dir>
|
||||||
|
<rump fs="ext2fs" writeable="yes"/>
|
||||||
|
</vfs>
|
||||||
|
</libc>
|
||||||
|
</config>
|
||||||
|
</start>
|
||||||
|
</config>}
|
||||||
|
|
||||||
|
install_config $config
|
||||||
|
|
||||||
|
#
|
||||||
|
# Boot modules
|
||||||
|
#
|
||||||
|
|
||||||
|
# generic modules
|
||||||
|
set boot_modules {
|
||||||
|
core ld.lib.so init
|
||||||
|
libc.lib.so
|
||||||
|
libm.lib.so
|
||||||
|
ram_blk
|
||||||
|
rump_fs.lib.so
|
||||||
|
rump.lib.so
|
||||||
|
test-libc_vfs
|
||||||
|
timer
|
||||||
|
vfs_rump.lib.so
|
||||||
|
ext2.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
|
append qemu_args " -m 256 -nographic"
|
||||||
|
|
||||||
|
run_genode_until {.*child "test-libc_vfs" exited with exit value 0.*} 60
|
||||||
|
|
||||||
|
exec rm -f bin/ext2.raw
|
109
repos/dde_rump/run/libc_vfs_fs_ext2.run
Normal file
109
repos/dde_rump/run/libc_vfs_fs_ext2.run
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
if {[have_spec arm]} {
|
||||||
|
assert_spec arm_v7
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check used commands
|
||||||
|
#
|
||||||
|
set mke2fs [check_installed mke2fs]
|
||||||
|
set dd [check_installed dd]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build
|
||||||
|
#
|
||||||
|
set build_components {
|
||||||
|
core init
|
||||||
|
drivers/timer
|
||||||
|
server/ram_blk
|
||||||
|
lib/vfs/rump
|
||||||
|
server/vfs
|
||||||
|
test/libc_vfs
|
||||||
|
}
|
||||||
|
|
||||||
|
build $build_components
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build EXT2-file-system image
|
||||||
|
#
|
||||||
|
catch { exec $dd if=/dev/zero of=bin/ext2.raw bs=1M count=16 }
|
||||||
|
catch { exec $mke2fs -F bin/ext2.raw }
|
||||||
|
|
||||||
|
create_boot_directory
|
||||||
|
|
||||||
|
#
|
||||||
|
# Generate config
|
||||||
|
#
|
||||||
|
append config {
|
||||||
|
<config>
|
||||||
|
<parent-provides>
|
||||||
|
<service name="CPU"/>
|
||||||
|
<service name="IO_MEM"/>
|
||||||
|
<service name="IO_PORT"/>
|
||||||
|
<service name="IRQ"/>
|
||||||
|
<service name="LOG"/>
|
||||||
|
<service name="PD"/>
|
||||||
|
<service name="RAM"/>
|
||||||
|
<service name="RM"/>
|
||||||
|
<service name="ROM"/>
|
||||||
|
</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="ram_blk">
|
||||||
|
<resource name="RAM" quantum="20M"/>
|
||||||
|
<provides><service name="Block"/></provides>
|
||||||
|
<config file="ext2.raw" block_size="512"/>
|
||||||
|
</start>
|
||||||
|
<start name="vfs">
|
||||||
|
<resource name="RAM" quantum="10M"/>
|
||||||
|
<provides><service name="File_system"/></provides>
|
||||||
|
<config>
|
||||||
|
<vfs> <rump fs="ext2fs"/> </vfs>
|
||||||
|
<policy label_prefix="test-libc_vfs" root="/" writeable="yes"/>
|
||||||
|
</config>
|
||||||
|
</start>
|
||||||
|
<start name="test-libc_vfs">
|
||||||
|
<resource name="RAM" quantum="10M"/>
|
||||||
|
<config>
|
||||||
|
<libc stdout="/dev/log">
|
||||||
|
<vfs>
|
||||||
|
<dir name="dev"> <log/> </dir>
|
||||||
|
<fs/>
|
||||||
|
</vfs>
|
||||||
|
</libc>
|
||||||
|
</config>
|
||||||
|
</start>
|
||||||
|
</config>}
|
||||||
|
|
||||||
|
install_config $config
|
||||||
|
|
||||||
|
#
|
||||||
|
# Boot modules
|
||||||
|
#
|
||||||
|
|
||||||
|
# generic modules
|
||||||
|
set boot_modules {
|
||||||
|
core ld.lib.so init
|
||||||
|
libc.lib.so
|
||||||
|
libm.lib.so
|
||||||
|
ram_blk
|
||||||
|
rump_fs.lib.so
|
||||||
|
rump.lib.so
|
||||||
|
test-libc_vfs
|
||||||
|
timer
|
||||||
|
vfs
|
||||||
|
vfs_rump.lib.so
|
||||||
|
ext2.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
|
append qemu_args " -m 256 -nographic"
|
||||||
|
|
||||||
|
run_genode_until {.*child "test-libc_vfs" exited with exit value 0.*} 60
|
||||||
|
|
||||||
|
exec rm -f bin/ext2.raw
|
69
repos/dde_rump/run/vfs_stress_ext2.run
Normal file
69
repos/dde_rump/run/vfs_stress_ext2.run
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#
|
||||||
|
# \brief VFS stress test
|
||||||
|
# \author Emery Hemingway
|
||||||
|
# \date 2015-08-30
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check used commands
|
||||||
|
#
|
||||||
|
set mke2fs [check_installed mke2fs]
|
||||||
|
set dd [check_installed dd]
|
||||||
|
|
||||||
|
build "core init drivers/timer test/vfs_stress server/ram_blk lib/vfs/rump"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build EXT2-file-system image
|
||||||
|
#
|
||||||
|
catch { exec $dd if=/dev/zero of=bin/ext2.raw bs=1M count=16 }
|
||||||
|
catch { exec $mke2fs -F bin/ext2.raw }
|
||||||
|
|
||||||
|
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="ram_blk">
|
||||||
|
<resource name="RAM" quantum="24M"/>
|
||||||
|
<provides><service name="Block"/></provides>
|
||||||
|
<config file="ext2.raw" block_size="512"/>
|
||||||
|
</start>
|
||||||
|
<start name="vfs_stress">
|
||||||
|
<resource name="RAM" quantum="32M"/>
|
||||||
|
<config depth="8">
|
||||||
|
<vfs> <rump fs="ext2fs" writeable="yes"/> </vfs>
|
||||||
|
</config>
|
||||||
|
</start>
|
||||||
|
</config>
|
||||||
|
}
|
||||||
|
|
||||||
|
set boot_modules {
|
||||||
|
core init ld.lib.so timer vfs_stress
|
||||||
|
rump.lib.so rump_fs.lib.so vfs_rump.lib.so
|
||||||
|
ram_blk ext2.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
|
append qemu_args "-nographic -smp cpus=6"
|
||||||
|
|
||||||
|
run_genode_until {child "vfs_stress" exited with exit value 0} 180
|
||||||
|
|
||||||
|
exec rm -f bin/ext2.raw
|
76
repos/dde_rump/run/vfs_stress_rump_fs.run
Normal file
76
repos/dde_rump/run/vfs_stress_rump_fs.run
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
#
|
||||||
|
# \brief VFS stress test
|
||||||
|
# \author Emery Hemingway
|
||||||
|
# \date 2015-08-30
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# Check used commands
|
||||||
|
#
|
||||||
|
set mke2fs [check_installed mke2fs]
|
||||||
|
set dd [check_installed dd]
|
||||||
|
|
||||||
|
build "core init drivers/timer test/vfs_stress server/ram_blk server/rump_fs"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Build EXT2-file-system image
|
||||||
|
#
|
||||||
|
catch { exec $dd if=/dev/zero of=bin/ext2.raw bs=1M count=16 }
|
||||||
|
catch { exec $mke2fs -F bin/ext2.raw }
|
||||||
|
|
||||||
|
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="32M"/>
|
||||||
|
<config depth="32" threads="1">
|
||||||
|
<vfs> <fs/> </vfs>
|
||||||
|
</config>
|
||||||
|
</start>
|
||||||
|
<start name="ram_blk">
|
||||||
|
<resource name="RAM" quantum="24M"/>
|
||||||
|
<provides><service name="Block"/></provides>
|
||||||
|
<config file="ext2.raw" block_size="512"/>
|
||||||
|
</start>
|
||||||
|
<start name="rump_fs">
|
||||||
|
<resource name="RAM" quantum="24M"/>
|
||||||
|
<provides> <service name="File_system"/> </provides>
|
||||||
|
<config fs="ext2fs">
|
||||||
|
<policy label="" root="/" writeable="yes"/>
|
||||||
|
</config>
|
||||||
|
</start>
|
||||||
|
</config>
|
||||||
|
}
|
||||||
|
|
||||||
|
set boot_modules {
|
||||||
|
core init ld.lib.so timer vfs_stress
|
||||||
|
rump.lib.so rump_fs.lib.so rump_fs
|
||||||
|
ram_blk ext2.raw
|
||||||
|
}
|
||||||
|
|
||||||
|
build_boot_image $boot_modules
|
||||||
|
|
||||||
|
append qemu_args "-nographic -smp cpus=6"
|
||||||
|
|
||||||
|
run_genode_until {child "vfs_stress" exited with exit value 0} 180
|
||||||
|
|
||||||
|
exec rm -f bin/ext2.raw
|
5
repos/dde_rump/src/lib/vfs/rump/README
Normal file
5
repos/dde_rump/src/lib/vfs/rump/README
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
The vfs_rump plugin enables access to block device backed file systems
|
||||||
|
supported by the rump kernel. A single rump kernel is in use for any
|
||||||
|
number of <rump> nodes. The configuration node takes two arguments:
|
||||||
|
'fs' specifies the file system type, and 'writeable' specifies if the
|
||||||
|
mount is read only or writeable, 'writeable' defaults to true.
|
21
repos/dde_rump/src/lib/vfs/rump/random.cc
Normal file
21
repos/dde_rump/src/lib/vfs/rump/random.cc
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/**
|
||||||
|
* \brief Dummy random support
|
||||||
|
* \author Sebastian Sumpf
|
||||||
|
* \date 2015-02-16
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <util/random.h>
|
||||||
|
|
||||||
|
|
||||||
|
int rumpuser_getrandom_backend(void *buf, Genode::size_t buflen, int flags, Genode::size_t *retp)
|
||||||
|
{
|
||||||
|
*retp = buflen;
|
||||||
|
return 0;
|
||||||
|
}
|
2
repos/dde_rump/src/lib/vfs/rump/target.mk
Normal file
2
repos/dde_rump/src/lib/vfs/rump/target.mk
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
TARGET = rump_plugin
|
||||||
|
LIBS = vfs_rump
|
550
repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc
Normal file
550
repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc
Normal file
@ -0,0 +1,550 @@
|
|||||||
|
/*
|
||||||
|
* \brief Rump VFS plugin
|
||||||
|
* \author Christian Helmuth
|
||||||
|
* \author Sebastian Sumpf
|
||||||
|
* \author Emery Hemingway
|
||||||
|
* \date 2015-09-05
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014-2016 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <rump/env.h>
|
||||||
|
#include <rump_fs/fs.h>
|
||||||
|
#include <vfs/file_system_factory.h>
|
||||||
|
#include <vfs/vfs_handle.h>
|
||||||
|
#include <timer_session/connection.h>
|
||||||
|
#include <os/path.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
#include <sys/errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/dirent.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <rump/rump.h>
|
||||||
|
#include <rump/rump_syscalls.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
extern int errno;
|
||||||
|
|
||||||
|
namespace Vfs { struct Rump_file_system; };
|
||||||
|
|
||||||
|
static void _rump_sync()
|
||||||
|
{
|
||||||
|
/* sync through front-end */
|
||||||
|
rump_sys_sync();
|
||||||
|
|
||||||
|
/* sync Genode back-end */
|
||||||
|
rump_io_backend_sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char const *fs_types[] = { RUMP_MOUNT_CD9660, RUMP_MOUNT_EXT2FS,
|
||||||
|
RUMP_MOUNT_FFS, RUMP_MOUNT_MSDOS,
|
||||||
|
RUMP_MOUNT_NTFS, RUMP_MOUNT_UDF, 0 };
|
||||||
|
|
||||||
|
class Vfs::Rump_file_system : public File_system
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum { BUFFER_SIZE = 4096 };
|
||||||
|
|
||||||
|
typedef Genode::Path<MAX_PATH_LEN> Path;
|
||||||
|
|
||||||
|
class Rump_vfs_handle : public Vfs_handle
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
int _fd;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Rump_vfs_handle(File_system &fs, Allocator &alloc,
|
||||||
|
int status_flags, int fd)
|
||||||
|
: Vfs_handle(fs, fs, alloc, status_flags), _fd(fd) { }
|
||||||
|
|
||||||
|
~Rump_vfs_handle() { rump_sys_close(_fd); }
|
||||||
|
|
||||||
|
int fd() const { return _fd; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We define our own fs arg structure to fit all sizes, we assume that 'fspec'
|
||||||
|
* is the only valid argument and all other fields are unused.
|
||||||
|
*/
|
||||||
|
struct fs_args
|
||||||
|
{
|
||||||
|
char *fspec;
|
||||||
|
char pad[150];
|
||||||
|
|
||||||
|
fs_args() { Genode::memset(pad, 0, sizeof(pad)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool _check_type(char const *type)
|
||||||
|
{
|
||||||
|
for (int i = 0; fs_types[i]; i++)
|
||||||
|
if (!Genode::strcmp(type, fs_types[i]))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _print_types()
|
||||||
|
{
|
||||||
|
Genode::error("fs types:");
|
||||||
|
for (int i = 0; fs_types[i]; ++i)
|
||||||
|
Genode::error("\t", fs_types[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *_buffer()
|
||||||
|
{
|
||||||
|
/* buffer for directory entries */
|
||||||
|
static char buf[BUFFER_SIZE];
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirent_result _dirent(char const *path,
|
||||||
|
struct ::dirent *dent, Dirent &vfs_dir)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We cannot use 'd_type' member of 'dirent' here since the EXT2
|
||||||
|
* implementation sets the type to unkown. Hence we use stat.
|
||||||
|
*/
|
||||||
|
struct stat s;
|
||||||
|
rump_sys_lstat(path, &s);
|
||||||
|
|
||||||
|
if (S_ISREG(s.st_mode))
|
||||||
|
vfs_dir.type = Dirent_type::DIRENT_TYPE_FILE;
|
||||||
|
else if (S_ISDIR(s.st_mode))
|
||||||
|
vfs_dir.type = Dirent_type::DIRENT_TYPE_DIRECTORY;
|
||||||
|
else if (S_ISLNK(s.st_mode))
|
||||||
|
vfs_dir.type = Dirent_type::DIRENT_TYPE_SYMLINK;
|
||||||
|
else if (S_ISBLK(s.st_mode))
|
||||||
|
vfs_dir.type = Dirent_type::DIRENT_TYPE_BLOCKDEV;
|
||||||
|
else if (S_ISCHR(s.st_mode))
|
||||||
|
vfs_dir.type = Dirent_type::DIRENT_TYPE_CHARDEV;
|
||||||
|
else if (S_ISFIFO(s.st_mode))
|
||||||
|
vfs_dir.type = Dirent_type::DIRENT_TYPE_FIFO;
|
||||||
|
else
|
||||||
|
vfs_dir.type = Dirent_type::DIRENT_TYPE_FILE;
|
||||||
|
|
||||||
|
strncpy(vfs_dir.name, dent->d_name, sizeof(Dirent::name));
|
||||||
|
|
||||||
|
return DIRENT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Rump_file_system(Xml_node const &config)
|
||||||
|
{
|
||||||
|
typedef Genode::String<16> Fs_type;
|
||||||
|
|
||||||
|
Fs_type fs_type = config.attribute_value("fs", Fs_type());
|
||||||
|
|
||||||
|
if (!_check_type(fs_type.string())) {
|
||||||
|
Genode::error("Invalid or no file system given (use \'<rump fs=\"<fs type>\"/>)");
|
||||||
|
_print_types();
|
||||||
|
throw Genode::Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* mount into extra-terrestrial-file system */
|
||||||
|
struct fs_args args;
|
||||||
|
int opts = config.attribute_value("writeable", true) ?
|
||||||
|
0 : RUMP_MNT_RDONLY;
|
||||||
|
|
||||||
|
args.fspec = (char *)GENODE_DEVICE;
|
||||||
|
if (rump_sys_mount(fs_type.string(), "/", opts, &args, sizeof(args)) == -1) {
|
||||||
|
Genode::error("Mounting '",fs_type,"' file system failed (",errno,")");
|
||||||
|
throw Genode::Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
Genode::log(fs_type," file system mounted");
|
||||||
|
}
|
||||||
|
|
||||||
|
/***************************
|
||||||
|
** File_system interface **
|
||||||
|
***************************/
|
||||||
|
|
||||||
|
static char const *name() { return "rump"; }
|
||||||
|
|
||||||
|
|
||||||
|
/*********************************
|
||||||
|
** Directory service interface **
|
||||||
|
*********************************/
|
||||||
|
|
||||||
|
void sync(char const *path) override {
|
||||||
|
_rump_sync(); }
|
||||||
|
|
||||||
|
Genode::Dataspace_capability dataspace(char const *path) override
|
||||||
|
{
|
||||||
|
int fd = rump_sys_open(path, O_RDONLY);
|
||||||
|
if (fd == -1) return Genode::Dataspace_capability();
|
||||||
|
|
||||||
|
struct stat s;
|
||||||
|
if (rump_sys_lstat(path, &s) != 0) return Genode::Dataspace_capability();
|
||||||
|
size_t const ds_size = s.st_size;
|
||||||
|
|
||||||
|
char *local_addr = nullptr;
|
||||||
|
Ram_dataspace_capability ds_cap;
|
||||||
|
try {
|
||||||
|
ds_cap = env()->ram_session()->alloc(ds_size);
|
||||||
|
|
||||||
|
local_addr = env()->rm_session()->attach(ds_cap);
|
||||||
|
|
||||||
|
enum { CHUNK_SIZE = 16U << 10 };
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ds_size;) {
|
||||||
|
ssize_t n = rump_sys_read(fd, &local_addr[i], min(ds_size-i, CHUNK_SIZE));
|
||||||
|
if (n == -1)
|
||||||
|
throw n;
|
||||||
|
i += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
env()->rm_session()->detach(local_addr);
|
||||||
|
} catch(...) {
|
||||||
|
if (local_addr)
|
||||||
|
env()->rm_session()->detach(local_addr);
|
||||||
|
env()->ram_session()->free(ds_cap);
|
||||||
|
}
|
||||||
|
rump_sys_close(fd);
|
||||||
|
return ds_cap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release(char const *path,
|
||||||
|
Genode::Dataspace_capability ds_cap) override
|
||||||
|
{
|
||||||
|
if (ds_cap.valid())
|
||||||
|
env()->ram_session()->free(
|
||||||
|
static_cap_cast<Genode::Ram_dataspace>(ds_cap));
|
||||||
|
}
|
||||||
|
|
||||||
|
file_size num_dirent(char const *path) override
|
||||||
|
{
|
||||||
|
file_size n = 0;
|
||||||
|
int fd = rump_sys_open(*path ? path : "/", O_RDONLY | O_DIRECTORY);
|
||||||
|
if (fd == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
rump_sys_lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
int bytes = 0;
|
||||||
|
char *buf = _buffer();
|
||||||
|
do {
|
||||||
|
bytes = rump_sys_getdents(fd, buf, BUFFER_SIZE);
|
||||||
|
void *current, *end;
|
||||||
|
for (current = buf, end = &buf[bytes];
|
||||||
|
current < end;
|
||||||
|
current = _DIRENT_NEXT((::dirent *)current))
|
||||||
|
{
|
||||||
|
struct ::dirent *dent = (::dirent *)current;
|
||||||
|
if (strcmp(".", dent->d_name) && strcmp("..", dent->d_name))
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
} while(bytes);
|
||||||
|
|
||||||
|
rump_sys_close(fd);
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool directory(char const *path) override
|
||||||
|
{
|
||||||
|
struct stat s;
|
||||||
|
if (rump_sys_lstat(path, &s) != 0) return false;
|
||||||
|
return S_ISDIR(s.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
char const *leaf_path(char const *path) override
|
||||||
|
{
|
||||||
|
struct stat s;
|
||||||
|
return (rump_sys_lstat(path, &s) == 0) ? path : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Mkdir_result mkdir(char const *path, unsigned mode) override
|
||||||
|
{
|
||||||
|
if (rump_sys_mkdir(path, mode|0777) != 0) switch (::errno) {
|
||||||
|
case ENAMETOOLONG: return MKDIR_ERR_NAME_TOO_LONG;
|
||||||
|
case EACCES: return MKDIR_ERR_NO_PERM;
|
||||||
|
case ENOENT: return MKDIR_ERR_NO_ENTRY;
|
||||||
|
case EEXIST: return MKDIR_ERR_EXISTS;
|
||||||
|
case ENOSPC: return MKDIR_ERR_NO_SPACE;
|
||||||
|
default:
|
||||||
|
return MKDIR_ERR_NO_PERM;
|
||||||
|
}
|
||||||
|
return MKDIR_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Open_result open(char const *path, unsigned mode,
|
||||||
|
Vfs_handle **handle,
|
||||||
|
Allocator &alloc) override
|
||||||
|
{
|
||||||
|
/* OPEN_MODE_CREATE (or O_EXC) will not work */
|
||||||
|
if (mode & OPEN_MODE_CREATE)
|
||||||
|
mode |= O_CREAT;
|
||||||
|
|
||||||
|
int fd = rump_sys_open(path, mode);
|
||||||
|
if (fd == -1) switch (errno) {
|
||||||
|
case ENAMETOOLONG: return OPEN_ERR_NAME_TOO_LONG;
|
||||||
|
case EACCES: return OPEN_ERR_NO_PERM;
|
||||||
|
case ENOENT: return OPEN_ERR_UNACCESSIBLE;
|
||||||
|
case EEXIST: return OPEN_ERR_EXISTS;
|
||||||
|
case ENOSPC: return OPEN_ERR_NO_SPACE;
|
||||||
|
default:
|
||||||
|
return OPEN_ERR_NO_PERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
*handle = new (alloc) Rump_vfs_handle(*this, alloc, mode, fd);
|
||||||
|
return OPEN_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close(Vfs_handle *vfs_handle) override
|
||||||
|
{
|
||||||
|
Rump_vfs_handle *rump_handle =
|
||||||
|
static_cast<Rump_vfs_handle *>(vfs_handle);
|
||||||
|
|
||||||
|
if (rump_handle)
|
||||||
|
destroy(vfs_handle->alloc(), rump_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
Stat_result stat(char const *path, Stat &stat)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
if (rump_sys_lstat(path, &sb) != 0) return STAT_ERR_NO_ENTRY;
|
||||||
|
|
||||||
|
stat.size = sb.st_size;
|
||||||
|
stat.mode = sb.st_mode;
|
||||||
|
stat.uid = sb.st_uid;
|
||||||
|
stat.gid = sb.st_gid;
|
||||||
|
stat.inode = sb.st_ino;
|
||||||
|
stat.device = sb.st_dev;
|
||||||
|
|
||||||
|
return STAT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dirent_result dirent(char const *path, file_offset index_,
|
||||||
|
Dirent &vfs_dir) override
|
||||||
|
{
|
||||||
|
int fd = rump_sys_open(*path ? path : "/", O_RDONLY | O_DIRECTORY);
|
||||||
|
if (fd == -1)
|
||||||
|
return DIRENT_ERR_INVALID_PATH;
|
||||||
|
|
||||||
|
rump_sys_lseek(fd, 0, SEEK_SET);
|
||||||
|
|
||||||
|
int bytes;
|
||||||
|
unsigned const index = index_;
|
||||||
|
vfs_dir.fileno = 0;
|
||||||
|
char *buf = _buffer();
|
||||||
|
struct ::dirent *dent = nullptr;
|
||||||
|
do {
|
||||||
|
bytes = rump_sys_getdents(fd, buf, BUFFER_SIZE);
|
||||||
|
void *current, *end;
|
||||||
|
for (current = buf, end = &buf[bytes];
|
||||||
|
current < end;
|
||||||
|
current = _DIRENT_NEXT((::dirent *)current))
|
||||||
|
{
|
||||||
|
dent = (::dirent *)current;
|
||||||
|
if (strcmp(".", dent->d_name) && strcmp("..", dent->d_name)) {
|
||||||
|
if (vfs_dir.fileno++ == index) {
|
||||||
|
Path newpath(dent->d_name, path);
|
||||||
|
rump_sys_close(fd);
|
||||||
|
return _dirent(newpath.base(), dent, vfs_dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (bytes > 0);
|
||||||
|
rump_sys_close(fd);
|
||||||
|
|
||||||
|
vfs_dir.type = DIRENT_TYPE_END;
|
||||||
|
vfs_dir.name[0] = '\0';
|
||||||
|
return DIRENT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Unlink_result unlink(char const *path) override
|
||||||
|
{
|
||||||
|
struct stat s;
|
||||||
|
if (rump_sys_lstat(path, &s) == -1)
|
||||||
|
return UNLINK_ERR_NO_ENTRY;
|
||||||
|
|
||||||
|
if (S_ISDIR(s.st_mode)) {
|
||||||
|
if (rump_sys_rmdir(path) == 0) return UNLINK_OK;
|
||||||
|
} else {
|
||||||
|
if (rump_sys_unlink(path) == 0) return UNLINK_OK;
|
||||||
|
}
|
||||||
|
switch (errno) {
|
||||||
|
case ENOENT: return UNLINK_ERR_NO_ENTRY;
|
||||||
|
case ENOTEMPTY: return UNLINK_ERR_NOT_EMPTY;
|
||||||
|
}
|
||||||
|
return UNLINK_ERR_NO_PERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
Readlink_result readlink(char const *path, char *buf,
|
||||||
|
file_size buf_size, file_size &out_len) override
|
||||||
|
{
|
||||||
|
ssize_t n = rump_sys_readlink(path, buf, buf_size);
|
||||||
|
if (n == -1) {
|
||||||
|
out_len = 0;
|
||||||
|
return READLINK_ERR_NO_ENTRY;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_len = n;
|
||||||
|
return READLINK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Symlink_result symlink(char const *from, char const *to) override
|
||||||
|
{
|
||||||
|
if (rump_sys_symlink(from, to) != 0) switch (errno) {
|
||||||
|
case EEXIST: {
|
||||||
|
if (rump_sys_readlink(to, NULL, 0) == -1)
|
||||||
|
return SYMLINK_ERR_EXISTS;
|
||||||
|
rump_sys_unlink(to);
|
||||||
|
return rump_sys_symlink(from, to) == 0 ?
|
||||||
|
SYMLINK_OK : SYMLINK_ERR_EXISTS;
|
||||||
|
}
|
||||||
|
case ENOENT: return SYMLINK_ERR_NO_ENTRY;
|
||||||
|
case ENOSPC: return SYMLINK_ERR_NO_SPACE;
|
||||||
|
case EACCES: return SYMLINK_ERR_NO_PERM;
|
||||||
|
case ENAMETOOLONG: return SYMLINK_ERR_NAME_TOO_LONG;
|
||||||
|
default:
|
||||||
|
return SYMLINK_ERR_NO_PERM;
|
||||||
|
}
|
||||||
|
return SYMLINK_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rename_result rename(char const *from, char const *to) override
|
||||||
|
{
|
||||||
|
if (rump_sys_rename(from, to) != 0) switch (errno) {
|
||||||
|
case ENOENT: return RENAME_ERR_NO_ENTRY;
|
||||||
|
case EXDEV: return RENAME_ERR_CROSS_FS;
|
||||||
|
case EACCES: return RENAME_ERR_NO_PERM;
|
||||||
|
}
|
||||||
|
return RENAME_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************
|
||||||
|
** File io service interface **
|
||||||
|
*******************************/
|
||||||
|
|
||||||
|
Write_result write(Vfs_handle *vfs_handle,
|
||||||
|
char const *buf, file_size buf_size,
|
||||||
|
file_size &out_count) override
|
||||||
|
{
|
||||||
|
Rump_vfs_handle *handle =
|
||||||
|
static_cast<Rump_vfs_handle *>(vfs_handle);
|
||||||
|
|
||||||
|
ssize_t n = rump_sys_pwrite(handle->fd(), buf, buf_size, handle->seek());
|
||||||
|
if (n == -1) switch (errno) {
|
||||||
|
case EWOULDBLOCK: return WRITE_ERR_WOULD_BLOCK;
|
||||||
|
case EINVAL: return WRITE_ERR_INVALID;
|
||||||
|
case EIO: return WRITE_ERR_IO;
|
||||||
|
case EINTR: return WRITE_ERR_INTERRUPT;
|
||||||
|
default:
|
||||||
|
return WRITE_ERR_IO;
|
||||||
|
}
|
||||||
|
out_count = n;
|
||||||
|
return WRITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Read_result read(Vfs_handle *vfs_handle, char *buf, file_size buf_size,
|
||||||
|
file_size &out_count) override
|
||||||
|
{
|
||||||
|
Rump_vfs_handle *handle =
|
||||||
|
static_cast<Rump_vfs_handle *>(vfs_handle);
|
||||||
|
|
||||||
|
ssize_t n = rump_sys_pread(handle->fd(), buf, buf_size, handle->seek());
|
||||||
|
if (n == -1) switch (errno) {
|
||||||
|
case EWOULDBLOCK: return READ_ERR_WOULD_BLOCK;
|
||||||
|
case EINVAL: return READ_ERR_INVALID;
|
||||||
|
case EIO: return READ_ERR_IO;
|
||||||
|
case EINTR: return READ_ERR_INTERRUPT;
|
||||||
|
default:
|
||||||
|
return READ_ERR_IO;
|
||||||
|
}
|
||||||
|
out_count = n;
|
||||||
|
return READ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ftruncate_result ftruncate(Vfs_handle *vfs_handle, file_size len) override
|
||||||
|
{
|
||||||
|
Rump_vfs_handle *handle =
|
||||||
|
static_cast<Rump_vfs_handle *>(vfs_handle);
|
||||||
|
|
||||||
|
if (rump_sys_ftruncate(handle->fd(), len) != 0) switch (errno) {
|
||||||
|
case EACCES: return FTRUNCATE_ERR_NO_PERM;
|
||||||
|
case EINTR: return FTRUNCATE_ERR_INTERRUPT;
|
||||||
|
case ENOSPC: return FTRUNCATE_ERR_NO_SPACE;
|
||||||
|
default:
|
||||||
|
return FTRUNCATE_ERR_NO_PERM;
|
||||||
|
}
|
||||||
|
return FTRUNCATE_OK;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Rump_factory : public Vfs::File_system_factory
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
Timer::Connection _timer;
|
||||||
|
Genode::Signal_handler<Rump_factory> _sync_handler;
|
||||||
|
|
||||||
|
void _sync() { _rump_sync(); }
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Rump_factory(Genode::Env &env, Genode::Allocator &alloc)
|
||||||
|
: _timer(env, "rump-sync"),
|
||||||
|
_sync_handler(env.ep(), *this, &Rump_factory::_sync)
|
||||||
|
{
|
||||||
|
Rump::construct_env(env);
|
||||||
|
|
||||||
|
rump_io_backend_init();
|
||||||
|
|
||||||
|
/* start rump kernel */
|
||||||
|
rump_init();
|
||||||
|
|
||||||
|
/* register block device */
|
||||||
|
rump_pub_etfs_register(
|
||||||
|
GENODE_DEVICE, GENODE_BLOCK_SESSION, RUMP_ETFS_BLK);
|
||||||
|
|
||||||
|
/* set all bits but the stickies */
|
||||||
|
rump_sys_umask(S_ISUID|S_ISGID|S_ISVTX);
|
||||||
|
|
||||||
|
/* start syncing */
|
||||||
|
enum { TEN_SEC = 10*1000*1000 };
|
||||||
|
_timer.sigh(_sync_handler);
|
||||||
|
_timer.trigger_periodic(TEN_SEC);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Vfs::File_system *create(Genode::Env &env,
|
||||||
|
Genode::Allocator &alloc,
|
||||||
|
Genode::Xml_node config) override
|
||||||
|
{
|
||||||
|
return new (alloc) Vfs::Rump_file_system(config);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" Vfs::File_system_factory *vfs_file_system_factory(void)
|
||||||
|
{
|
||||||
|
struct Extern_factory : Vfs::File_system_factory
|
||||||
|
{
|
||||||
|
Vfs::File_system *create(Genode::Env &env,
|
||||||
|
Genode::Allocator &alloc,
|
||||||
|
Genode::Xml_node node) override
|
||||||
|
{
|
||||||
|
static Rump_factory factory(env, alloc);
|
||||||
|
return factory.create(env, alloc, node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static Extern_factory factory;
|
||||||
|
return &factory;
|
||||||
|
}
|
@ -45,6 +45,7 @@ part_blk
|
|||||||
xml_generator
|
xml_generator
|
||||||
blk_cache
|
blk_cache
|
||||||
rump_ext2
|
rump_ext2
|
||||||
|
libc_vfs_ext2
|
||||||
thread
|
thread
|
||||||
pthread
|
pthread
|
||||||
vbox_auto_win7
|
vbox_auto_win7
|
||||||
|
Loading…
Reference in New Issue
Block a user