obscure File_system::Out_of_node_handles exception

Replace the Out_of_node_handles exception with Out_of_metadata.
Clients need to know when the server is out of internal resources,
but not why.

Cleanup and sort the errors at file_system_session.h.
Remove 'Size_limit_reached exception' from File_system, which was
internal to ram_fs.

Issue #1751
Fixes #1909
This commit is contained in:
Emery Hemingway 2016-03-17 15:09:07 +01:00 committed by Christian Helmuth
parent 58632ab8b5
commit cb952d2087
14 changed files with 109 additions and 95 deletions

View File

@ -94,7 +94,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node);
}
catch (Invalid_handle) { PERR("Invalid_handle"); }
catch (Size_limit_reached) { PERR("Size_limit_reached"); }
/*
* The 'acknowledge_packet' function cannot block because we

View File

@ -120,7 +120,6 @@ namespace File_system {
_process_packet_op(packet, *node);
}
catch (Invalid_handle) { PERR("Invalid_handle"); }
catch (Size_limit_reached) { PERR("Size_limit_reached"); }
/*
* The 'acknowledge_packet' function cannot block because we

View File

@ -108,7 +108,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node);
}
catch (Invalid_handle) { PERR("Invalid_handle"); }
catch (Size_limit_reached) { PERR("Size_limit_reached"); }
/*
* The 'acknowledge_packet' function cannot block because we

View File

@ -56,7 +56,7 @@ namespace File_system {
/**
* Allocate node handle
*
* \throw Out_of_node_handles
* \throw Out_of_metadata
*/
int _alloc(Node_base *node)
{
@ -68,7 +68,7 @@ namespace File_system {
return i;
}
throw Out_of_node_handles();
throw Out_of_metadata();
}
bool _in_range(int handle) const

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2012-2013 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.
@ -51,16 +51,15 @@ namespace File_system {
* Exception types
*/
class Exception : public Genode::Exception { };
class Permission_denied : Exception { };
class Node_already_exists : Exception { };
class Lookup_failed : Exception { };
class Name_too_long : Exception { };
class No_space : Exception { };
class Out_of_node_handles : Exception { };
class Invalid_handle : Exception { };
class Invalid_name : Exception { };
class Size_limit_reached : Exception { };
class Lookup_failed : Exception { };
class Name_too_long : Exception { };
class Node_already_exists : Exception { };
class No_space : Exception { };
class Not_empty : Exception { };
class Out_of_metadata : Exception { };
class Permission_denied : Exception { };
struct Session;
}
@ -214,13 +213,13 @@ struct File_system::Session : public Genode::Session
* Open or create file
*
* \throw Invalid_handle directory handle is invalid
* \throw Node_already_exists file cannot be created because a
* node with the same name already exists
* \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
* \throw Lookup_failed the name refers to a node other than a file
* \throw Node_already_exists file cannot be created because a node with
* the same name already exists
* \throw No_space storage exhausted
* \throw Out_of_metadata server cannot allocate metadata
* \throw Permission_denied
*/
virtual File_handle file(Dir_handle, Name const &name, Mode, bool create) = 0;
@ -228,23 +227,27 @@ struct File_system::Session : public Genode::Session
* 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
* \throw Invalid_name symlink name contains invalid characters
* \throw Lookup_failed the name refers to a node other than a symlink
* \throw Node_already_exists symlink cannot be created because a node with
* the same name already exists
* \throw No_space storage exhausted
* \throw Out_of_metadata server cannot allocate metadata
* \throw Permission_denied
*/
virtual Symlink_handle symlink(Dir_handle, Name const &name, bool create) = 0;
/**
* Open or create directory
*
* \throw Permission_denied
* \throw Node_already_exists directory cannot be created because a
* node with the same name already exists
* \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
* \throw Name_too_long 'path' is too long
* \throw Node_already_exists directory cannot be created because a
* node with the same name already exists
* \throw No_space storage exhausted
* \throw Out_of_metadata server cannot allocate metadata
* \throw Permission_denied
*/
virtual Dir_handle dir(Path const &path, bool create) = 0;
@ -254,9 +257,9 @@ 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
* \throw Lookup_failed path lookup failed because one element
* of 'path' does not exist
* \throw Out_of_metadata server cannot allocate metadata
*/
virtual Node_handle node(Path const &path) = 0;
@ -278,25 +281,31 @@ struct File_system::Session : public Genode::Session
/**
* Delete file or directory
*
* \throw Invalid_handle directory handle is invalid
* \throw Invalid_name 'name' contains invalid characters
* \throw Lookup_failed lookup of 'name' in 'dir' failed
* \throw Not_empty argument is a non-empty directory and
* the backend does not support recursion
* \throw Permission_denied
* \throw Invalid_name
* \throw Lookup_failed
* \throw Not_empty argument is a non-empty directory and
* the backend does not support recursion
*/
virtual void unlink(Dir_handle, Name const &) = 0;
virtual void unlink(Dir_handle dir, Name const &name) = 0;
/**
* 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
* \throw Permission_denied node modification not allowed
*/
virtual void truncate(File_handle, file_size_t size) = 0;
/**
* Move and rename directory entry
*
* \throw Invalid_handle a directory handle is invalid
* \throw Invalid_name 'to' contains invalid characters
* \throw Lookup_failed 'from' not found
* \throw Permission_denied node modification not allowed
*/
virtual void move(Dir_handle, Name const &from,
Dir_handle, Name const &to) = 0;
@ -321,37 +330,40 @@ struct File_system::Session : public Genode::Session
GENODE_RPC(Rpc_tx_cap, Genode::Capability<Tx>, _tx_cap);
GENODE_RPC_THROW(Rpc_file, File_handle, file,
GENODE_TYPE_LIST(Invalid_handle, Node_already_exists,
Invalid_name, Lookup_failed,
Permission_denied, No_space,
Out_of_node_handles),
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
Lookup_failed, Node_already_exists,
No_space, Out_of_metadata,
Permission_denied),
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, No_space,
Out_of_node_handles),
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
Lookup_failed, Node_already_exists,
No_space, Out_of_metadata,
Permission_denied),
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, Out_of_node_handles),
GENODE_TYPE_LIST(Lookup_failed, Name_too_long,
Node_already_exists, No_space,
Out_of_metadata, Permission_denied),
Path const &, bool);
GENODE_RPC_THROW(Rpc_node, Node_handle, node,
GENODE_TYPE_LIST(Lookup_failed, Out_of_node_handles),
GENODE_TYPE_LIST(Lookup_failed, Out_of_metadata),
Path const &);
GENODE_RPC(Rpc_close, void, close, Node_handle);
GENODE_RPC(Rpc_status, Status, status, Node_handle);
GENODE_RPC(Rpc_control, void, control, Node_handle, Control);
GENODE_RPC_THROW(Rpc_unlink, void, unlink,
GENODE_TYPE_LIST(Permission_denied, Invalid_name,
Lookup_failed, Not_empty),
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
Lookup_failed, Not_empty,
Permission_denied),
Dir_handle, Name const &);
GENODE_RPC_THROW(Rpc_truncate, void, truncate,
GENODE_TYPE_LIST(Permission_denied, Invalid_handle, No_space),
GENODE_TYPE_LIST(Invalid_handle, No_space,
Permission_denied),
File_handle, file_size_t);
GENODE_RPC_THROW(Rpc_move, void, move,
GENODE_TYPE_LIST(Permission_denied, Invalid_name, Lookup_failed),
GENODE_TYPE_LIST(Invalid_handle, Invalid_name,
Lookup_failed, Permission_denied),
Dir_handle, Name const &, Dir_handle, Name const &);
GENODE_RPC_THROW(Rpc_sigh, void, sigh,
GENODE_TYPE_LIST(Invalid_handle),

View File

@ -81,8 +81,10 @@ class File_system::File : public Node
if (seek_offset == (seek_off_t)(~0))
seek_offset = _chunk.used_size();
if (seek_offset + len >= Chunk_level_0::SIZE)
throw Size_limit_reached();
if (seek_offset + len >= Chunk_level_0::SIZE) {
len = (Chunk_level_0::SIZE-1) - seek_offset;
PERR("%s: size limit %d reached", name(), Chunk_level_0::SIZE);
}
_chunk.write(src, len, (size_t)seek_offset);

View File

@ -247,11 +247,9 @@ class Vfs::Fs_file_system : public File_system
::File_system::Node_handle node = _fs.node(path);
Fs_handle_guard node_guard(_fs, node);
status = _fs.status(node);
} catch (...) {
if (verbose)
PDBG("stat failed for path '%s'", path);
return STAT_ERR_NO_ENTRY;
}
catch (::File_system::Lookup_failed) { return STAT_ERR_NO_ENTRY; }
catch (::File_system::Out_of_metadata) { return STAT_ERR_NO_PERM; }
memset(&out, 0, sizeof(out));
@ -266,6 +264,8 @@ class Vfs::Fs_file_system : public File_system
out.uid = 0;
out.gid = 0;
out.inode = status.inode;
out.device = (Genode::addr_t)this;
return STAT_OK;
}
@ -278,7 +278,11 @@ class Vfs::Fs_file_system : public File_system
if (strcmp(path, "") == 0)
path = "/";
::File_system::Dir_handle dir_handle = _fs.dir(path, false);
::File_system::Dir_handle dir_handle;
try { dir_handle = _fs.dir(path, false); }
catch (::File_system::Lookup_failed) { return DIRENT_ERR_INVALID_PATH; }
catch (::File_system::Name_too_long) { return DIRENT_ERR_INVALID_PATH; }
catch (...) { return DIRENT_ERR_NO_PERM; }
Fs_handle_guard dir_guard(_fs, dir_handle);
enum { DIRENT_SIZE = sizeof(::File_system::Directory_entry) };
@ -318,9 +322,8 @@ class Vfs::Fs_file_system : public File_system
case Directory_entry::TYPE_SYMLINK: type = DIRENT_TYPE_SYMLINK; break;
}
out.fileno = entry->inode;
out.type = type;
out.fileno = index + 1;
strncpy(out.name, entry->name, sizeof(out.name));
source.release_packet(packet);
@ -343,9 +346,11 @@ class Vfs::Fs_file_system : public File_system
_fs.unlink(dir, file_name.base() + 1);
}
catch (::File_system::Permission_denied) { return UNLINK_ERR_NO_PERM; }
catch (::File_system::Invalid_handle) { return UNLINK_ERR_NO_ENTRY; }
catch (::File_system::Invalid_name) { return UNLINK_ERR_NO_ENTRY; }
catch (::File_system::Lookup_failed) { return UNLINK_ERR_NO_ENTRY; }
catch (::File_system::Not_empty) { return UNLINK_ERR_NOT_EMPTY; }
catch (...) { return UNLINK_ERR_NO_ENTRY; }
catch (::File_system::Permission_denied) { return UNLINK_ERR_NO_PERM; }
return UNLINK_OK;
}
@ -374,9 +379,10 @@ class Vfs::Fs_file_system : public File_system
out_len = _read(symlink_handle, buf, buf_size, 0);
return READLINK_OK;
} catch (...) { }
return READLINK_ERR_NO_ENTRY;
}
catch (::File_system::Lookup_failed) { return READLINK_ERR_NO_ENTRY; }
catch (::File_system::Invalid_handle) { return READLINK_ERR_NO_ENTRY; }
catch (...) { return READLINK_ERR_NO_PERM; }
}
Rename_result rename(char const *from_path, char const *to_path) override
@ -428,7 +434,7 @@ class Vfs::Fs_file_system : public File_system
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; }
catch (::File_system::Out_of_metadata) { return MKDIR_ERR_NO_ENTRY; }
return MKDIR_OK;
}
@ -467,7 +473,7 @@ class Vfs::Fs_file_system : public File_system
catch (::File_system::Lookup_failed) { return SYMLINK_ERR_NO_ENTRY; }
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; }
catch (::File_system::Out_of_metadata) { return SYMLINK_ERR_NO_ENTRY; }
return SYMLINK_OK;
}
@ -477,12 +483,8 @@ class Vfs::Fs_file_system : public File_system
if (strcmp(path, "") == 0)
path = "/";
/*
* XXX handle more exceptions
*/
::File_system::Node_handle node;
try { node = _fs.node(path); } catch (::File_system::Lookup_failed) { return 0; }
try { node = _fs.node(path); } catch (...) { return 0; }
Fs_handle_guard node_guard(_fs, node);
::File_system::Status status = _fs.status(node);
@ -550,26 +552,29 @@ class Vfs::Fs_file_system : public File_system
*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; }
catch (::File_system::Lookup_failed) { return OPEN_ERR_UNACCESSIBLE; }
catch (::File_system::Node_already_exists) { return OPEN_ERR_EXISTS; }
catch (::File_system::Lookup_failed) { return OPEN_ERR_UNACCESSIBLE; }
catch (::File_system::Permission_denied) { return OPEN_ERR_NO_PERM; }
catch (::File_system::Invalid_handle) { return OPEN_ERR_UNACCESSIBLE; }
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; }
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_metadata) { return OPEN_ERR_NO_PERM; }
return OPEN_OK;
}
void close(Vfs_handle *vfs_handle) override
{
if (!vfs_handle) return;
Lock::Guard guard(_lock);
Fs_vfs_handle *handle = static_cast<Fs_vfs_handle *>(vfs_handle);
Fs_vfs_handle *fs_handle = static_cast<Fs_vfs_handle *>(vfs_handle);
if (handle) {
_fs.close(handle->file_handle());
destroy(handle->alloc(), handle);
if (fs_handle) {
_fs.close(fs_handle->file_handle());
destroy(fs_handle->alloc(), fs_handle);
}
}
@ -584,8 +589,8 @@ class Vfs::Fs_file_system : public File_system
{
try {
::File_system::Node_handle node = _fs.node(path);
Fs_handle_guard node_guard(_fs, node);
_fs.sync(node);
_fs.close(node);
} catch (...) { }
}

View File

@ -167,8 +167,8 @@ class Fs_log::Root_component :
} catch (No_space) {
PERR("file system out of space");
} catch (Out_of_node_handles) {
PERR("too many open file handles");
} catch (Out_of_metadata) {
PERR("file system server out of metadata");
} catch (Invalid_name) {
PERR("%s: invalid path", Path(file_name, dir_path).base());

View File

@ -97,7 +97,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node);
}
catch (Invalid_handle) { PERR("Invalid_handle"); }
catch (Size_limit_reached) { PERR("Size_limit_reached"); }
/*
* The 'acknowledge_packet' function cannot block because we

View File

@ -95,7 +95,6 @@ namespace File_system {
_process_packet_op(packet, *node);
}
catch (Invalid_handle) { PERR("Invalid_handle"); }
catch (Size_limit_reached) { PERR("Size_limit_reached"); }
/*
* The 'acknowledge_packet' function cannot block because we

View File

@ -107,7 +107,6 @@ namespace File_system {
_process_packet_op(packet, *node);
}
catch (Invalid_handle) { PERR("Invalid_handle"); }
catch (Size_limit_reached) { PERR("Size_limit_reached"); }
/*
* The 'acknowledge_packet' function cannot block because we

View File

@ -171,8 +171,10 @@ namespace File_system {
if (seek_offset == (seek_off_t)(~0))
seek_offset = _chunk.used_size();
if (seek_offset + len >= Chunk_level_0::SIZE)
throw Size_limit_reached();
if (seek_offset + len >= Chunk_level_0::SIZE) {
len = (Chunk_level_0::SIZE-1) - seek_offset;
PERR("%s: size limit %d reached", name(), Chunk_level_0::SIZE);
}
_chunk.write(src, len, (size_t)seek_offset);

View File

@ -700,7 +700,6 @@ class File_system::Session_component : public Session_rpc_object
_process_packet_op(packet, *node);
}
catch (Invalid_handle) { PERR("Invalid_handle"); }
catch (Size_limit_reached) { PERR("Size_limit_reached"); }
/*
* The 'acknowledge_packet' function cannot block because we

View File

@ -67,7 +67,7 @@ namespace File_system {
/**
* Allocate node handle
*
* \throw Out_of_node_handles
* \throw Out_of_metadata
*/
int _alloc(Node *node, Mode mode)
{
@ -80,7 +80,7 @@ namespace File_system {
return i;
}
throw Out_of_node_handles();
throw Out_of_metadata();
}
bool _in_range(int handle) const