vfs: simplify File_io_service::write return values

This patch removes the 'Insufficient_buffer' exception by returning the
WRITE_ERR_WOULD_BLOCK result value instead. It also eliminates the
superfluous WRITE_ERR_AGAIN and WRITE_ERR_INTERRUPT codes.

Issue #4697
This commit is contained in:
Norman Feske 2022-12-06 17:04:26 +01:00 committed by Christian Helmuth
parent d9f5dda322
commit cf87b0fadb
20 changed files with 228 additions and 321 deletions

View File

@ -159,7 +159,7 @@ class Vfs::Rump_file_system : public File_system
case EWOULDBLOCK: return WRITE_ERR_WOULD_BLOCK;
case EINVAL: return WRITE_ERR_INVALID;
case EIO: return WRITE_ERR_IO;
case EINTR: return WRITE_ERR_INTERRUPT;
case EINTR: return WRITE_ERR_IO;
default:
Genode::error(__func__, ": unhandled rump error ", errno);
return WRITE_ERR_IO;

View File

@ -174,31 +174,25 @@ namespace Util {
bool completed = false;
file_size out = 0;
Result result = Result::WRITE_ERR_INVALID;
try {
result = _handle.fs().write(&_handle,
_data + _current_offset,
_current_count, out);
} catch (Vfs::File_io_service::Insufficient_buffer) {
return progress;
}
if ( result == Result::WRITE_ERR_AGAIN
|| result == Result::WRITE_ERR_INTERRUPT
|| result == Result::WRITE_ERR_WOULD_BLOCK) {
Result const result =
_handle.fs().write(&_handle, _data + _current_offset,
_current_count, out);
switch (result) {
case Result::WRITE_ERR_WOULD_BLOCK:
return progress;
} else
if (result == Result::WRITE_OK) {
case Result::WRITE_OK:
_current_offset += out;
_current_count -= out;
_success = true;
} else
break;
if ( result == Result::WRITE_ERR_IO
|| result == Result::WRITE_ERR_INVALID) {
case Result::WRITE_ERR_IO:
case Result::WRITE_ERR_INVALID:
_success = false;
completed = true;
break;
}
if (_current_count == 0 || completed || (out == 0 && _allow_partial)) {

View File

@ -70,15 +70,16 @@ Crypto::Result Crypto::add_key(Key const &key)
_add_key_handle.seek(0);
file_size nr_of_written_bytes { 0 };
try {
_add_key_handle.fs().write(
&_add_key_handle, buffer, sizeof (buffer),
nr_of_written_bytes);
} catch (File_io_service::Insufficient_buffer) {
using Write_result = Vfs::File_io_service::Write_result;
Write_result const result =
_add_key_handle.fs().write(&_add_key_handle, buffer, sizeof (buffer),
nr_of_written_bytes);
if (result == Write_result::WRITE_ERR_WOULD_BLOCK)
return Result::RETRY_LATER;
}
Key_directory &key_dir { _get_unused_key_dir() };
key_dir.encrypt_handle = &vfs_open_rw(
@ -98,17 +99,17 @@ Crypto::Result Crypto::remove_key(Cbe::Key::Id key_id)
{
Vfs::file_size written = 0;
_remove_key_handle.seek(0);
try {
using Write_result = Vfs::File_io_service::Write_result;
Write_result const result =
_remove_key_handle.fs().write(&_remove_key_handle,
(char const*)&key_id.value,
sizeof (key_id.value),
written);
(void)written;
} catch (Vfs::File_io_service::Insufficient_buffer) {
if (result == Write_result::WRITE_ERR_WOULD_BLOCK)
return Result::RETRY_LATER;
}
Key_directory &key_dir { _lookup_key_dir(key_id.value) };
_env.root_dir().close(key_dir.encrypt_handle);
key_dir.encrypt_handle = nullptr;
@ -200,22 +201,17 @@ void Crypto::_execute_decrypt_block(Job &job,
{
job.handle->seek(job.request.block_number() * Cbe::BLOCK_SIZE);
file_size nr_of_written_bytes { 0 };
try {
job.handle->fs().write(
job.handle,
reinterpret_cast<char const*>(
&cipher_buf.item(job.cipher_buf_idx)),
file_size(sizeof (Cbe::Block_data)),
nr_of_written_bytes);
job.state = Job_state::OP_WRITTEN_TO_VFS_HANDLE;
progress = true;
return;
job.handle->fs().write(
job.handle,
reinterpret_cast<char const*>(
&cipher_buf.item(job.cipher_buf_idx)),
file_size(sizeof (Cbe::Block_data)),
nr_of_written_bytes);
} catch (Vfs::File_io_service::Insufficient_buffer) {
return;
}
job.state = Job_state::OP_WRITTEN_TO_VFS_HANDLE;
progress = true;
return;
}
case Job_state::OP_WRITTEN_TO_VFS_HANDLE:
{
@ -271,22 +267,17 @@ void Crypto::_execute_encrypt_block(Job &job,
{
job.handle->seek(job.request.block_number() * Cbe::BLOCK_SIZE);
file_size nr_of_written_bytes { 0 };
try {
job.handle->fs().write(
job.handle,
reinterpret_cast<char const*>(
&plain_buf.item(job.plain_buf_idx)),
file_size(sizeof (Cbe::Block_data)),
nr_of_written_bytes);
job.state = Job_state::OP_WRITTEN_TO_VFS_HANDLE;
progress = true;
return;
job.handle->fs().write(
job.handle,
reinterpret_cast<char const*>(
&plain_buf.item(job.plain_buf_idx)),
file_size(sizeof (Cbe::Block_data)),
nr_of_written_bytes);
} catch (Vfs::File_io_service::Insufficient_buffer) {
return;
}
job.state = Job_state::OP_WRITTEN_TO_VFS_HANDLE;
progress = true;
return;
}
case Job_state::OP_WRITTEN_TO_VFS_HANDLE:
{

View File

@ -393,22 +393,14 @@ class Vfs_block_io_job
reinterpret_cast<char *>(
&io_data.item(_cbe_req_io_buf_idx(_cbe_req))) };
Result result;
try {
result = _handle.fs().write(&_handle,
data + _nr_of_processed_bytes,
_nr_of_remaining_bytes,
nr_of_written_bytes);
Result const result =
_handle.fs().write(&_handle,
data + _nr_of_processed_bytes,
_nr_of_remaining_bytes,
nr_of_written_bytes);
} catch (Vfs::File_io_service::Insufficient_buffer) {
return;
}
switch (result) {
case Result::WRITE_ERR_AGAIN:
case Result::WRITE_ERR_INTERRUPT:
case Result::WRITE_ERR_WOULD_BLOCK:
return;
case Result::WRITE_OK:

View File

@ -37,22 +37,12 @@ void Trust_anchor::_execute_write_read_operation(Vfs_handle &file,
case Job_state::WRITE_IN_PROGRESS:
{
file_size nr_of_written_bytes { 0 };
Write_result result { Write_result::WRITE_ERR_INVALID };
try {
result =
file.fs().write(
&file, write_buf + _job.fl_offset,
_job.fl_size, nr_of_written_bytes);
} catch (Vfs::File_io_service::Insufficient_buffer) {
return;
}
Write_result const result =
file.fs().write(&file, write_buf + _job.fl_offset,
_job.fl_size, nr_of_written_bytes);
switch (result) {
case Write_result::WRITE_ERR_AGAIN:
case Write_result::WRITE_ERR_INTERRUPT:
case Write_result::WRITE_ERR_WOULD_BLOCK:
case Write_result::WRITE_ERR_WOULD_BLOCK:
return;
case Write_result::WRITE_OK:
@ -155,22 +145,14 @@ void Trust_anchor::_execute_write_operation(Vfs_handle &file,
case Job_state::WRITE_IN_PROGRESS:
{
file_size nr_of_written_bytes { 0 };
Write_result result { Write_result::WRITE_ERR_INVALID };
try {
result =
file.fs().write(
&file, write_buf + _job.fl_offset,
_job.fl_size, nr_of_written_bytes);
Write_result const result =
file.fs().write(
&file, write_buf + _job.fl_offset,
_job.fl_size, nr_of_written_bytes);
} catch (Vfs::File_io_service::Insufficient_buffer) {
return;
}
switch (result) {
case Write_result::WRITE_ERR_AGAIN:
case Write_result::WRITE_ERR_INTERRUPT:
case Write_result::WRITE_ERR_WOULD_BLOCK:
case Write_result::WRITE_ERR_WOULD_BLOCK:
return;
case Write_result::WRITE_OK:

View File

@ -248,30 +248,27 @@ class Vfs_replay
bool completed = false;
file_size out = 0;
Result result = Result::WRITE_ERR_INVALID;
try {
result = _vfs_handle->fs().write(_vfs_handle,
_write_buffer.local_addr<char>(),
request.current_count, out);
} catch (Vfs::File_io_service::Insufficient_buffer) {
Result const result =
_vfs_handle->fs().write(_vfs_handle,
_write_buffer.local_addr<char>(),
request.current_count, out);
switch (result) {
case Result::WRITE_ERR_WOULD_BLOCK:
return progress;
}
if ( result == Result::WRITE_ERR_AGAIN
|| result == Result::WRITE_ERR_INTERRUPT
|| result == Result::WRITE_ERR_WOULD_BLOCK) {
return progress;
}
if (result == Result::WRITE_OK) {
case Result::WRITE_OK:
request.current_offset += out;
request.current_count -= out;
request.success = true;
}
break;
if ( result == Result::WRITE_ERR_IO
|| result == Result::WRITE_ERR_INVALID) {
case Result::WRITE_ERR_IO:
case Result::WRITE_ERR_INVALID:
request.success = false;
completed = true;
break;
}
if (request.current_count == 0 || completed) {
request.state = Request::State::WRITE_COMPLETE;
} else {

View File

@ -233,7 +233,7 @@ class Vfs_audit::File_system : public Vfs::File_system
if (result == WRITE_OK)
_log("wrote to ", h.path, " ", out, " / ", len);
else if (result == WRITE_ERR_WOULD_BLOCK || result == WRITE_ERR_AGAIN)
else if (result == WRITE_ERR_WOULD_BLOCK)
_log("write stalled for ", h.path);
else
_log("write failed for ", h.path);

View File

@ -152,33 +152,27 @@ namespace Vfs_cbe {
bool completed = false;
file_size out = 0;
Result result = Result::WRITE_ERR_INVALID;
try {
char const * const data =
reinterpret_cast<char const * const>(&io_data.item(_index));
result = _handle.fs().write(&_handle,
data + _current_offset,
_current_count, out);
} catch (Vfs::File_io_service::Insufficient_buffer) {
return progress;
}
char const * const data =
reinterpret_cast<char const * const>(&io_data.item(_index));
if ( result == Result::WRITE_ERR_AGAIN
|| result == Result::WRITE_ERR_INTERRUPT
|| result == Result::WRITE_ERR_WOULD_BLOCK) {
Result const result =
_handle.fs().write(&_handle, data + _current_offset,
_current_count, out);
switch (result) {
case Result::WRITE_ERR_WOULD_BLOCK:
return progress;
} else
if (result == Result::WRITE_OK) {
case Result::WRITE_OK:
_current_offset += out;
_current_count -= out;
_success = true;
} else
break;
if ( result == Result::WRITE_ERR_IO
|| result == Result::WRITE_ERR_INVALID) {
case Result::WRITE_ERR_IO:
case Result::WRITE_ERR_INVALID:
_success = false;
completed = true;
break;
}
if (_current_count == 0 || completed) {

View File

@ -1185,14 +1185,15 @@ class Vfs_cbe::Wrapper
file_size written = 0;
_add_key_handle->seek(0);
try {
using Write_result = Vfs::File_io_service::Write_result;
Write_result const result =
_add_key_handle->fs().write(_add_key_handle,
buffer, sizeof (buffer), written);
(void)written;
} catch (Vfs::File_io_service::Insufficient_buffer) {
/* try again later */
break;
}
if (result == Write_result::WRITE_ERR_WOULD_BLOCK)
break; /* try again later */
/*
* Instead of acknowledge the CBE's request before we write
@ -1278,16 +1279,17 @@ class Vfs_cbe::Wrapper
file_size written = 0;
_remove_key_handle->seek(0);
try {
using Write_result = Vfs::File_io_service::Write_result;
Write_result const result =
_remove_key_handle->fs().write(_remove_key_handle,
(char const*)&key_id.value,
sizeof (key_id.value),
written);
(void)written;
} catch (Vfs::File_io_service::Insufficient_buffer) {
/* try again later */
break;
}
if (result == Write_result::WRITE_ERR_WOULD_BLOCK)
break; /* try again later */
Crypto_file *cf = nullptr;
try {
@ -1395,14 +1397,13 @@ class Vfs_cbe::Wrapper
case Crypto_job::State::IDLE:
break;
case Crypto_job::State::SUBMITTED:
try {
{
char const *data = nullptr;
if (op == Crypto_job::Operation::ENCRYPT) {
data = reinterpret_cast<char const*>(&plain.item(plain_index));
} else
if (op == Crypto_job::Operation::DECRYPT) {
}
else if (op == Crypto_job::Operation::DECRYPT) {
data = reinterpret_cast<char const*>(&cipher.item(cipher_index));
}
@ -1413,16 +1414,14 @@ class Vfs_cbe::Wrapper
if (op == Crypto_job::Operation::ENCRYPT) {
cbe.crypto_cipher_data_requested(plain_index);
} else
if (op == Crypto_job::Operation::DECRYPT) {
}
else if (op == Crypto_job::Operation::DECRYPT) {
cbe.crypto_plain_data_requested(cipher_index);
}
state = Crypto_job::State::PENDING;
result.progress |= true;
} catch (Vfs::File_io_service::Insufficient_buffer) { }
}
[[fallthrough]];
case Crypto_job::State::PENDING:
@ -1939,9 +1938,9 @@ class Vfs_cbe::Data_file_system : public Single_file_system
State state = _w.frontend_request().state;
if (state == State::NONE) {
if (!_w.client_request_acceptable()) {
throw Insufficient_buffer();
}
if (!_w.client_request_acceptable())
return Write_result::WRITE_ERR_WOULD_BLOCK;
using Op = Cbe::Request::Operation;
bool const accepted =
@ -1956,7 +1955,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system
if ( state == State::PENDING
|| state == State::IN_PROGRESS) {
_w.enqueue_handle(*this);
throw Insufficient_buffer();
return WRITE_ERR_WOULD_BLOCK;
}
if (state == State::COMPLETE) {

View File

@ -98,7 +98,6 @@ class Vfs_import::File_system : public Vfs::File_system
dst_handle, target.string(), count, out_count);
switch (wres) {
case WRITE_ERR_AGAIN:
case WRITE_ERR_WOULD_BLOCK:
break;
default:
@ -151,41 +150,35 @@ class Vfs_import::File_system : public Vfs::File_system
if (!bytes_from_source) break;
bool stalled { false };
bool write_error { false };
Vfs::file_size remaining_bytes { bytes_from_source };
char const *src { buf };
while (remaining_bytes > 0 && !write_error) {
try {
Vfs::file_size out_count { 0 };
switch (dst_handle->fs().write(dst_handle, src,
remaining_bytes,
out_count)) {
case WRITE_ERR_AGAIN:
case WRITE_ERR_WOULD_BLOCK:
stalled = true;
break;
case Write_result::WRITE_ERR_INVALID:
case Write_result::WRITE_ERR_IO:
case Write_result::WRITE_ERR_INTERRUPT:
env.root_dir().unlink(path.string());
write_error = true;
break;
case WRITE_OK:
out_count = min(remaining_bytes, out_count);
remaining_bytes -= out_count;
src += out_count;
at.value += out_count;
dst_handle->advance_seek(out_count);
break;
}
} catch (Vfs::File_io_service::Insufficient_buffer) {
stalled = true; }
Vfs::file_size out_count { 0 };
if (stalled)
env.env().ep().wait_and_dispatch_one_io_signal();
switch (dst_handle->fs().write(dst_handle, src,
remaining_bytes,
out_count)) {
case WRITE_ERR_WOULD_BLOCK:
env.io().commit_and_wait();
break;
case Write_result::WRITE_ERR_INVALID:
case Write_result::WRITE_ERR_IO:
env.root_dir().unlink(path.string());
write_error = true;
break;
case WRITE_OK:
out_count = min(remaining_bytes, out_count);
remaining_bytes -= out_count;
src += out_count;
at.value += out_count;
dst_handle->advance_seek(out_count);
break;
}
}
if (write_error)
break;

View File

@ -844,9 +844,7 @@ ssize_t Libc::Vfs_plugin::write(File_descriptor *fd, const void *buf,
if (nonblocking) {
monitor().monitor([&] {
try {
out_result = handle->fs().write(handle, (char const *)buf, count, out_count);
} catch (Vfs::File_io_service::Insufficient_buffer) { }
out_result = handle->fs().write(handle, (char const *)buf, count, out_count);
return Fn::COMPLETE;
});
} else {
@ -886,23 +884,21 @@ ssize_t Libc::Vfs_plugin::write(File_descriptor *fd, const void *buf,
/* number of bytes written in one iteration */
Vfs::file_size partial_out_count = 0;
try {
char const * const src = (char const *)_buf + _offset;
char const * const src = (char const *)_buf + _offset;
_out_result = _handle->fs().write(_handle, src, _count, partial_out_count);
_out_result = _handle->fs().write(_handle, src, _count, partial_out_count);
} catch (Vfs::File_io_service::Insufficient_buffer) { return Fn::INCOMPLETE; }
if (_out_result == Result::WRITE_ERR_WOULD_BLOCK)
return Fn::INCOMPLETE;
if (_out_result != Result::WRITE_OK) {
if (_out_result != Result::WRITE_OK)
return Fn::COMPLETE;
}
/* increment byte count reported to caller */
_out_count += partial_out_count;
bool const write_complete = (partial_out_count == _count);
if (write_complete) {
if (write_complete)
return Fn::COMPLETE;
}
/*
* If the write has not consumed all bytes, set up
@ -941,11 +937,9 @@ ssize_t Libc::Vfs_plugin::write(File_descriptor *fd, const void *buf,
Plugin::resume_all();
switch (out_result) {
case Result::WRITE_ERR_AGAIN: return Errno(EAGAIN);
case Result::WRITE_ERR_WOULD_BLOCK: return Errno(EWOULDBLOCK);
case Result::WRITE_ERR_INVALID: return Errno(EINVAL);
case Result::WRITE_ERR_IO: return Errno(EIO);
case Result::WRITE_ERR_INTERRUPT: return Errno(EINTR);
case Result::WRITE_OK: break;
}
@ -2283,12 +2277,15 @@ int Libc::Vfs_plugin::symlink(const char *target_path, const char *link_path)
case Stage::WRITE:
{
try {
handle->fs().write(handle, target_path, count, out_count);
} catch (Vfs::File_io_service::Insufficient_buffer) {
typedef Vfs::File_io_service::Write_result Result;
Result result = handle->fs().write(handle, target_path,
count, out_count);
if (result == Result::WRITE_ERR_WOULD_BLOCK)
return Fn::INCOMPLETE;
}
} stage = Stage::SYNC; [[fallthrough]];
}
stage = Stage::SYNC;
[[fallthrough]];
case Stage::SYNC:
{

View File

@ -2013,16 +2013,15 @@ class Lwip::File_system final : public Vfs::File_system, public Lwip::Directory
char const *src, file_size count,
file_size &out_count) override
{
Write_result res = Write_result::WRITE_ERR_INVALID;
out_count = 0;
if ((vfs_handle->status_flags() & OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY)
return Write_result::WRITE_ERR_INVALID;
if (Lwip_handle *handle = dynamic_cast<Lwip_handle*>(vfs_handle)) {
res = handle->write(src, count, out_count);
if (res == WRITE_ERR_WOULD_BLOCK) throw Insufficient_buffer();
}
return res;
if (Lwip_handle *handle = dynamic_cast<Lwip_handle*>(vfs_handle))
return handle->write(src, count, out_count);
return Write_result::WRITE_ERR_INVALID;
}
Read_result complete_read(Vfs_handle *vfs_handle,

View File

@ -188,6 +188,8 @@ struct Vfs::Oss_file_system::Audio
}
};
using Write_result = Vfs::File_io_service::Write_result;
private:
Audio(Audio const &);
@ -509,14 +511,14 @@ struct Vfs::Oss_file_system::Audio
return true;
}
bool write(char const *buf, file_size buf_size, file_size &out_size)
Write_result write(char const *buf, file_size buf_size, file_size &out_size)
{
using namespace Genode;
out_size = 0;
if (_info.ofrag_bytes == 0)
throw Vfs::File_io_service::Insufficient_buffer();
return Write_result::WRITE_ERR_WOULD_BLOCK;
bool block_write = false;
@ -527,10 +529,8 @@ struct Vfs::Oss_file_system::Audio
unsigned stream_samples_to_write = buf_size / CHANNELS / sizeof(int16_t);
if (stream_samples_to_write == 0) {
/* invalid argument */
return false;
}
if (stream_samples_to_write == 0)
return Write_result::WRITE_ERR_INVALID;
_start_output();
@ -554,18 +554,18 @@ struct Vfs::Oss_file_system::Audio
_out[0]->stream()->reset();
}
}
} else {
/*
* Look up the previously allocated packet.
* The tail pointer got incremented after allocation,
* so we need to decrement by 1.
*/
unsigned const tail =
} else {
/*
* Look up the previously allocated packet.
* The tail pointer got incremented after allocation,
* so we need to decrement by 1.
*/
unsigned const tail =
(_out[0]->stream()->tail() +
Audio_out::QUEUE_SIZE - 1) %
Audio_out::QUEUE_SIZE;
lp = _out[0]->stream()->get(tail);
}
}
unsigned const pos = _out[0]->stream()->packet_position(lp);
Audio_out::Packet *rp = _out[1]->stream()->get(pos);
@ -602,14 +602,15 @@ struct Vfs::Oss_file_system::Audio
/* update info */
update_info_ofrag_avail_from_optr_fifo_samples();
if (block_write) { throw Vfs::File_io_service::Insufficient_buffer(); }
if (block_write)
return Write_result::WRITE_ERR_WOULD_BLOCK;
return true;
return Write_result::WRITE_OK;
}
}
}
return true;
return Write_result::WRITE_OK;
}
};
@ -665,12 +666,13 @@ class Vfs::Oss_file_system::Data_file_system : public Single_file_system
Write_result write(char const *buf, file_size buf_size,
file_size &out_count) override
{
try {
return _audio.write(buf, buf_size, out_count) ? WRITE_OK : WRITE_ERR_INVALID;
} catch (Vfs::File_io_service::Insufficient_buffer) {
Write_result const result = _audio.write(buf, buf_size, out_count);
if (result == Write_result::WRITE_ERR_WOULD_BLOCK) {
blocked = true;
return WRITE_OK;
}
return result;
}
bool read_ready() override

View File

@ -755,35 +755,28 @@ class Genode::Writeable_file : Noncopyable
bool stalled = false;
try {
Vfs::file_size out_count = 0;
Vfs::file_size out_count = 0;
using Write_result = Vfs::File_io_service::Write_result;
using Write_result = Vfs::File_io_service::Write_result;
switch (handle.fs().write(&handle, src, remaining_bytes,
out_count)) {
switch (handle.fs().write(&handle, src, remaining_bytes, out_count)) {
case Write_result::WRITE_ERR_AGAIN:
case Write_result::WRITE_ERR_WOULD_BLOCK:
stalled = true;
break;
case Write_result::WRITE_ERR_WOULD_BLOCK:
stalled = true;
break;
case Write_result::WRITE_ERR_INVALID:
case Write_result::WRITE_ERR_IO:
case Write_result::WRITE_ERR_INTERRUPT:
write_error = true;
break;
case Write_result::WRITE_ERR_INVALID:
case Write_result::WRITE_ERR_IO:
write_error = true;
break;
case Write_result::WRITE_OK:
out_count = min((Vfs::file_size)remaining_bytes, out_count);
remaining_bytes -= (size_t)out_count;
src += out_count;
handle.advance_seek(out_count);
break;
};
}
catch (Vfs::File_io_service::Insufficient_buffer) {
stalled = true; }
case Write_result::WRITE_OK:
out_count = min((Vfs::file_size)remaining_bytes, out_count);
remaining_bytes -= (size_t)out_count;
src += out_count;
handle.advance_seek(out_count);
break;
};
if (stalled)
io.commit_and_wait();

View File

@ -30,16 +30,8 @@ struct Vfs::File_io_service : Interface
** Write **
***********/
/*
* Exception, thrown when, for example, 'alloc_packet()' or
* 'submit_packet()' failed in the VFS plugin. The caller can try again
* after a previous VFS request is completed.
*/
struct Insufficient_buffer { };
enum Write_result { WRITE_ERR_AGAIN, WRITE_ERR_WOULD_BLOCK,
WRITE_ERR_INVALID, WRITE_ERR_IO,
WRITE_ERR_INTERRUPT, WRITE_OK };
enum Write_result { WRITE_ERR_WOULD_BLOCK, WRITE_ERR_INVALID,
WRITE_ERR_IO, WRITE_OK };
virtual Write_result write(Vfs_handle *vfs_handle,
char const *buf, file_size buf_size,

View File

@ -133,11 +133,9 @@ static inline void print(Genode::Output &output, Vfs::File_io_service::Write_res
switch (r) {
CASE_PRINT(WRITE_OK);
CASE_PRINT(WRITE_ERR_AGAIN);
CASE_PRINT(WRITE_ERR_WOULD_BLOCK);
CASE_PRINT(WRITE_ERR_INVALID);
CASE_PRINT(WRITE_ERR_IO);
CASE_PRINT(WRITE_ERR_INTERRUPT);
}
#undef CASE_PRINT

View File

@ -504,8 +504,8 @@ class Vfs::Fs_file_system : public File_system, private Remote_io
return read_num_bytes;
}
file_size _write(Fs_vfs_handle &handle,
const char *buf, file_size count, file_size seek_offset)
Write_result _write(Fs_vfs_handle &handle, file_size const seek_offset,
const char *buf, file_size count, file_size &out_count)
{
/*
* TODO
@ -524,7 +524,7 @@ class Vfs::Fs_file_system : public File_system, private Remote_io
if (!source.ready_to_submit()) {
if (!handle.enqueued())
_congested_handles.enqueue(handle);
throw Insufficient_buffer();
return Write_result::WRITE_ERR_WOULD_BLOCK;
}
try {
@ -537,15 +537,18 @@ class Vfs::Fs_file_system : public File_system, private Remote_io
memcpy(source.packet_content(packet_in), buf, (size_t)count);
_submit_packet(packet_in);
} catch (::File_system::Session::Tx::Source::Packet_alloc_failed) {
}
catch (::File_system::Session::Tx::Source::Packet_alloc_failed) {
if (!handle.enqueued())
_congested_handles.enqueue(handle);
throw Insufficient_buffer();
} catch (...) {
Genode::error("unhandled exception");
return 0;
return Write_result::WRITE_ERR_WOULD_BLOCK;
}
return count;
catch (...) {
Genode::error("unhandled exception");
return Write_result::WRITE_ERR_IO;
}
out_count = count;
return Write_result::WRITE_OK;
}
void _handle_ack()
@ -967,12 +970,11 @@ class Vfs::Fs_file_system : public File_system, private Remote_io
********************************/
Write_result write(Vfs_handle *vfs_handle, char const *buf,
file_size buf_size, file_size &out_count) override
file_size count, file_size &out_count) override
{
Fs_vfs_handle &handle = static_cast<Fs_vfs_handle &>(*vfs_handle);
out_count = _write(handle, buf, buf_size, handle.seek());
return WRITE_OK;
return _write(handle, handle.seek(), buf, count, out_count);
}
bool queue_read(Vfs_handle *vfs_handle, file_size count) override

View File

@ -408,25 +408,20 @@ class Vfs_server::Io_node : public Vfs_server::Node,
seek_off_t write_pos)
{
file_size out_count = 0;
try {
_handle.seek(_initial_write_seek_offset + write_pos);
_handle.seek(_initial_write_seek_offset + write_pos);
switch (_handle.fs().write(&_handle, src_ptr, length, out_count)) {
case Write_result::WRITE_ERR_AGAIN:
case Write_result::WRITE_ERR_WOULD_BLOCK:
break;
switch (_handle.fs().write(&_handle, src_ptr, length, out_count)) {
case Write_result::WRITE_ERR_WOULD_BLOCK:
break;
case Write_result::WRITE_ERR_INVALID:
case Write_result::WRITE_ERR_IO:
case Write_result::WRITE_ERR_INTERRUPT:
_acknowledge_as_failure();
break;
case Write_result::WRITE_ERR_INVALID:
case Write_result::WRITE_ERR_IO:
_acknowledge_as_failure();
break;
case Write_result::WRITE_OK:
break;
}
case Write_result::WRITE_OK:
break;
}
catch (Vfs::File_io_service::Insufficient_buffer) { /* re-execute */ }
_modified = true;
@ -452,14 +447,11 @@ class Vfs_server::Io_node : public Vfs_server::Node,
void _execute_write_timestamp()
{
try {
_packet.with_timestamp([&] (::File_system::Timestamp const time) {
Vfs::Timestamp ts { .value = time.value };
_handle.fs().update_modification_timestamp(&_handle, ts);
});
_acknowledge_as_success(0);
}
catch (Vfs::File_io_service::Insufficient_buffer) { }
_packet.with_timestamp([&] (::File_system::Timestamp const time) {
Vfs::Timestamp ts { .value = time.value };
_handle.fs().update_modification_timestamp(&_handle, ts);
});
_acknowledge_as_success(0);
_modified = true;
}

View File

@ -137,6 +137,7 @@ namespace Vfs_block {
_handle.seek(base_offset + current_offset);
state = State::IN_PROGRESS;
progress = true;
[[fallthrough]];
case State::IN_PROGRESS:
{
@ -145,31 +146,24 @@ namespace Vfs_block {
bool completed = false;
file_size out = 0;
Result result = Result::WRITE_ERR_INVALID;
try {
result = _handle.fs().write(&_handle,
data + current_offset,
current_count, out);
} catch (Vfs::File_io_service::Insufficient_buffer) {
Result result = _handle.fs().write(&_handle,
data + current_offset,
current_count, out);
switch (result) {
case Result::WRITE_ERR_WOULD_BLOCK:
return progress;
}
if ( result == Result::WRITE_ERR_AGAIN
|| result == Result::WRITE_ERR_INTERRUPT
|| result == Result::WRITE_ERR_WOULD_BLOCK) {
return progress;
} else
if (result == Result::WRITE_OK) {
case Result::WRITE_OK:
current_offset += out;
current_count -= out;
success = true;
} else
break;
if ( result == Result::WRITE_ERR_IO
|| result == Result::WRITE_ERR_INVALID) {
case Result::WRITE_ERR_IO:
case Result::WRITE_ERR_INVALID:
success = false;
completed = true;
break;
}
if (current_count == 0 || completed) {

View File

@ -95,16 +95,12 @@ inline void assert_write(Vfs::File_io_service::Write_result r)
typedef Vfs::File_io_service::Write_result Result;
switch (r) {
case Result::WRITE_OK: return;
case Result::WRITE_ERR_AGAIN:
error("WRITE_ERR_AGAIN"); break;
case Result::WRITE_ERR_WOULD_BLOCK:
error("WRITE_ERR_WOULD_BLOCK"); break;
case Result::WRITE_ERR_INVALID:
error("WRITE_ERR_INVALID"); break;
case Result::WRITE_ERR_IO:
error("WRITE_ERR_IO"); break;
case Result::WRITE_ERR_INTERRUPT:
error("WRITE_ERR_INTERRUPT"); break;
}
throw Exception();
}