From 7605101665aa65504c6204be2e4271cdecd94151 Mon Sep 17 00:00:00 2001 From: Norman Feske Date: Tue, 25 Jan 2022 17:52:40 +0100 Subject: [PATCH] fatfs: use Block::Connection::Job API This patch removes the use of blocking packet-stream calls from the backend of the fatfs library. Issue #4390 --- repos/libports/src/lib/fatfs/diskio_block.cc | 145 ++++++++++++------- 1 file changed, 95 insertions(+), 50 deletions(-) diff --git a/repos/libports/src/lib/fatfs/diskio_block.cc b/repos/libports/src/lib/fatfs/diskio_block.cc index 44819b34a7..dd9d02b21f 100644 --- a/repos/libports/src/lib/fatfs/diskio_block.cc +++ b/repos/libports/src/lib/fatfs/diskio_block.cc @@ -17,6 +17,7 @@ #include #include #include +#include /* Genode block backend */ #include @@ -34,16 +35,16 @@ extern "C" { struct Drive; struct Platform { - Genode::Env &env; - Genode::Allocator &alloc; - Genode::Allocator_avl tx_alloc { &alloc }; + Env &env; + Allocator &alloc; + Allocator_avl tx_alloc { &alloc }; enum { MAX_DEV_NUM = 8 }; /* XXX: could make a tree... */ Drive* drives[MAX_DEV_NUM]; - Platform(Genode::Env &env, Genode::Allocator &alloc) + Platform(Env &env, Allocator &alloc) : env(env), alloc(alloc) { for (int i = 0; i < MAX_DEV_NUM; ++i) @@ -53,33 +54,101 @@ extern "C" { static Platform *_platform; - void block_init(Genode::Env &env, Genode::Allocator &alloc) + void block_init(Env &env, Allocator &alloc) { static Platform platform { env, alloc }; _platform = &platform; } + struct Drive : private Block::Connection<> { + Entrypoint &_ep; + Info const info = Block::Connection<>::info(); + Io_signal_handler _signal_handler { _ep, *this, &Drive::_update_jobs }; + + struct Read_job : Job + { + char * const dst_ptr; + + Read_job(Drive &drive, char *dst_ptr, + Block::block_number_t sector, Block::block_count_t count) + : + Job(drive, Block::Operation { .type = Block::Operation::Type::READ, + .block_number = sector, + .count = count }), + dst_ptr(dst_ptr) + { } + }; + + struct Write_job : Job + { + char const * const src_ptr; + + Write_job(Drive &drive, char const *src_ptr, + Block::block_number_t sector, Block::block_count_t count) + : + Job(drive, Block::Operation { .type = Block::Operation::Type::WRITE, + .block_number = sector, + .count = count }), + src_ptr(src_ptr) + { } + }; + + void _update_jobs() + { + struct Update_jobs_policy + { + void produce_write_content(Job &job, Block::seek_off_t offset, + char *dst, size_t length) + { + Write_job &write_job = static_cast(job); + memcpy(dst, write_job.src_ptr, length); + } + + void consume_read_result(Job &job, Block::seek_off_t offset, + char const *src, size_t length) + { + Read_job &read_job = static_cast(job); + memcpy(read_job.dst_ptr, src, length); + } + + void completed(Job &, bool success) { } + + } policy; + + update_jobs(policy); + } + using Block::Connection<>::tx; using Block::Connection<>::alloc_packet; + void block_for_io() + { + _update_jobs(); + + _ep.wait_and_dispatch_one_io_signal(); + } + void sync() { - /* - * We don't need to distinguish tags because there can only be one - * outstanding request. - */ - Block::Session::Tag const tag { 0 }; - tx()->submit_packet(sync_all_packet_descriptor(info, tag)); - tx()->get_acked_packet(); + Block::Operation const operation { .type = Block::Operation::Type::SYNC }; + + Job sync_job { *this, operation }; + + while (!sync_job.completed()) + block_for_io(); } Drive(Platform &platform, char const *label) - : Block::Connection<>(platform.env, &platform.tx_alloc, 128*1024, label) - { } + : + Block::Connection<>(platform.env, &platform.tx_alloc, 128*1024, label), + _ep(platform.env.ep()) + { + sigh(_signal_handler); + } }; } @@ -90,7 +159,7 @@ using namespace Fatfs; extern "C" Fatfs::DSTATUS disk_initialize (BYTE drv) { if (drv >= Platform::MAX_DEV_NUM) { - Genode::error("only ", (int)Platform::MAX_DEV_NUM," supported"); + error("only ", (int)Platform::MAX_DEV_NUM," supported"); return STA_NODISK; } @@ -103,7 +172,7 @@ extern "C" Fatfs::DSTATUS disk_initialize (BYTE drv) String<2> label(drv); _platform->drives[drv] = new (_platform->alloc) Drive(*_platform, label.string()); } catch(Service_denied) { - Genode::error("could not open block connection for drive ", drv); + error("could not open block connection for drive ", drv); return STA_NODISK; } @@ -136,25 +205,14 @@ extern "C" DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count) Drive &drive = *_platform->drives[pdrv]; - Genode::size_t const op_len = drive.info.block_size*count; + size_t const op_len = drive.info.block_size*count; - /* allocate packet-descriptor for reading */ - Block::Packet_descriptor p(drive.alloc_packet(op_len), - Block::Packet_descriptor::READ, sector, count); - drive.tx()->submit_packet(p); - p = drive.tx()->get_acked_packet(); + Drive::Read_job read_job { drive, (char *)buff, sector, count }; - DRESULT res; - if (p.succeeded() && p.size() >= op_len) { - Genode::memcpy(buff, drive.tx()->packet_content(p), op_len); - res = RES_OK; - } else { - Genode::error(__func__, " failed at sector ", sector, ", count ", count); - res = RES_ERROR; - } + while (!read_job.completed()) + drive.block_for_io(); - drive.tx()->release_packet(p); - return res; + return RES_OK; } @@ -166,27 +224,14 @@ extern "C" DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT c Drive &drive = *_platform->drives[pdrv]; - Genode::size_t const op_len = drive.info.block_size*count; + size_t const op_len = drive.info.block_size*count; - /* allocate packet-descriptor for writing */ - Block::Packet_descriptor p(drive.alloc_packet(op_len), - Block::Packet_descriptor::WRITE, sector, count); + Drive::Write_job write_job { drive, (char const *)buff, sector, count }; - Genode::memcpy(drive.tx()->packet_content(p), buff, op_len); + while (!write_job.completed()) + drive.block_for_io(); - drive.tx()->submit_packet(p); - p = drive.tx()->get_acked_packet(); - - DRESULT res; - if (p.succeeded()) { - res = RES_OK; - } else { - Genode::error(__func__, " failed at sector ", sector, ", count ", count); - res = RES_ERROR; - } - - drive.tx()->release_packet(p); - return res; + return RES_OK; } #endif /* _READONLY */