VFS: catch Out_of_ram and Out_of_cap exceptions

Catch out of RAM and capability exceptions and return error values.
Abort opening a composite directory at Dir_file_system where an
opendir call on any child file-system returns an OUT_OF_RAM or
OUT_OF_CAPS error.

Ref #2642
This commit is contained in:
Emery Hemingway 2018-01-12 13:47:48 -06:00 committed by Norman Feske
parent c34a4bfdb4
commit c7d0accac0
14 changed files with 194 additions and 80 deletions

View File

@ -540,8 +540,12 @@ class Vfs::Dir_file_system : public File_system
* are subjected to the stacked file-system layout.
*/
if (directory(path)) {
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
try {
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
/*
@ -558,8 +562,12 @@ class Vfs::Dir_file_system : public File_system
/* path equals directory name */
if (strlen(path) == 0) {
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
try {
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
/* path refers to any of our sub file systems */
@ -595,6 +603,9 @@ class Vfs::Dir_file_system : public File_system
switch (r) {
case OPENDIR_OK:
break;
case OPEN_ERR_OUT_OF_RAM:
case OPEN_ERR_OUT_OF_CAPS:
return r;
case OPENDIR_ERR_LOOKUP_FAILED:
default:
continue;
@ -625,8 +636,13 @@ class Vfs::Dir_file_system : public File_system
* only, VFS root additionally calls 'open_composite_dirs' in order to
* open its file systems
*/
Dir_vfs_handle *root_handle = new (alloc)
Dir_vfs_handle(*this, *this, alloc, path);
Dir_vfs_handle *root_handle;
try {
root_handle = new (alloc)
Dir_vfs_handle(*this, *this, alloc, path);
}
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
/* the VFS root may contain more file systems */
if (_vfs_root)
@ -667,8 +683,13 @@ class Vfs::Dir_file_system : public File_system
return opendir_result;
}
Dir_vfs_handle *dir_vfs_handle = new (alloc)
Dir_vfs_handle(*this, *this, alloc, path);
Dir_vfs_handle *dir_vfs_handle;
try {
dir_vfs_handle = new (alloc)
Dir_vfs_handle(*this, *this, alloc, path);
}
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
/* path equals "/" (for reading the name of this directory) */
if (strlen(sub_path) == 0)

View File

@ -202,10 +202,14 @@ class Vfs::Single_file_system : public File_system
if (create)
return OPENDIR_ERR_PERMISSION_DENIED;
*out_handle =
new (alloc) Single_vfs_dir_handle(*this, *this, alloc,
_node_type, _filename);
return OPENDIR_OK;
try {
*out_handle = new (alloc)
Single_vfs_dir_handle(*this, *this, alloc,
_node_type, _filename);
return OPENDIR_OK;
}
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
}
void close(Vfs_handle *handle) override

View File

@ -384,22 +384,26 @@ class Vfs::Block_file_system : public Single_file_system
if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Block_vfs_handle(*this, *this, alloc,
_label, _lock,
_block_buffer,
_block_buffer_count,
_tx_block_alloc,
_block,
_block_size,
_block_count,
_block_ops,
_tx_source,
_readable,
_writeable,
_signal_receiver,
_signal_context,
_source_submit_cap);
return OPEN_OK;
try {
*out_handle = new (alloc) Block_vfs_handle(*this, *this, alloc,
_label, _lock,
_block_buffer,
_block_buffer_count,
_tx_block_alloc,
_block,
_block_size,
_block_count,
_block_ops,
_tx_source,
_readable,
_writeable,
_signal_receiver,
_signal_context,
_source_submit_cap);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
Stat_result stat(char const *path, Stat &out) override

View File

@ -775,9 +775,9 @@ class Vfs::Fs_file_system : public File_system
catch (::File_system::Invalid_name) { return OPEN_ERR_NAME_TOO_LONG; }
catch (::File_system::Name_too_long) { return OPEN_ERR_NAME_TOO_LONG; }
catch (::File_system::No_space) { return OPEN_ERR_NO_SPACE; }
catch (::File_system::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (::File_system::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
catch (::File_system::Unavailable) { return OPEN_ERR_UNACCESSIBLE; }
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
return OPEN_OK;
}
@ -800,9 +800,9 @@ class Vfs::Fs_file_system : public File_system
catch (::File_system::Name_too_long) { return OPENDIR_ERR_NAME_TOO_LONG; }
catch (::File_system::Node_already_exists) { return OPENDIR_ERR_NODE_ALREADY_EXISTS; }
catch (::File_system::No_space) { return OPENDIR_ERR_NO_SPACE; }
catch (::File_system::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (::File_system::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
catch (::File_system::Permission_denied) { return OPENDIR_ERR_PERMISSION_DENIED; }
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
return OPENDIR_OK;
}
@ -844,10 +844,10 @@ class Vfs::Fs_file_system : public File_system
catch (::File_system::Lookup_failed) { return OPENLINK_ERR_LOOKUP_FAILED; }
catch (::File_system::Node_already_exists) { return OPENLINK_ERR_NODE_ALREADY_EXISTS; }
catch (::File_system::No_space) { return OPENLINK_ERR_NO_SPACE; }
catch (::File_system::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (::File_system::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
catch (::File_system::Permission_denied) { return OPENLINK_ERR_PERMISSION_DENIED; }
catch (::File_system::Unavailable) { return OPENLINK_ERR_LOOKUP_FAILED; }
catch (Genode::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
}
void close(Vfs_handle *vfs_handle) override

View File

@ -125,9 +125,13 @@ class Vfs::Inline_file_system : public Single_file_system
if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Inline_vfs_handle(*this, *this, alloc,
_base, _size);
return OPEN_OK;
try {
*out_handle = new (alloc)
Inline_vfs_handle(*this, *this, alloc, _base, _size);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
Stat_result stat(char const *path, Stat &out) override

View File

@ -115,9 +115,13 @@ class Vfs::Log_file_system : public Single_file_system
if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Log_vfs_handle(*this, *this, alloc,
_log);
return OPEN_OK;
try {
*out_handle = new (alloc)
Log_vfs_handle(*this, *this, alloc, _log);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
};

View File

@ -69,8 +69,13 @@ struct Vfs::Null_file_system : Single_file_system
if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Null_vfs_handle(*this, *this, alloc);
return OPEN_OK;
try {
*out_handle = new (alloc)
Null_vfs_handle(*this, *this, alloc);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
/********************************

View File

@ -551,8 +551,9 @@ class Vfs::Ram_file_system : public Vfs::File_system
File *file;
char const *name = basename(path);
bool const create = mode & OPEN_MODE_CREATE;
if (mode & OPEN_MODE_CREATE) {
if (create) {
Directory *parent = lookup_parent(path);
if (!parent) return OPEN_ERR_UNACCESSIBLE;
Node::Guard guard(parent);
@ -573,8 +574,22 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (!file) return OPEN_ERR_UNACCESSIBLE;
}
*handle = new (alloc) Ram_vfs_handle(*this, alloc, mode, *file);
return OPEN_OK;
try {
*handle = new (alloc) Ram_vfs_handle(*this, alloc, mode, *file);
return OPEN_OK;
} catch (Genode::Out_of_ram) {
if (create) {
lookup_parent(path)->release(file);
remove(file);
}
return OPEN_ERR_OUT_OF_RAM;
} catch (Genode::Out_of_caps) {
if (create) {
lookup_parent(path)->release(file);
remove(file);
}
return OPEN_ERR_OUT_OF_CAPS;
}
}
Opendir_result opendir(char const *path, bool create,
@ -599,9 +614,8 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (parent->child(name))
return OPENDIR_ERR_NODE_ALREADY_EXISTS;
try {
dir = new (_alloc) Directory(name);
} catch (Out_of_memory) { return OPENDIR_ERR_NO_SPACE; }
try { dir = new (_alloc) Directory(name); }
catch (Out_of_memory) { return OPENDIR_ERR_NO_SPACE; }
parent->adopt(dir);
@ -614,11 +628,24 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (!dir) return OPENDIR_ERR_LOOKUP_FAILED;
}
*handle = new (alloc) Ram_vfs_handle(*this, alloc,
Ram_vfs_handle::STATUS_RDONLY,
*dir);
return OPENDIR_OK;
try {
*handle = new (alloc) Ram_vfs_handle(*this, alloc,
Ram_vfs_handle::STATUS_RDONLY,
*dir);
return OPENDIR_OK;
} catch (Genode::Out_of_ram) {
if (create) {
parent->release(dir);
remove(dir);
}
return OPENDIR_ERR_OUT_OF_RAM;
} catch (Genode::Out_of_caps) {
if (create) {
parent->release(dir);
remove(dir);
}
return OPENDIR_ERR_OUT_OF_CAPS;
}
}
Openlink_result openlink(char const *path, bool create,
@ -660,11 +687,24 @@ class Vfs::Ram_file_system : public Vfs::File_system
if (!link) return OPENLINK_ERR_LOOKUP_FAILED;
}
*handle = new (alloc) Ram_vfs_handle(*this, alloc,
Ram_vfs_handle::STATUS_RDWR,
*link);
return OPENLINK_OK;
try {
*handle = new (alloc) Ram_vfs_handle(*this, alloc,
Ram_vfs_handle::STATUS_RDWR,
*link);
return OPENLINK_OK;
} catch (Genode::Out_of_ram) {
if (create) {
parent->release(link);
remove(link);
}
return OPENLINK_ERR_OUT_OF_RAM;
} catch (Genode::Out_of_caps) {
if (create) {
parent->release(link);
remove(link);
}
return OPENLINK_ERR_OUT_OF_CAPS;
}
}
void close(Vfs_handle *vfs_handle) override

View File

@ -128,8 +128,13 @@ class Vfs::Rom_file_system : public Single_file_system
_rom.update();
*out_handle = new (alloc) Rom_vfs_handle(*this, *this, alloc, _rom);
return OPEN_OK;
try {
*out_handle = new (alloc)
Rom_vfs_handle(*this, *this, alloc, _rom);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
Dataspace_capability dataspace(char const *) override

View File

@ -109,9 +109,13 @@ class Vfs::Rtc_file_system : public Single_file_system
if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Rtc_vfs_handle(*this, *this, alloc,
_rtc);
return OPEN_OK;
try {
*out_handle = new (alloc)
Rtc_vfs_handle(*this, *this, alloc, _rtc);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
Stat_result stat(char const *path, Stat &out) override

View File

@ -59,8 +59,12 @@ class Vfs::Symlink_file_system : public Single_file_system
if (create)
return OPENLINK_ERR_NODE_ALREADY_EXISTS;
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPENLINK_OK;
try {
*out_handle = new (alloc) Vfs_handle(*this, *this, alloc, 0);
return OPENLINK_OK;
}
catch (Genode::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
}
void close(Vfs_handle *vfs_handle) override

View File

@ -651,9 +651,13 @@ class Vfs::Tar_file_system : public File_system
if (!node || !node->record || node->record->type() != Record::TYPE_FILE)
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Tar_vfs_file_handle(*this, alloc, 0, node);
return OPEN_OK;
try {
*out_handle = new (alloc)
Tar_vfs_file_handle(*this, alloc, 0, node);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
Opendir_result opendir(char const *path, bool /* create */,
@ -666,9 +670,13 @@ class Vfs::Tar_file_system : public File_system
(node->record && (node->record->type() != Record::TYPE_DIR)))
return OPENDIR_ERR_LOOKUP_FAILED;
*out_handle = new (alloc) Tar_vfs_dir_handle(*this, alloc, 0, node);
return OPENDIR_OK;
try {
*out_handle = new (alloc)
Tar_vfs_dir_handle(*this, alloc, 0, node);
return OPENDIR_OK;
}
catch (Genode::Out_of_ram) { return OPENDIR_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENDIR_ERR_OUT_OF_CAPS; }
}
Openlink_result openlink(char const *path, bool /* create */,
@ -679,9 +687,13 @@ class Vfs::Tar_file_system : public File_system
node->record->type() != Record::TYPE_SYMLINK)
return OPENLINK_ERR_LOOKUP_FAILED;
*out_handle = new (alloc) Tar_vfs_symlink_handle(*this, alloc, 0, node);
return OPENLINK_OK;
try {
*out_handle = new (alloc)
Tar_vfs_symlink_handle(*this, alloc, 0, node);
return OPENLINK_OK;
}
catch (Genode::Out_of_ram) { return OPENLINK_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPENLINK_ERR_OUT_OF_CAPS; }
}
void close(Vfs_handle *vfs_handle) override

View File

@ -128,10 +128,13 @@ class Vfs::Terminal_file_system : public Single_file_system
if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc)
Registered_handle(_handle_registry, *this, *this, alloc, 0);
return OPEN_OK;
try {
*out_handle = new (alloc)
Registered_handle(_handle_registry, *this, *this, alloc, 0);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
/********************************

View File

@ -71,8 +71,12 @@ struct Vfs::Zero_file_system : Single_file_system
if (!_single_file(path))
return OPEN_ERR_UNACCESSIBLE;
*out_handle = new (alloc) Zero_vfs_handle(*this, *this, alloc);
return OPEN_OK;
try {
*out_handle = new (alloc) Zero_vfs_handle(*this, *this, alloc);
return OPEN_OK;
}
catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; }
catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; }
}
};