rump_fs: add support for session (un-)mounting

Issue #2558.
This commit is contained in:
Josef Söntgen 2017-10-23 11:00:41 +02:00 committed by Christian Helmuth
parent 616352b840
commit f2d063be07
4 changed files with 97 additions and 15 deletions

View File

@ -23,6 +23,11 @@
*/
#define GENODE_DEVICE "/genode"
/**
* Device where to mount the block device
*/
#define GENODE_MOUNT_DIR "/mnt"
void rump_io_backend_init();

View File

@ -85,29 +85,86 @@ void File_system::init()
_print_types();
throw Genode::Exception();
}
Genode::log("Using ", fs_type, " as file system");
/* start rump kernel */
rump_init();
/* register block device */
rump_pub_etfs_register(GENODE_DEVICE, GENODE_BLOCK_SESSION, RUMP_ETFS_BLK);
/* mount into extra-terrestrial-file system */
struct fs_args args;
int opts = check_read_only(fs_type) ? RUMP_MNT_RDONLY : 0;
/* disable access time updates */
opts |= RUMP_MNT_NOATIME;
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 ", errno, " )");
throw Genode::Exception();
}
/* create mount directory */
rump_sys_mkdir(GENODE_MOUNT_DIR, 0777);
/* check support for symlinks */
_supports_symlinks = check_symlinks(fs_type);
}
static int root_fd = -42;
void File_system::mount_fs()
{
/* mount into extra-terrestrial-file system */
struct fs_args args;
args.fspec = (char *)GENODE_DEVICE;
Fs_type const fs_type = Rump::env().config_rom().xml().attribute_value("fs", Fs_type());
int opts = check_read_only(fs_type) ? RUMP_MNT_RDONLY : 0;
opts |= RUMP_MNT_NOATIME;
if (root_fd == -42) {
root_fd = open("/", O_DIRECTORY | O_RDONLY);
if (root_fd == -1) {
Genode::error("opening root directory failed");
throw Genode::Exception();
}
}
int err = rump_sys_mount(fs_type.string(), GENODE_MOUNT_DIR,
opts, &args, sizeof(args));
if (err == -1) {
Genode::error("mounting file system failed (errno ", errno, " )");
throw Genode::Exception();
}
int const mnt_fd = open(GENODE_MOUNT_DIR, O_DIRECTORY | O_RDONLY);
if (mnt_fd == -1) {
Genode::error("opening mnt directory failed");
throw Genode::Exception();
}
err = rump_sys_fchroot(mnt_fd);
if (err == -1) {
Genode::error("fchroot to '", GENODE_MOUNT_DIR, "' failed ",
"(errno ", errno, " )");
throw Genode::Exception();
}
}
void File_system::unmount_fs()
{
/* try to flush all outstanding modifications */
rump_sys_sync();
int err = rump_sys_fchroot(root_fd);
if (err == -1) {
Genode::error("fchroot to '/' failed ", "(errno ", errno, " )");
throw Genode::Exception();
}
bool const force = true;
err = rump_sys_unmount(GENODE_MOUNT_DIR, force ? RUMP_MNT_FORCE : 0);
if (err == -1) {
Genode::error("unmounting file system failed (errno ", errno, " )");
throw Genode::Exception();
}
}
bool File_system::supports_symlinks() { return _supports_symlinks; }

View File

@ -32,6 +32,8 @@ extern "C" {
namespace File_system {
void init();
void mount_fs();
void unmount_fs();
bool supports_symlinks();
}

View File

@ -423,6 +423,8 @@ class Rump_fs::Root : public Root_component<Session_component>
Genode::Env &_env;
int _sessions { 0 };
Genode::Attached_rom_dataspace _config { _env, "config" };
protected:
@ -471,7 +473,7 @@ class Rump_fs::Root : public Root_component<Session_component>
/* determine policy root offset */
try {
policy.attribute("root").value(tmp, sizeof(tmp));
session_root.import(tmp, "/");
session_root.import(tmp, "/mnt");
} catch (Xml_node::Nonexistent_attribute) { }
/*
@ -493,16 +495,32 @@ class Rump_fs::Root : public Root_component<Session_component>
char const *root_dir = session_root.base();
try {
if (++_sessions == 1) { File_system::mount_fs(); }
} catch (...) {
Genode::error("could not mount file system");
throw Service_denied();
}
try {
return new (md_alloc())
Session_component(_env, tx_buf_size, root_dir, writeable, *md_alloc());
}
catch (Lookup_failed) {
} catch (Lookup_failed) {
Genode::error("File system root directory \"", root_dir, "\" does not exist");
throw Service_denied();
}
}
void _destroy_session(Session_component *session)
{
Genode::destroy(md_alloc(), session);
try {
if (--_sessions == 0) { File_system::unmount_fs(); }
} catch (...) { }
}
public:
/**