mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
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:
parent
d9f5dda322
commit
cf87b0fadb
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user