From 41bf78cf98ffca358ebdda946a292c8992b54444 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Wed, 22 Nov 2023 12:17:56 -0800 Subject: [PATCH] [Denali] Update the read many request to take a sector count as well. This greatly reduces the size of the message (we had surpassed the 1 page - 4KiB message limit with the previous method). --- sys/denali/denali_server.cpp | 32 ++++++++------- sys/denali/lib/denali/denali.yunq | 3 ++ sys/denali/lib/denali/denali.yunq.cpp | 40 ++++++++++++++++++- sys/denali/lib/denali/denali.yunq.h | 3 ++ .../fs/ext2/ext2_block_reader.cpp | 15 ++++--- 5 files changed, 71 insertions(+), 22 deletions(-) diff --git a/sys/denali/denali_server.cpp b/sys/denali/denali_server.cpp index 82aa695..7745219 100644 --- a/sys/denali/denali_server.cpp +++ b/sys/denali/denali_server.cpp @@ -35,28 +35,30 @@ glcr::ErrorCode DenaliServer::HandleReadMany(const ReadManyRequest& req, ReadResponse& resp) { ASSIGN_OR_RETURN(AhciDevice * device, driver_.GetDevice(req.device_id())); - uint64_t region_paddr; - OwnedMemoryRegion region = OwnedMemoryRegion::ContiguousPhysical( - req.lba().size() * 512, ®ion_paddr); + if (req.lba().size() != req.sector_cnt().size()) { + return glcr::INVALID_ARGUMENT; + } - auto& vec = req.lba(); - uint64_t curr_run_start = 0; - for (uint64_t i = 0; i < vec.size(); i++) { - if (i + 1 < vec.size() && vec.at(i) + 1 == vec.at(i + 1)) { - continue; - } - uint64_t lba = vec.at(curr_run_start); - uint64_t size = (i - curr_run_start) + 1; - uint64_t paddr = region_paddr + curr_run_start * 512; - DmaReadCommand command(lba, size, paddr); + uint64_t sector_cnt = 0; + for (uint64_t i = 0; i < req.sector_cnt().size(); i++) { + sector_cnt += req.sector_cnt().at(i); + } + uint64_t region_paddr; + OwnedMemoryRegion region = + OwnedMemoryRegion::ContiguousPhysical(sector_cnt * 512, ®ion_paddr); + + for (uint64_t i = 0; i < req.lba().size(); i++) { + uint64_t lba = req.lba().at(i); + uint64_t size = req.sector_cnt().at(i); + DmaReadCommand command(lba, size, region_paddr); device->IssueCommand(&command); command.WaitComplete(); - curr_run_start = i + 1; + region_paddr += size * 512; } resp.set_device_id(req.device_id()); - resp.set_size(req.lba().size()); + resp.set_size(sector_cnt); resp.set_memory(region.DuplicateCap()); return glcr::OK; } diff --git a/sys/denali/lib/denali/denali.yunq b/sys/denali/lib/denali/denali.yunq index 27cfc91..340861b 100644 --- a/sys/denali/lib/denali/denali.yunq +++ b/sys/denali/lib/denali/denali.yunq @@ -11,7 +11,10 @@ message ReadRequest { message ReadManyRequest { u64 device_id; + // FIXME: Add repeated message fields. + // Must be the same length. repeated u64 lba; + repeated u64 sector_cnt; } message ReadResponse { diff --git a/sys/denali/lib/denali/denali.yunq.cpp b/sys/denali/lib/denali/denali.yunq.cpp index 0199dc2..50a12d9 100644 --- a/sys/denali/lib/denali/denali.yunq.cpp +++ b/sys/denali/lib/denali/denali.yunq.cpp @@ -100,11 +100,21 @@ void ReadManyRequest::ParseFromBytesInternal(const glcr::ByteBuffer& bytes, uint lba_.PushBack(bytes.At(i)); } + // Parse sector_cnt. + auto sector_cnt_pointer = bytes.At(offset + header_size + (8 * 2)); + + sector_cnt_.Resize(sector_cnt_pointer.length / sizeof(uint64_t)); + for (uint64_t i = offset + sector_cnt_pointer.offset; + i < offset + sector_cnt_pointer.offset + sector_cnt_pointer.length; + i += sizeof(uint64_t)) { + sector_cnt_.PushBack(bytes.At(i)); + } + } uint64_t ReadManyRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const { - uint32_t next_extension = header_size + 8 * 2; + uint32_t next_extension = header_size + 8 * 3; const uint32_t core_size = next_extension; // Write device_id. bytes.WriteAt(offset + header_size + (8 * 0), device_id()); @@ -121,6 +131,19 @@ uint64_t ReadManyRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t off uint32_t ext_offset = offset + lba_ptr.offset + (i * sizeof(uint64_t)); bytes.WriteAt(ext_offset, lba().at(i)); } + // Write sector_cnt. + ExtPointer sector_cnt_ptr{ + .offset = next_extension, + .length = (uint32_t)(sector_cnt().size() * sizeof(uint64_t)), + }; + + next_extension += sector_cnt_ptr.length; + bytes.WriteAt(offset + header_size + (8 * 2), sector_cnt_ptr); + + for (uint64_t i = 0; i < sector_cnt().size(); i++) { + uint32_t ext_offset = offset + sector_cnt_ptr.offset + (i * sizeof(uint64_t)); + bytes.WriteAt(ext_offset, sector_cnt().at(i)); + } // The next extension pointer is the length of the message. WriteHeader(bytes, offset, core_size, next_extension); @@ -129,7 +152,7 @@ uint64_t ReadManyRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t off } uint64_t ReadManyRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const { - uint32_t next_extension = header_size + 8 * 2; + uint32_t next_extension = header_size + 8 * 3; const uint32_t core_size = next_extension; uint64_t next_cap = 0; // Write device_id. @@ -147,6 +170,19 @@ uint64_t ReadManyRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t off uint32_t ext_offset = offset + lba_ptr.offset + (i * sizeof(uint64_t)); bytes.WriteAt(ext_offset, lba().at(i)); } + // Write sector_cnt. + ExtPointer sector_cnt_ptr{ + .offset = next_extension, + .length = (uint32_t)(sector_cnt().size() * sizeof(uint64_t)), + }; + + next_extension += sector_cnt_ptr.length; + bytes.WriteAt(offset + header_size + (8 * 2), sector_cnt_ptr); + + for (uint64_t i = 0; i < sector_cnt().size(); i++) { + uint32_t ext_offset = offset + sector_cnt_ptr.offset + (i * sizeof(uint64_t)); + bytes.WriteAt(ext_offset, sector_cnt().at(i)); + } // The next extension pointer is the length of the message. WriteHeader(bytes, offset, core_size, next_extension); diff --git a/sys/denali/lib/denali/denali.yunq.h b/sys/denali/lib/denali/denali.yunq.h index 79d7322..1727f4d 100644 --- a/sys/denali/lib/denali/denali.yunq.h +++ b/sys/denali/lib/denali/denali.yunq.h @@ -47,10 +47,13 @@ class ReadManyRequest { void set_device_id(const uint64_t& value) { device_id_ = value; } const glcr::Vector& lba() const { return lba_; } void add_lba(const uint64_t& value) { lba_.PushBack(value); } + const glcr::Vector& sector_cnt() const { return sector_cnt_; } + void add_sector_cnt(const uint64_t& value) { sector_cnt_.PushBack(value); } private: uint64_t device_id_; glcr::Vector lba_; + glcr::Vector sector_cnt_; // Parses everything except for caps. void ParseFromBytesInternal(const glcr::ByteBuffer&, uint64_t offset); diff --git a/sys/victoriafalls/fs/ext2/ext2_block_reader.cpp b/sys/victoriafalls/fs/ext2/ext2_block_reader.cpp index bb85086..89f1d60 100644 --- a/sys/victoriafalls/fs/ext2/ext2_block_reader.cpp +++ b/sys/victoriafalls/fs/ext2/ext2_block_reader.cpp @@ -78,14 +78,19 @@ glcr::ErrorOr Ext2BlockReader::ReadBlocks( const glcr::Vector& block_list) { ReadManyRequest req; req.set_device_id(device_id_); - // FIXME: We should have better ergonomics for setting a repeated field in - // Yunq. for (uint64_t i = 0; i < block_list.size(); i++) { - uint64_t sector = lba_offset_ + block_list.at(i) * SectorsPerBlock(); - for (uint64_t j = 0; j < SectorsPerBlock(); j++) { - req.add_lba(sector + j); + uint64_t curr_start = lba_offset_ + block_list.at(i) * SectorsPerBlock(); + uint64_t curr_run_len = 1; + while ((i + 1) < block_list.size() && + block_list.at(i + 1) == block_list.at(i) + 1) { + i++; + curr_run_len++; } + req.add_lba(curr_start); + req.add_sector_cnt(curr_run_len * SectorsPerBlock()); + dbgln("Read {x}, {x}", curr_start, curr_run_len * SectorsPerBlock()); } + dbgln("Read many: {x}", req.lba().size()); ReadResponse resp; RET_ERR(denali_.ReadMany(req, resp)); return OwnedMemoryRegion::FromCapability(resp.memory());