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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * 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) 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); Libc::file_descriptor_allocator()->free(fd);
return 0; 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * 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; 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' * 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. * are subjected to the stacked file-system layout.
*/ */
if (is_directory(path)) { 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; return OPEN_OK;
} }
@ -423,23 +426,32 @@ class Vfs::Dir_file_system : public File_system
/* path equals directory name */ /* path equals directory name */
if (strlen(path) == 0) { 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; return OPEN_OK;
} }
/* path refers to any of our sub file systems */ /* path refers to any of our sub file systems */
for (File_system *fs = _first_file_system; fs; fs = fs->next) { for (File_system *fs = _first_file_system; fs; fs = fs->next) {
Open_result const err = fs->open(path, mode, out_handle); Open_result const err = fs->open(path, mode, out_handle, alloc);
switch (err) {
if (err == OPEN_OK) case OPEN_ERR_UNACCESSIBLE:
continue;
default:
return err; return err;
} }
}
/* path does not match any existing file or directory */ /* path does not match any existing file or directory */
return OPEN_ERR_UNACCESSIBLE; 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 Unlink_result unlink(char const *path) override
{ {
auto unlink_fn = [] (File_system &fs, char const *path) 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -19,6 +19,8 @@
namespace Vfs { namespace Vfs {
class Vfs_handle; class Vfs_handle;
struct Directory_service; struct Directory_service;
using Genode::Allocator;
} }
@ -56,7 +58,15 @@ struct Vfs::Directory_service
OPEN_OK 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -54,17 +54,11 @@ class Vfs::Fs_file_system : public File_system
public: public:
Fs_vfs_handle(File_system &fs, int status_flags, Fs_vfs_handle(File_system &fs, Allocator &alloc,
::File_system::File_handle handle) int status_flags, ::File_system::File_handle handle)
: Vfs_handle(fs, fs, status_flags), _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; } ::File_system::File_handle file_handle() const { return _handle; }
}; };
@ -521,7 +515,7 @@ class Vfs::Fs_file_system : public File_system
return path; 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); 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, ::File_system::File_handle file = _fs.file(dir, file_name.base() + 1,
mode, create); 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::Permission_denied) { return OPEN_ERR_NO_PERM; }
catch (::File_system::Invalid_handle) { 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; 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 ** ** 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * 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: private:
class Ram_vfs_handle : public Vfs_handle struct Ram_vfs_handle : Vfs_handle
{ {
private: Vfs_ram::File &file;
Vfs_ram::File *_file; Ram_vfs_handle(Ram_file_system &fs,
Allocator &alloc,
public: int status_flags,
Vfs_ram::File &node)
Ram_vfs_handle(File_system &fs, int status_flags, Vfs_ram::File *file) : Vfs_handle(fs, fs, alloc, status_flags), file(node)
: Vfs_handle(fs, fs, status_flags), _file(file)
{ } { }
Vfs_ram::File *file() const { return _file; }
}; };
Genode::Allocator &_alloc; Genode::Allocator &_alloc;
Vfs_ram::Directory _root; Vfs_ram::Directory _root = { "" };
Vfs_ram::Node *lookup(char const *path, bool return_parent = false) 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: public:
Ram_file_system(Xml_node config) Ram_file_system(Xml_node config)
: _alloc(*env()->heap()), _root("") { } : _alloc(*env()->heap()) { }
/********************************* /*********************************
** Directory service interface ** ** Directory service interface **
@ -437,7 +434,7 @@ class Vfs::Ram_file_system : public Vfs::File_system
return MKDIR_OK; 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; using namespace Vfs_ram;
@ -464,11 +461,21 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (!file) return OPEN_ERR_UNACCESSIBLE; if (!file) return OPEN_ERR_UNACCESSIBLE;
} }
/* allocate handle on the heap */ *handle = new (alloc) Ram_vfs_handle(*this, alloc, mode, *file);
*handle = new (env()->heap()) Ram_vfs_handle(*this, mode, file);
return OPEN_OK; 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 Stat_result stat(char const *path, Stat &stat) override
{ {
using namespace Vfs_ram; using namespace Vfs_ram;
@ -686,8 +693,8 @@ class Vfs::Ram_file_system : public Vfs::File_system
Ram_vfs_handle const *handle = Ram_vfs_handle const *handle =
static_cast<Ram_vfs_handle *>(vfs_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()->write(buf, len, handle->seek()); out = handle->file.write(buf, len, handle->seek());
return WRITE_OK; return WRITE_OK;
} }
@ -702,9 +709,9 @@ class Vfs::Ram_file_system : public Vfs::File_system
Ram_vfs_handle const *handle = Ram_vfs_handle const *handle =
static_cast<Ram_vfs_handle *>(vfs_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; return READ_OK;
} }
@ -716,8 +723,8 @@ class Vfs::Ram_file_system : public Vfs::File_system
Ram_vfs_handle const *handle = Ram_vfs_handle const *handle =
static_cast<Ram_vfs_handle *>(vfs_handle); static_cast<Ram_vfs_handle *>(vfs_handle);
Vfs_ram::Node::Guard guard(handle->file()); Vfs_ram::Node::Guard guard(&handle->file);
handle->file()->truncate(len); handle->file.truncate(len);
return FTRUNCATE_OK; 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -72,10 +72,11 @@ class Vfs::Rom_file_system : public Single_file_system
* each time when opening the corresponding file. * each time when opening the corresponding file.
*/ */
Open_result open(char const *path, unsigned, Open_result open(char const *path, unsigned,
Vfs_handle **out_handle) override Vfs_handle **out_handle,
Allocator &alloc) override
{ {
Open_result const result = Open_result const result =
Single_file_system::open(path, 0, out_handle); Single_file_system::open(path, 0, out_handle, alloc);
_rom.update(); _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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -128,15 +128,22 @@ class Vfs::Single_file_system : public File_system
} }
Open_result open(char const *path, unsigned, Open_result open(char const *path, unsigned,
Vfs_handle **out_handle) override Vfs_handle **out_handle,
Allocator &alloc) override
{ {
if (!_is_single_file(path)) if (!_is_single_file(path))
return OPEN_ERR_UNACCESSIBLE; 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; return OPEN_OK;
} }
void close(Vfs_handle *handle) override
{
if (handle && (&handle->ds() == this))
destroy(handle->alloc(), handle);
}
Unlink_result unlink(char const *) override Unlink_result unlink(char const *) override
{ {
return UNLINK_ERR_NO_PERM; 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * 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 { } void release(char const *path, Dataspace_capability ds_cap) override { }
Open_result open(char const *path, unsigned, Open_result open(char const *, unsigned, Vfs_handle **out_handle,
Vfs_handle **out_handle) override { Allocator&) override {
return OPEN_ERR_UNACCESSIBLE; } return OPEN_ERR_UNACCESSIBLE; }
void close(Vfs_handle *) override { }
Unlink_result unlink(char const *) override { Unlink_result unlink(char const *) override {
return UNLINK_ERR_NO_PERM; } return UNLINK_ERR_NO_PERM; }

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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -102,8 +102,8 @@ class Vfs::Tar_file_system : public File_system
public: public:
Tar_vfs_handle(File_system &fs, int status_flags, Record const *record) Tar_vfs_handle(File_system &fs, Allocator &alloc, int status_flags, Record const *record)
: Vfs_handle(fs, fs, status_flags), _record(record) : Vfs_handle(fs, fs, alloc, status_flags), _record(record)
{ } { }
Record const *record() const { return _record; } Record const *record() const { return _record; }
@ -573,18 +573,26 @@ class Vfs::Tar_file_system : public File_system
return node ? path : 0; 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); Node const *node = dereference(path);
if (!node || !node->record || node->record->type() != Record::TYPE_FILE) if (!node || !node->record || node->record->type() != Record::TYPE_FILE)
return OPEN_ERR_UNACCESSIBLE; return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (env()->heap()) *out_handle = new (alloc) Tar_vfs_handle(*this, alloc, 0, node->record);
Tar_vfs_handle(*this, 0, node->record);
return OPEN_OK; 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 ** ** 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 * This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2. * under the terms of the GNU General Public License version 2.
@ -26,8 +26,9 @@ class Vfs::Vfs_handle
Directory_service &_ds; Directory_service &_ds;
File_io_service &_fs; File_io_service &_fs;
Genode::Allocator &_alloc;
int _status_flags; int _status_flags;
file_size _seek; file_size _seek = 0;
public: public:
@ -40,21 +41,27 @@ class Vfs::Vfs_handle
~Guard() ~Guard()
{ {
if (handle) if (handle)
Genode::destroy(Genode::env()->heap(), handle); handle->_ds.close(handle);
} }
}; };
enum { STATUS_RDONLY = 0, STATUS_WRONLY = 1, STATUS_RDWR = 2 }; 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() { } virtual ~Vfs_handle() { }
Directory_service &ds() { return _ds; } Directory_service &ds() { return _ds; }
File_io_service &fs() { return _fs; } File_io_service &fs() { return _fs; }
Allocator &alloc() { return _alloc; }
int status_flags() const { return _status_flags; } int status_flags() const { return _status_flags; }
@ -76,4 +83,5 @@ class Vfs::Vfs_handle
void advance_seek(file_size incr) { _seek += incr; } void advance_seek(file_size incr) { _seek += incr; }
}; };
#endif /* _INCLUDE__VFS__VFS_HANDLE_H_ */ #endif /* _INCLUDE__VFS__VFS_HANDLE_H_ */

View File

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