vfs: improve read-ready handling in VFS server

This commit is contained in:
Christian Helmuth 2017-02-12 10:58:27 +01:00
parent 9d7cda04fa
commit ad185fe1fe
2 changed files with 120 additions and 16 deletions

View File

@ -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();
} }

View File

@ -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,