Add write completion loop to VFS server and libc

Loop at the VFS server and libc VFS plugin on partial writes. This
implies that the VFS server will not process successive packets for an
open node until a write packet has been processed completely. The libc
will now supspend and reissue write requests to the VFS until the write
has been submitted completely.

Ref #2303
Fix #2971
This commit is contained in:
Ehmry - 2019-06-04 18:22:48 +02:00
parent f6d22088f2
commit efe39ab077
2 changed files with 19 additions and 7 deletions

View File

@ -445,7 +445,7 @@ ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf,
Vfs::Vfs_handle *handle;
void const *buf;
::size_t count;
::size_t const count;
Vfs::file_size &out_count;
Result &out_result;
@ -458,14 +458,16 @@ ssize_t Libc::Vfs_plugin::write(Libc::File_descriptor *fd, const void *buf,
bool suspend() override
{
Vfs::file_size out = 0;
try {
out_result = VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf,
count, out_count));
retry = false;
out_result = VFS_THREAD_SAFE(handle->fs().write(handle, (char const *)buf+out_count,
count - out_count, out));
} catch (Vfs::File_io_service::Insufficient_buffer) {
retry = true;
out_result = Result::WRITE_OK;
}
out_count += out;
retry = (out_result == Result::WRITE_OK) && (out_count < count);
return retry;
}
} check(handle, buf, count, out_count, out_result);

View File

@ -251,6 +251,8 @@ class Vfs_server::Io_node : public Vfs_server::Node,
if (result == Write_result::WRITE_OK) {
mark_as_updated();
_packet.succeeded(true);
} else {
_packet.succeeded(false);
}
}
catch (Vfs::File_io_service::Insufficient_buffer)
@ -609,6 +611,8 @@ class Vfs_server::File : public Io_node
char const *_leaf_path = nullptr; /* offset pointer to Node::_path */
file_size _write_offset { 0 };
inline
seek_off_t seek_tail(file_size count)
{
@ -648,9 +652,15 @@ class Vfs_server::File : public Io_node
if (seek_offset == (seek_off_t)SEEK_TAIL)
seek_offset = seek_tail(count);
bool result = _vfs_write(_stream.packet_content(_packet),
count, seek_offset, out_count);
bool result = _vfs_write(_stream.packet_content(_packet)+_write_offset,
count-_write_offset, seek_offset, out_count);
if (result) {
/* loop until the write completes or produces an error */
if (_packet.succeeded() && ((out_count+_write_offset) < count)) {
_write_offset += out_count;
return false;
}
_write_offset = 0;
_ack_packet(out_count);
if (out_count > 0) {
mark_as_updated();