mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
vfs: improve read-ready handling in VFS server
This commit is contained in:
parent
9d7cda04fa
commit
ad185fe1fe
@ -139,15 +139,36 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object,
|
|||||||
switch (packet.operation()) {
|
switch (packet.operation()) {
|
||||||
|
|
||||||
case Packet_descriptor::READ:
|
case Packet_descriptor::READ:
|
||||||
|
|
||||||
|
try {
|
||||||
|
_apply(static_cast<File_handle>(packet.handle().value), [&] (File &node) {
|
||||||
|
if (!node.read_ready()) {
|
||||||
|
node.notify_read_ready(true);
|
||||||
|
throw Not_read_ready();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.mode&READ_ONLY)
|
||||||
|
res_length = node.read(_vfs, (char *)content, length, seek);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Not_read_ready) { throw; }
|
||||||
|
catch (Operation_incomplete) { throw Not_read_ready(); }
|
||||||
|
catch (...) {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
_apply(packet.handle(), [&] (Node &node) {
|
_apply(packet.handle(), [&] (Node &node) {
|
||||||
if (!node.read_ready())
|
if (!node.read_ready())
|
||||||
throw Not_read_ready();
|
throw Not_read_ready();
|
||||||
|
|
||||||
if (node.mode&READ_ONLY)
|
if (node.mode&READ_ONLY)
|
||||||
res_length = node.read(_vfs, (char *)content, length, seek);
|
res_length = node.read(_vfs, (char *)content, length, seek);
|
||||||
});
|
});
|
||||||
} catch (Not_read_ready) { throw;
|
}
|
||||||
} catch (...) { }
|
catch (Not_read_ready) { throw; }
|
||||||
|
catch (Operation_incomplete) { throw Not_read_ready(); }
|
||||||
|
catch (...) { }
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Packet_descriptor::WRITE:
|
case Packet_descriptor::WRITE:
|
||||||
@ -162,12 +183,16 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object,
|
|||||||
case Packet_descriptor::READ_READY:
|
case Packet_descriptor::READ_READY:
|
||||||
try {
|
try {
|
||||||
_apply(static_cast<File_handle>(packet.handle().value), [] (File &node) {
|
_apply(static_cast<File_handle>(packet.handle().value), [] (File &node) {
|
||||||
node.notify_read_ready = true;
|
if (!node.read_ready()) {
|
||||||
});
|
node.notify_read_ready(true);
|
||||||
} catch (...) { }
|
|
||||||
|
|
||||||
throw Dont_ack();
|
throw Dont_ack();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Dont_ack) { throw; }
|
||||||
|
catch (...) { }
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
packet.length(res_length);
|
packet.length(res_length);
|
||||||
packet.succeeded(!!res_length);
|
packet.succeeded(!!res_length);
|
||||||
@ -353,13 +378,14 @@ class Vfs_server::Session_component : public File_system::Session_rpc_object,
|
|||||||
/* File_io_handler interface */
|
/* File_io_handler interface */
|
||||||
void handle_file_io(File &file) override
|
void handle_file_io(File &file) override
|
||||||
{
|
{
|
||||||
if (file.notify_read_ready && tx_sink()->ready_to_ack()) {
|
if (file.notify_read_ready() && file.read_ready()
|
||||||
|
&& tx_sink()->ready_to_ack()) {
|
||||||
Packet_descriptor packet(Packet_descriptor(),
|
Packet_descriptor packet(Packet_descriptor(),
|
||||||
Node_handle(file.id().value),
|
Node_handle(file.id().value),
|
||||||
Packet_descriptor::READ_READY,
|
Packet_descriptor::READ_READY,
|
||||||
0, 0);
|
0, 0);
|
||||||
tx_sink()->acknowledge_packet(packet);
|
tx_sink()->acknowledge_packet(packet);
|
||||||
file.notify_read_ready = false;
|
file.notify_read_ready(false);
|
||||||
}
|
}
|
||||||
_process_packets();
|
_process_packets();
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,13 @@ namespace Vfs_server {
|
|||||||
virtual void handle_file_io(File &file) = 0;
|
virtual void handle_file_io(File &file) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read/write operation incomplete exception
|
||||||
|
*
|
||||||
|
* The operation can be retried later.
|
||||||
|
*/
|
||||||
|
struct Operation_incomplete { };
|
||||||
|
|
||||||
/* Vfs::MAX_PATH is shorter than File_system::MAX_PATH */
|
/* Vfs::MAX_PATH is shorter than File_system::MAX_PATH */
|
||||||
enum { MAX_PATH_LEN = Vfs::MAX_PATH_LEN };
|
enum { MAX_PATH_LEN = Vfs::MAX_PATH_LEN };
|
||||||
|
|
||||||
@ -149,9 +156,13 @@ class Vfs_server::File : public Node
|
|||||||
Vfs::Vfs_handle *_handle;
|
Vfs::Vfs_handle *_handle;
|
||||||
char const *_leaf_path; /* offset pointer to Node::_path */
|
char const *_leaf_path; /* offset pointer to Node::_path */
|
||||||
|
|
||||||
public:
|
bool _notify_read_ready = false;
|
||||||
|
|
||||||
bool notify_read_ready = false;
|
enum class Op_state {
|
||||||
|
IDLE, READ_QUEUED
|
||||||
|
} op_state = Op_state::IDLE;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
File(Node_space &space,
|
File(Node_space &space,
|
||||||
Vfs::File_system &vfs,
|
Vfs::File_system &vfs,
|
||||||
@ -180,6 +191,15 @@ class Vfs_server::File : public Node
|
|||||||
mark_as_updated();
|
mark_as_updated();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void notify_read_ready(bool requested)
|
||||||
|
{
|
||||||
|
if (requested)
|
||||||
|
_handle->fs().notify_read_ready(_handle);
|
||||||
|
_notify_read_ready = requested;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool notify_read_ready() const { return _notify_read_ready; }
|
||||||
|
|
||||||
|
|
||||||
/********************
|
/********************
|
||||||
** Node interface **
|
** Node interface **
|
||||||
@ -188,8 +208,6 @@ class Vfs_server::File : public Node
|
|||||||
size_t read(Vfs::File_system&, char *dst, size_t len,
|
size_t read(Vfs::File_system&, char *dst, size_t len,
|
||||||
seek_off_t seek_offset) override
|
seek_off_t seek_offset) override
|
||||||
{
|
{
|
||||||
Vfs::file_size res = 0;
|
|
||||||
|
|
||||||
if (seek_offset == SEEK_TAIL) {
|
if (seek_offset == SEEK_TAIL) {
|
||||||
typedef Directory_service::Stat_result Result;
|
typedef Directory_service::Stat_result Result;
|
||||||
Vfs::Directory_service::Stat st;
|
Vfs::Directory_service::Stat st;
|
||||||
@ -200,8 +218,68 @@ class Vfs_server::File : public Node
|
|||||||
}
|
}
|
||||||
|
|
||||||
_handle->seek(seek_offset);
|
_handle->seek(seek_offset);
|
||||||
_handle->fs().read(_handle, dst, len, res);
|
|
||||||
return res;
|
typedef Vfs::File_io_service::Read_result Result;
|
||||||
|
|
||||||
|
Vfs::file_size out_count = 0;
|
||||||
|
Result out_result = Result::READ_OK;
|
||||||
|
|
||||||
|
switch (op_state) {
|
||||||
|
case Op_state::IDLE:
|
||||||
|
|
||||||
|
if (!_handle->fs().queue_read(_handle, dst, len, out_result, out_count))
|
||||||
|
throw Operation_incomplete();
|
||||||
|
|
||||||
|
switch (out_result) {
|
||||||
|
case Result::READ_OK:
|
||||||
|
op_state = Op_state::IDLE;
|
||||||
|
return out_count;
|
||||||
|
|
||||||
|
case Result::READ_ERR_WOULD_BLOCK:
|
||||||
|
case Result::READ_ERR_AGAIN:
|
||||||
|
case Result::READ_ERR_INTERRUPT:
|
||||||
|
op_state = Op_state::IDLE;
|
||||||
|
throw Operation_incomplete();
|
||||||
|
|
||||||
|
case Result::READ_ERR_IO:
|
||||||
|
case Result::READ_ERR_INVALID:
|
||||||
|
op_state = Op_state::IDLE;
|
||||||
|
/* FIXME revise error handling */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case Result::READ_QUEUED:
|
||||||
|
op_state = Op_state::READ_QUEUED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fall through */
|
||||||
|
|
||||||
|
case Op_state::READ_QUEUED:
|
||||||
|
out_result = _handle->fs().complete_read(_handle, dst, len, out_count);
|
||||||
|
switch (out_result) {
|
||||||
|
case Result::READ_OK:
|
||||||
|
op_state = Op_state::IDLE;
|
||||||
|
return out_count;
|
||||||
|
|
||||||
|
case Result::READ_ERR_WOULD_BLOCK:
|
||||||
|
case Result::READ_ERR_AGAIN:
|
||||||
|
case Result::READ_ERR_INTERRUPT:
|
||||||
|
op_state = Op_state::IDLE;
|
||||||
|
throw Operation_incomplete();
|
||||||
|
|
||||||
|
case Result::READ_ERR_IO:
|
||||||
|
case Result::READ_ERR_INVALID:
|
||||||
|
op_state = Op_state::IDLE;
|
||||||
|
/* FIXME revise error handling */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case Result::READ_QUEUED:
|
||||||
|
op_state = Op_state::READ_QUEUED;
|
||||||
|
throw Operation_incomplete();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t write(Vfs::File_system&, char const *src, size_t len,
|
size_t write(Vfs::File_system&, char const *src, size_t len,
|
||||||
|
Loading…
Reference in New Issue
Block a user