File_system session: broaden error handling

Throw Invalid_name, No_space, and Out_of_node_handles where appropriate.

Catch the new range of errors thrown by at the VFS.
Catch Out_of_node_handles at the VFS, but print a message and re-throw.

Issue #1648
This commit is contained in:
Emery Hemingway 2015-10-07 19:15:47 +02:00 committed by Christian Helmuth
parent 1d4bd10701
commit 1c6164a0c5
2 changed files with 48 additions and 28 deletions

View File

@ -217,11 +217,18 @@ struct File_system::Session : public Genode::Session
* \throw Invalid_name file name contains invalid characters
* \throw Lookup_failed the name refers to a node other than a
* file
* \throw Out_of_node_handles server cannot allocate metadata
* \throw No_space
*/
virtual File_handle file(Dir_handle, Name const &name, Mode, bool create) = 0;
/**
* Open or create symlink
*
* \throw Invalid_handle directory handle is invalid
* \throw Invalid_name file name contains invalid characters
* \throw Out_of_node_handles server cannot allocate metadata
* \throw No_space
*/
virtual Symlink_handle symlink(Dir_handle, Name const &name, bool create) = 0;
@ -234,6 +241,7 @@ struct File_system::Session : public Genode::Session
* \throw Lookup_failed path lookup failed because one element
* of 'path' does not exist
* \throw Name_too_long
* \throw Out_of_node_handles server cannot allocate metadata
* \throw No_space
*/
virtual Dir_handle dir(Path const &path, bool create) = 0;
@ -243,6 +251,10 @@ struct File_system::Session : public Genode::Session
*
* The returned node handle can be used merely as argument for
* 'status'.
*
* \throw Lookup_failed path lookup failed because one element
* of 'path' does not exist
* \throw Out_of_node_handles server cannot allocate metadata
*/
virtual Node_handle node(Path const &path) = 0;
@ -268,6 +280,10 @@ struct File_system::Session : public Genode::Session
/**
* Truncate or grow file to specified size
*
* \throw Permission_denied node modification not allowed
* \throw Invalid_handle node handle is invalid
* \throw No_space new size exceeds free space
*/
virtual void truncate(File_handle, file_size_t size) = 0;
@ -286,8 +302,7 @@ struct File_system::Session : public Genode::Session
* Synchronize file system
*
* This is only needed by file systems that maintain an internal
* cache, which needs to be flushed on certain occasions. Therefore,
* the default implementation just serves as a reminder.
* cache, which needs to be flushed on certain occasions.
*/
virtual void sync(Node_handle) { }
@ -300,18 +315,22 @@ struct File_system::Session : public Genode::Session
GENODE_RPC_THROW(Rpc_file, File_handle, file,
GENODE_TYPE_LIST(Invalid_handle, Node_already_exists,
Invalid_name, Lookup_failed,
Permission_denied),
Permission_denied, No_space,
Out_of_node_handles),
Dir_handle, Name const &, Mode, bool);
GENODE_RPC_THROW(Rpc_symlink, Symlink_handle, symlink,
GENODE_TYPE_LIST(Invalid_handle, Node_already_exists,
Invalid_name, Lookup_failed, Permission_denied),
Invalid_name, Lookup_failed,
Permission_denied, No_space,
Out_of_node_handles),
Dir_handle, Name const &, bool);
GENODE_RPC_THROW(Rpc_dir, Dir_handle, dir,
GENODE_TYPE_LIST(Permission_denied, Node_already_exists,
Lookup_failed, Name_too_long, No_space),
Lookup_failed, Name_too_long,
No_space, Out_of_node_handles),
Path const &, bool);
GENODE_RPC_THROW(Rpc_node, Node_handle, node,
GENODE_TYPE_LIST(Lookup_failed),
GENODE_TYPE_LIST(Lookup_failed, Out_of_node_handles),
Path const &);
GENODE_RPC(Rpc_close, void, close, Node_handle);
GENODE_RPC(Rpc_status, Status, status, Node_handle);
@ -320,7 +339,7 @@ struct File_system::Session : public Genode::Session
GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed),
Dir_handle, Name const &);
GENODE_RPC_THROW(Rpc_truncate, void, truncate,
GENODE_TYPE_LIST(Permission_denied, Invalid_handle),
GENODE_TYPE_LIST(Permission_denied, Invalid_handle, No_space),
File_handle, file_size_t);
GENODE_RPC_THROW(Rpc_move, void, move,
GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed),

View File

@ -17,7 +17,6 @@
/* Genode includes */
#include <base/allocator_avl.h>
#include <file_system_session/connection.h>
#include <util/string.h>
namespace Vfs { class Fs_file_system; }
@ -241,7 +240,8 @@ class Vfs::Fs_file_system : public File_system
void release(char const *path, Dataspace_capability ds_cap) override
{
env()->ram_session()->free(static_cap_cast<Genode::Ram_dataspace>(ds_cap));
if (ds_cap.valid())
env()->ram_session()->free(static_cap_cast<Genode::Ram_dataspace>(ds_cap));
}
Stat_result stat(char const *path, Stat &out) override
@ -347,9 +347,8 @@ class Vfs::Fs_file_system : public File_system
_fs.unlink(dir, file_name.base() + 1);
}
catch (...) {
return UNLINK_ERR_NO_ENTRY;
}
catch (::File_system::Permission_denied) { return UNLINK_ERR_NO_PERM; }
catch (...) { return UNLINK_ERR_NO_ENTRY; }
return UNLINK_OK;
}
@ -399,15 +398,14 @@ class Vfs::Fs_file_system : public File_system
try {
::File_system::Dir_handle from_dir = _fs.dir(from_dir_path.base(), false);
Fs_handle_guard from_dir_guard(_fs, from_dir);
::File_system::Dir_handle to_dir = _fs.dir(to_dir_path.base(), false);
Fs_handle_guard to_dir_guard(_fs, to_dir);
_fs.move(from_dir, from_file_name.base() + 1,
to_dir, to_file_name.base() + 1);
} catch (...) {
return RENAME_ERR_NO_ENTRY; }
}
catch (::File_system::Lookup_failed) { return RENAME_ERR_NO_ENTRY; }
catch (...) { return RENAME_ERR_NO_PERM; }
return RENAME_OK;
}
@ -421,15 +419,15 @@ class Vfs::Fs_file_system : public File_system
try {
_fs.close(_fs.dir(abs_path.base(), true));
return MKDIR_OK;
}
catch (::File_system::Permission_denied) { return MKDIR_ERR_NO_PERM; }
catch (::File_system::Node_already_exists) { return MKDIR_ERR_EXISTS; }
catch (::File_system::Lookup_failed) { return MKDIR_ERR_NO_ENTRY; }
catch (::File_system::Name_too_long) { return MKDIR_ERR_NAME_TOO_LONG; }
catch (::File_system::No_space) { return MKDIR_ERR_NO_SPACE; }
catch (::File_system::Out_of_node_handles) { return MKDIR_ERR_NO_ENTRY; }
return MKDIR_ERR_NO_PERM;
return MKDIR_OK;
}
Symlink_result symlink(char const *from, char const *to) override
@ -458,15 +456,16 @@ class Vfs::Fs_file_system : public File_system
Fs_handle_guard symlink_guard(_fs, symlink_handle);
_write(symlink_handle, from, strlen(from) + 1, 0);
return SYMLINK_OK;
}
catch (::File_system::Invalid_handle) { return SYMLINK_ERR_NO_ENTRY; }
catch (::File_system::Node_already_exists) { return SYMLINK_ERR_EXISTS; }
catch (::File_system::Node_already_exists) { return SYMLINK_ERR_EXISTS; }
catch (::File_system::Invalid_name) { return SYMLINK_ERR_NAME_TOO_LONG; }
catch (::File_system::Lookup_failed) { return SYMLINK_ERR_NO_ENTRY; }
catch (::File_system::Permission_denied) { return SYMLINK_ERR_NO_PERM; }
catch (::File_system::Permission_denied) { return SYMLINK_ERR_NO_PERM; }
catch (::File_system::No_space) { return SYMLINK_ERR_NO_SPACE; }
catch (::File_system::Out_of_node_handles) { return SYMLINK_ERR_NO_ENTRY; }
return SYMLINK_ERR_NO_ENTRY;
return SYMLINK_OK;
}
file_size num_dirent(char const *path) override
@ -507,8 +506,7 @@ class Vfs::Fs_file_system : public File_system
::File_system::Node_handle node = _fs.node(path);
_fs.close(node);
}
catch (...) {
return 0; }
catch (...) { return 0; }
return path;
}
@ -546,14 +544,16 @@ class Vfs::Fs_file_system : public File_system
mode, create);
*out_handle = new (env()->heap()) Fs_vfs_handle(*this, vfs_mode, file);
return OPEN_OK;
}
catch (::File_system::Permission_denied) { return OPEN_ERR_NO_PERM; }
catch (::File_system::Invalid_handle) { return OPEN_ERR_NO_PERM; }
catch (::File_system::Lookup_failed) { return OPEN_ERR_UNACCESSIBLE; }
catch (::File_system::Node_already_exists) { return OPEN_ERR_EXISTS; }
catch (::File_system::Node_already_exists) { return OPEN_ERR_EXISTS; }
catch (::File_system::Invalid_name) { return OPEN_ERR_NAME_TOO_LONG; }
catch (::File_system::No_space) { return OPEN_ERR_NO_SPACE; }
catch (::File_system::Out_of_node_handles) { return OPEN_ERR_UNACCESSIBLE; }
return OPEN_ERR_UNACCESSIBLE;
return OPEN_OK;
}
@ -615,9 +615,10 @@ class Vfs::Fs_file_system : public File_system
try {
_fs.truncate(handle->file_handle(), len);
}
}
catch (::File_system::Invalid_handle) { return FTRUNCATE_ERR_NO_PERM; }
catch (::File_system::Permission_denied) { return FTRUNCATE_ERR_NO_PERM; }
catch (::File_system::No_space) { return FTRUNCATE_ERR_NO_SPACE; }
return FTRUNCATE_OK;
}