From cb952d2087fe46665f3596a8f5164a6e2bd16d18 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Thu, 17 Mar 2016 15:09:07 +0100 Subject: [PATCH] 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 --- repos/dde_rump/src/server/rump_fs/main.cc | 1 - repos/libports/src/server/ffat_fs/main.cc | 1 - .../src/server/fuse_fs/fuse_fs_main.cc | 1 - .../file_system/node_handle_registry.h | 4 +- .../file_system_session/file_system_session.h | 108 ++++++++++-------- repos/os/include/ram_fs/file.h | 6 +- repos/os/include/vfs/fs_file_system.h | 65 ++++++----- repos/os/src/server/fs_log/main.cc | 4 +- repos/os/src/server/lx_fs/main.cc | 1 - repos/os/src/server/ram_fs/main.cc | 1 - repos/os/src/server/tar_fs/main.cc | 1 - repos/os/src/server/trace_fs/file.h | 6 +- repos/os/src/server/trace_fs/main.cc | 1 - .../os/src/server/vfs/node_handle_registry.h | 4 +- 14 files changed, 109 insertions(+), 95 deletions(-) diff --git a/repos/dde_rump/src/server/rump_fs/main.cc b/repos/dde_rump/src/server/rump_fs/main.cc index c031111333..d82c0a4d3e 100644 --- a/repos/dde_rump/src/server/rump_fs/main.cc +++ b/repos/dde_rump/src/server/rump_fs/main.cc @@ -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 diff --git a/repos/libports/src/server/ffat_fs/main.cc b/repos/libports/src/server/ffat_fs/main.cc index e3cad42054..57b9367e0c 100644 --- a/repos/libports/src/server/ffat_fs/main.cc +++ b/repos/libports/src/server/ffat_fs/main.cc @@ -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 diff --git a/repos/libports/src/server/fuse_fs/fuse_fs_main.cc b/repos/libports/src/server/fuse_fs/fuse_fs_main.cc index f1959d16b4..c24af32346 100644 --- a/repos/libports/src/server/fuse_fs/fuse_fs_main.cc +++ b/repos/libports/src/server/fuse_fs/fuse_fs_main.cc @@ -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 diff --git a/repos/os/include/file_system/node_handle_registry.h b/repos/os/include/file_system/node_handle_registry.h index c4e5ffb9e0..d24cd5c926 100644 --- a/repos/os/include/file_system/node_handle_registry.h +++ b/repos/os/include/file_system/node_handle_registry.h @@ -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 diff --git a/repos/os/include/file_system_session/file_system_session.h b/repos/os/include/file_system_session/file_system_session.h index ea4d09b60b..de537a136b 100644 --- a/repos/os/include/file_system_session/file_system_session.h +++ b/repos/os/include/file_system_session/file_system_session.h @@ -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_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), diff --git a/repos/os/include/ram_fs/file.h b/repos/os/include/ram_fs/file.h index ef65f970e4..7799504928 100644 --- a/repos/os/include/ram_fs/file.h +++ b/repos/os/include/ram_fs/file.h @@ -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); diff --git a/repos/os/include/vfs/fs_file_system.h b/repos/os/include/vfs/fs_file_system.h index ef8a55aeef..41063298f9 100644 --- a/repos/os/include/vfs/fs_file_system.h +++ b/repos/os/include/vfs/fs_file_system.h @@ -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(vfs_handle); + Fs_vfs_handle *fs_handle = static_cast(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 (...) { } } diff --git a/repos/os/src/server/fs_log/main.cc b/repos/os/src/server/fs_log/main.cc index 46755f0435..aec9ac2f74 100644 --- a/repos/os/src/server/fs_log/main.cc +++ b/repos/os/src/server/fs_log/main.cc @@ -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()); diff --git a/repos/os/src/server/lx_fs/main.cc b/repos/os/src/server/lx_fs/main.cc index 58b14a5d00..d804fe29f6 100644 --- a/repos/os/src/server/lx_fs/main.cc +++ b/repos/os/src/server/lx_fs/main.cc @@ -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 diff --git a/repos/os/src/server/ram_fs/main.cc b/repos/os/src/server/ram_fs/main.cc index a3b79dc6d4..f4f2abd1cf 100644 --- a/repos/os/src/server/ram_fs/main.cc +++ b/repos/os/src/server/ram_fs/main.cc @@ -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 diff --git a/repos/os/src/server/tar_fs/main.cc b/repos/os/src/server/tar_fs/main.cc index 7d7b983b8b..c073c9f748 100644 --- a/repos/os/src/server/tar_fs/main.cc +++ b/repos/os/src/server/tar_fs/main.cc @@ -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 diff --git a/repos/os/src/server/trace_fs/file.h b/repos/os/src/server/trace_fs/file.h index fafb51743d..79fd7e72ef 100644 --- a/repos/os/src/server/trace_fs/file.h +++ b/repos/os/src/server/trace_fs/file.h @@ -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); diff --git a/repos/os/src/server/trace_fs/main.cc b/repos/os/src/server/trace_fs/main.cc index febf842f20..d11941e197 100644 --- a/repos/os/src/server/trace_fs/main.cc +++ b/repos/os/src/server/trace_fs/main.cc @@ -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 diff --git a/repos/os/src/server/vfs/node_handle_registry.h b/repos/os/src/server/vfs/node_handle_registry.h index c8236b2978..198129670f 100644 --- a/repos/os/src/server/vfs/node_handle_registry.h +++ b/repos/os/src/server/vfs/node_handle_registry.h @@ -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