mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-21 03:55:04 +00:00
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:
parent
98b9a24357
commit
82a7799638
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
||||
|
||||
/**********
|
||||
|
@ -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 **
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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_ */
|
||||
|
@ -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 **
|
||||
|
@ -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_ */
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user