lib/vfs: pass handle allocator to open(...)

Opening a VFS handle previously involved allocating from the global heap
at each VFS file system. By amending open with an allocator argument,
dynamic allocation can be partitioned.

A new close method is used to deallocate open handles.

Issue #1751
Issue #1891
This commit is contained in:
Emery Hemingway 2016-03-30 15:24:19 +02:00 committed by Christian Helmuth
parent 98b9a24357
commit 82a7799638
11 changed files with 132 additions and 70 deletions

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
* 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.
@ -328,7 +328,8 @@ Libc::File_descriptor *Libc::Vfs_plugin::open(char const *path, int flags,
int Libc::Vfs_plugin::close(Libc::File_descriptor *fd)
{
Genode::destroy(Genode::env()->heap(), vfs_handle(fd));
Vfs::Vfs_handle *handle = vfs_handle(fd);
handle->ds().close(handle);
Libc::file_descriptor_allocator()->free(fd);
return 0;
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2014 Genode Labs GmbH
* Copyright (C) 2011-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.
@ -397,7 +397,10 @@ class Vfs::Dir_file_system : public File_system
return 0;
}
Open_result open(char const *path, unsigned mode, Vfs_handle **out_handle) override
Open_result open(char const *path,
unsigned mode,
Vfs_handle **out_handle,
Allocator &alloc = *Genode::env()->heap()) override
{
/*
* If 'path' is a directory, we create a 'Vfs_handle'
@ -405,7 +408,7 @@ class Vfs::Dir_file_system : public File_system
* are subjected to the stacked file-system layout.
*/
if (is_directory(path)) {
*out_handle = new (env()->heap()) Vfs_handle(*this, *this, 0);
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
}
@ -423,23 +426,32 @@ class Vfs::Dir_file_system : public File_system
/* path equals directory name */
if (strlen(path) == 0) {
*out_handle = new (env()->heap()) Vfs_handle(*this, *this, 0);
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
}
/* path refers to any of our sub file systems */
for (File_system *fs = _first_file_system; fs; fs = fs->next) {
Open_result const err = fs->open(path, mode, out_handle);
if (err == OPEN_OK)
Open_result const err = fs->open(path, mode, out_handle, alloc);
switch (err) {
case OPEN_ERR_UNACCESSIBLE:
continue;
default:
return err;
}
}
/* path does not match any existing file or directory */
return OPEN_ERR_UNACCESSIBLE;
}
void close(Vfs_handle *handle) override
{
if (handle && (&handle->ds() == this))
destroy(handle->alloc(), handle);
}
Unlink_result unlink(char const *path) override
{
auto unlink_fn = [] (File_system &fs, char const *path)

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2014 Genode Labs GmbH
* Copyright (C) 2011-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.
@ -19,6 +19,8 @@
namespace Vfs {
class Vfs_handle;
struct Directory_service;
using Genode::Allocator;
}
@ -56,7 +58,15 @@ struct Vfs::Directory_service
OPEN_OK
};
virtual Open_result open(char const *path, unsigned mode, Vfs_handle **) = 0;
virtual Open_result open(char const *path,
unsigned mode,
Vfs_handle **handle,
Allocator &alloc = *Genode::env()->heap()) = 0;
/**
* Close handle resources and deallocate handle
*/
virtual void close(Vfs_handle *handle) = 0;
/**********

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2014 Genode Labs GmbH
* Copyright (C) 2012-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.
@ -54,17 +54,11 @@ class Vfs::Fs_file_system : public File_system
public:
Fs_vfs_handle(File_system &fs, int status_flags,
::File_system::File_handle handle)
: Vfs_handle(fs, fs, status_flags), _handle(handle)
Fs_vfs_handle(File_system &fs, Allocator &alloc,
int status_flags, ::File_system::File_handle handle)
: Vfs_handle(fs, fs, alloc, status_flags), _handle(handle)
{ }
~Fs_vfs_handle()
{
Fs_file_system &fs = static_cast<Fs_file_system &>(ds());
fs._fs.close(_handle);
}
::File_system::File_handle file_handle() const { return _handle; }
};
@ -521,7 +515,7 @@ class Vfs::Fs_file_system : public File_system
return path;
}
Open_result open(char const *path, unsigned vfs_mode, Vfs_handle **out_handle) override
Open_result open(char const *path, unsigned vfs_mode, Vfs_handle **out_handle, Genode::Allocator& alloc) override
{
Lock::Guard guard(_lock);
@ -554,7 +548,7 @@ class Vfs::Fs_file_system : public File_system
::File_system::File_handle file = _fs.file(dir, file_name.base() + 1,
mode, create);
*out_handle = new (env()->heap()) Fs_vfs_handle(*this, vfs_mode, file);
*out_handle = new (alloc) Fs_vfs_handle(*this, alloc, vfs_mode, file);
}
catch (::File_system::Permission_denied) { return OPEN_ERR_NO_PERM; }
catch (::File_system::Invalid_handle) { return OPEN_ERR_NO_PERM; }
@ -567,6 +561,18 @@ class Vfs::Fs_file_system : public File_system
return OPEN_OK;
}
void close(Vfs_handle *vfs_handle) override
{
Lock::Guard guard(_lock);
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
if (handle) {
_fs.close(handle->file_handle());
destroy(handle->alloc(), handle);
}
}
/***************************
** File_system interface **

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
* Copyright (C) 2015-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.
@ -323,23 +323,20 @@ class Vfs::Ram_file_system : public Vfs::File_system
{
private:
class Ram_vfs_handle : public Vfs_handle
struct Ram_vfs_handle : Vfs_handle
{
private:
Vfs_ram::File &file;
Vfs_ram::File *_file;
public:
Ram_vfs_handle(File_system &fs, int status_flags, Vfs_ram::File *file)
: Vfs_handle(fs, fs, status_flags), _file(file)
{ }
Vfs_ram::File *file() const { return _file; }
Ram_vfs_handle(Ram_file_system &fs,
Allocator &alloc,
int status_flags,
Vfs_ram::File &node)
: Vfs_handle(fs, fs, alloc, status_flags), file(node)
{ }
};
Genode::Allocator &_alloc;
Vfs_ram::Directory _root;
Vfs_ram::Directory _root = { "" };
Vfs_ram::Node *lookup(char const *path, bool return_parent = false)
{
@ -388,7 +385,7 @@ class Vfs::Ram_file_system : public Vfs::File_system
public:
Ram_file_system(Xml_node config)
: _alloc(*env()->heap()), _root("") { }
: _alloc(*env()->heap()) { }
/*********************************
** Directory service interface **
@ -437,7 +434,7 @@ class Vfs::Ram_file_system : public Vfs::File_system
return MKDIR_OK;
}
Open_result open(char const *path, unsigned mode, Vfs_handle **handle) override
Open_result open(char const *path, unsigned mode, Vfs_handle **handle, Genode::Allocator &alloc) override
{
using namespace Vfs_ram;
@ -464,11 +461,21 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (!file) return OPEN_ERR_UNACCESSIBLE;
}
/* allocate handle on the heap */
*handle = new (env()->heap()) Ram_vfs_handle(*this, mode, file);
*handle = new (alloc) Ram_vfs_handle(*this, alloc, mode, *file);
return OPEN_OK;
}
void close(Vfs_handle *vfs_handle) override
{
Ram_vfs_handle *ram_handle =
static_cast<Ram_vfs_handle *>(vfs_handle);
if (ram_handle) {
destroy(_alloc, &ram_handle->file);
destroy(vfs_handle->alloc(), ram_handle);
}
}
Stat_result stat(char const *path, Stat &stat) override
{
using namespace Vfs_ram;
@ -686,8 +693,8 @@ class Vfs::Ram_file_system : public Vfs::File_system
Ram_vfs_handle const *handle =
static_cast<Ram_vfs_handle *>(vfs_handle);
Vfs_ram::Node::Guard guard(handle->file());
out = handle->file()->write(buf, len, handle->seek());
Vfs_ram::Node::Guard guard(&handle->file);
out = handle->file.write(buf, len, handle->seek());
return WRITE_OK;
}
@ -702,9 +709,9 @@ class Vfs::Ram_file_system : public Vfs::File_system
Ram_vfs_handle const *handle =
static_cast<Ram_vfs_handle *>(vfs_handle);
Vfs_ram::Node::Guard guard(handle->file());
Vfs_ram::Node::Guard guard(&handle->file);
out = handle->file()->read(buf, len, handle->seek());
out = handle->file.read(buf, len, handle->seek());
return READ_OK;
}
@ -716,8 +723,8 @@ class Vfs::Ram_file_system : public Vfs::File_system
Ram_vfs_handle const *handle =
static_cast<Ram_vfs_handle *>(vfs_handle);
Vfs_ram::Node::Guard guard(handle->file());
handle->file()->truncate(len);
Vfs_ram::Node::Guard guard(&handle->file);
handle->file.truncate(len);
return FTRUNCATE_OK;
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
* 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.
@ -71,11 +71,12 @@ class Vfs::Rom_file_system : public Single_file_system
* Overwrite the default open function to update the ROM dataspace
* each time when opening the corresponding file.
*/
Open_result open(char const *path, unsigned,
Vfs_handle **out_handle) override
Open_result open(char const *path, unsigned,
Vfs_handle **out_handle,
Allocator &alloc) override
{
Open_result const result =
Single_file_system::open(path, 0, out_handle);
Single_file_system::open(path, 0, out_handle, alloc);
_rom.update();

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
* 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.
@ -127,16 +127,23 @@ class Vfs::Single_file_system : public File_system
return _is_single_file(path) ? path : 0;
}
Open_result open(char const *path, unsigned,
Vfs_handle **out_handle) override
Open_result open(char const *path, unsigned,
Vfs_handle **out_handle,
Allocator &alloc) override
{
if (!_is_single_file(path))
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (env()->heap()) Vfs_handle(*this, *this, 0);
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
}
void close(Vfs_handle *handle) override
{
if (handle && (&handle->ds() == this))
destroy(handle->alloc(), handle);
}
Unlink_result unlink(char const *) override
{
return UNLINK_ERR_NO_PERM;

View File

@ -6,7 +6,7 @@
*/
/*
* Copyright (C) 2015 Genode Labs GmbH
* Copyright (C) 2015-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.
@ -131,10 +131,12 @@ class Vfs::Symlink_file_system : public File_system
void release(char const *path, Dataspace_capability ds_cap) override { }
Open_result open(char const *path, unsigned,
Vfs_handle **out_handle) override {
Open_result open(char const *, unsigned, Vfs_handle **out_handle,
Allocator&) override {
return OPEN_ERR_UNACCESSIBLE; }
void close(Vfs_handle *) override { }
Unlink_result unlink(char const *) override {
return UNLINK_ERR_NO_PERM; }
@ -171,4 +173,4 @@ class Vfs::Symlink_file_system : public File_system
};
#endif /* _INCLUDE__VFS__SYMLINK_FILE_SYSTEM_H_ */
#endif /* _INCLUDE__VFS__SYMLINK_FILE_SYSTEM_H_ */

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2014 Genode Labs GmbH
* Copyright (C) 2011-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.
@ -102,8 +102,8 @@ class Vfs::Tar_file_system : public File_system
public:
Tar_vfs_handle(File_system &fs, int status_flags, Record const *record)
: Vfs_handle(fs, fs, status_flags), _record(record)
Tar_vfs_handle(File_system &fs, Allocator &alloc, int status_flags, Record const *record)
: Vfs_handle(fs, fs, alloc, status_flags), _record(record)
{ }
Record const *record() const { return _record; }
@ -573,18 +573,26 @@ class Vfs::Tar_file_system : public File_system
return node ? path : 0;
}
Open_result open(char const *path, unsigned, Vfs_handle **out_handle) override
Open_result open(char const *path, unsigned, Vfs_handle **out_handle, Genode::Allocator& alloc) override
{
Node const *node = dereference(path);
if (!node || !node->record || node->record->type() != Record::TYPE_FILE)
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (env()->heap())
Tar_vfs_handle(*this, 0, node->record);
*out_handle = new (alloc) Tar_vfs_handle(*this, alloc, 0, node->record);
return OPEN_OK;
}
void close(Vfs_handle *vfs_handle) override
{
Tar_vfs_handle *tar_handle =
static_cast<Tar_vfs_handle *>(vfs_handle);
if (tar_handle)
destroy(vfs_handle->alloc(), tar_handle);
}
/***************************
** File_system interface **

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2011-2014 Genode Labs GmbH
* Copyright (C) 2011-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.
@ -26,8 +26,9 @@ class Vfs::Vfs_handle
Directory_service &_ds;
File_io_service &_fs;
Genode::Allocator &_alloc;
int _status_flags;
file_size _seek;
file_size _seek = 0;
public:
@ -40,21 +41,27 @@ class Vfs::Vfs_handle
~Guard()
{
if (handle)
Genode::destroy(Genode::env()->heap(), handle);
handle->_ds.close(handle);
}
};
enum { STATUS_RDONLY = 0, STATUS_WRONLY = 1, STATUS_RDWR = 2 };
Vfs_handle(Directory_service &ds, File_io_service &fs, int status_flags)
Vfs_handle(Directory_service &ds,
File_io_service &fs,
Genode::Allocator &alloc,
int status_flags)
:
_ds(ds), _fs(fs), _status_flags(status_flags), _seek(0)
_ds(ds), _fs(fs),
_alloc(alloc),
_status_flags(status_flags)
{ }
virtual ~Vfs_handle() { }
Directory_service &ds() { return _ds; }
File_io_service &fs() { return _fs; }
Allocator &alloc() { return _alloc; }
int status_flags() const { return _status_flags; }
@ -76,4 +83,5 @@ class Vfs::Vfs_handle
void advance_seek(file_size incr) { _seek += incr; }
};
#endif /* _INCLUDE__VFS__VFS_HANDLE_H_ */

View File

@ -41,7 +41,7 @@ namespace Noux {
~Vfs_io_channel()
{
_sig_rec.dissolve(this);
destroy(env()->heap(), _fh);
_fh->ds().close(_fh);
}
bool write(Sysio *sysio, size_t &offset) override