[VFS] Move victoria falls to rust. (Breaks voyageurs)
Move victoria falls to rust, which allows us to remove both the denali and victoria falls C++ code. This disk driver appears to work properly but has highlighted some instability in the voyageus xhci implementation which now breaks.
This commit is contained in:
parent
f918966727
commit
dc801786b1
37 changed files with 504 additions and 2065 deletions
|
|
@ -1 +0,0 @@
|
|||
yunq_gen(lib/denali lib denali)
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
interface Denali {
|
||||
method Read(ReadRequest) -> (ReadResponse);
|
||||
method ReadMany(ReadManyRequest) -> (ReadResponse);
|
||||
}
|
||||
|
||||
message DiskBlock {
|
||||
u64 lba;
|
||||
u64 size;
|
||||
}
|
||||
|
||||
message ReadRequest {
|
||||
u64 device_id;
|
||||
DiskBlock block;
|
||||
}
|
||||
|
||||
|
||||
message ReadManyRequest {
|
||||
u64 device_id;
|
||||
repeated DiskBlock blocks;
|
||||
}
|
||||
|
||||
message ReadResponse {
|
||||
u64 device_id;
|
||||
u64 size;
|
||||
capability memory;
|
||||
}
|
||||
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
// Generated file - DO NOT MODIFY
|
||||
#include "denali.yunq.client.h"
|
||||
|
||||
#include <glacier/buffer/byte_buffer.h>
|
||||
#include <glacier/buffer/cap_buffer.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <zcall.h>
|
||||
|
||||
|
||||
|
||||
|
||||
DenaliClient::~DenaliClient() {
|
||||
if (endpoint_ != 0) {
|
||||
check(ZCapRelease(endpoint_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
glcr::Status DenaliClient::Read(const ReadRequest& request, ReadResponse& response) {
|
||||
|
||||
uint64_t buffer_size = kBufferSize;
|
||||
uint64_t cap_size = kCapBufferSize;
|
||||
|
||||
const uint32_t kSentinel = 0xBEEFDEAD;
|
||||
buffer_.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer_.WriteAt<uint64_t>(8, 0);
|
||||
|
||||
cap_buffer_.Reset();
|
||||
|
||||
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
|
||||
|
||||
|
||||
buffer_.WriteAt<uint32_t>(4, 16 + length);
|
||||
|
||||
z_cap_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), cap_buffer_.UsedSlots(), cap_buffer_.RawPtr(), &reply_port_cap));
|
||||
|
||||
// FIXME: Add a way to zero out the first buffer.
|
||||
RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr()));
|
||||
|
||||
if (buffer_.At<uint32_t>(0) != kSentinel) {
|
||||
return glcr::InvalidResponse("Got an invalid response from server.");
|
||||
}
|
||||
|
||||
// Check Response Code.
|
||||
RET_ERR(buffer_.At<uint64_t>(8));
|
||||
|
||||
|
||||
yunq::MessageView resp_view(buffer_, 16);
|
||||
RETURN_ERROR(response.ParseFromBytes(resp_view, cap_buffer_));
|
||||
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
glcr::Status DenaliClient::ReadMany(const ReadManyRequest& request, ReadResponse& response) {
|
||||
|
||||
uint64_t buffer_size = kBufferSize;
|
||||
uint64_t cap_size = kCapBufferSize;
|
||||
|
||||
const uint32_t kSentinel = 0xBEEFDEAD;
|
||||
buffer_.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer_.WriteAt<uint64_t>(8, 1);
|
||||
|
||||
cap_buffer_.Reset();
|
||||
|
||||
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
|
||||
|
||||
|
||||
buffer_.WriteAt<uint32_t>(4, 16 + length);
|
||||
|
||||
z_cap_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), cap_buffer_.UsedSlots(), cap_buffer_.RawPtr(), &reply_port_cap));
|
||||
|
||||
// FIXME: Add a way to zero out the first buffer.
|
||||
RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr()));
|
||||
|
||||
if (buffer_.At<uint32_t>(0) != kSentinel) {
|
||||
return glcr::InvalidResponse("Got an invalid response from server.");
|
||||
}
|
||||
|
||||
// Check Response Code.
|
||||
RET_ERR(buffer_.At<uint64_t>(8));
|
||||
|
||||
|
||||
yunq::MessageView resp_view(buffer_, 16);
|
||||
RETURN_ERROR(response.ParseFromBytes(resp_view, cap_buffer_));
|
||||
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Generated file - DO NOT MODIFY
|
||||
#pragma once
|
||||
|
||||
#include <glacier/buffer/byte_buffer.h>
|
||||
#include <glacier/buffer/cap_buffer.h>
|
||||
#include <glacier/status/error.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
#include "denali.yunq.h"
|
||||
|
||||
|
||||
class DenaliClient {
|
||||
public:
|
||||
DenaliClient(z_cap_t Denali_cap) : endpoint_(Denali_cap) {}
|
||||
DenaliClient(const DenaliClient&) = delete;
|
||||
DenaliClient(DenaliClient&& other) : endpoint_(other.endpoint_) {other.endpoint_ = 0;};
|
||||
~DenaliClient();
|
||||
|
||||
z_cap_t Capability() { return endpoint_; }
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] glcr::Status Read(const ReadRequest& request, ReadResponse& response);
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] glcr::Status ReadMany(const ReadManyRequest& request, ReadResponse& response);
|
||||
|
||||
|
||||
private:
|
||||
z_cap_t endpoint_;
|
||||
uint64_t kBufferSize = 0x1000;
|
||||
glcr::ByteBuffer buffer_{kBufferSize};
|
||||
uint64_t kCapBufferSize = 0x10;
|
||||
glcr::CapBuffer cap_buffer_{kCapBufferSize};
|
||||
};
|
||||
|
||||
|
|
@ -1,186 +0,0 @@
|
|||
// Generated file -- DO NOT MODIFY.
|
||||
#include "denali.yunq.h"
|
||||
|
||||
#include <yunq/message_view.h>
|
||||
#include <yunq/serialize.h>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
const uint64_t header_size = 24; // 4x uint32, 1x uint64
|
||||
|
||||
struct ExtPointer {
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
glcr::Status DiskBlock::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status DiskBlock::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status DiskBlock::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse lba.
|
||||
ASSIGN_OR_RETURN(lba_, message.ReadField<uint64_t>(0));
|
||||
// Parse size.
|
||||
ASSIGN_OR_RETURN(size_, message.ReadField<uint64_t>(1));
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t DiskBlock::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 2);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t DiskBlock::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 2, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t DiskBlock::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write lba.
|
||||
serializer.WriteField<uint64_t>(0, lba_);
|
||||
// Write size.
|
||||
serializer.WriteField<uint64_t>(1, size_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
glcr::Status ReadRequest::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status ReadRequest::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status ReadRequest::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse device_id.
|
||||
ASSIGN_OR_RETURN(device_id_, message.ReadField<uint64_t>(0));
|
||||
// Parse block.
|
||||
message.ReadMessage<DiskBlock>(1, block_);
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t ReadRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 2);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t ReadRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 2, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t ReadRequest::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write device_id.
|
||||
serializer.WriteField<uint64_t>(0, device_id_);
|
||||
// Write block.
|
||||
serializer.WriteMessage<DiskBlock>(1, block_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
glcr::Status ReadManyRequest::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status ReadManyRequest::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status ReadManyRequest::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse device_id.
|
||||
ASSIGN_OR_RETURN(device_id_, message.ReadField<uint64_t>(0));
|
||||
// Parse blocks.
|
||||
message.ReadRepeatedMessage<DiskBlock>(1, blocks_);
|
||||
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t ReadManyRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 2);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t ReadManyRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 2, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t ReadManyRequest::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write device_id.
|
||||
serializer.WriteField<uint64_t>(0, device_id_);
|
||||
// Write blocks.
|
||||
serializer.WriteRepeatedMessage<DiskBlock>(1, blocks_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
glcr::Status ReadResponse::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
// Parse memory.
|
||||
ASSIGN_OR_RETURN(memory_, message.ReadCapability(2));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status ReadResponse::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
// Parse memory.
|
||||
ASSIGN_OR_RETURN(memory_, message.ReadCapability(2, caps));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status ReadResponse::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse device_id.
|
||||
ASSIGN_OR_RETURN(device_id_, message.ReadField<uint64_t>(0));
|
||||
// Parse size.
|
||||
ASSIGN_OR_RETURN(size_, message.ReadField<uint64_t>(1));
|
||||
// Parse memory.
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t ReadResponse::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 3);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t ReadResponse::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 3, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t ReadResponse::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write device_id.
|
||||
serializer.WriteField<uint64_t>(0, device_id_);
|
||||
// Write size.
|
||||
serializer.WriteField<uint64_t>(1, size_);
|
||||
// Write memory.
|
||||
serializer.WriteCapability(2, memory_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
|
||||
|
|
@ -1,138 +0,0 @@
|
|||
// Generated file - DO NOT MODIFY
|
||||
#pragma once
|
||||
|
||||
#include <glacier/buffer/byte_buffer.h>
|
||||
#include <glacier/buffer/cap_buffer.h>
|
||||
#include <glacier/status/status.h>
|
||||
#include <glacier/container/vector.h>
|
||||
#include <glacier/string/string.h>
|
||||
#include <yunq/message_view.h>
|
||||
#include <yunq/serialize.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
|
||||
class DiskBlock {
|
||||
public:
|
||||
DiskBlock() {}
|
||||
// Delete copy and move until implemented.
|
||||
DiskBlock(const DiskBlock&) = delete;
|
||||
DiskBlock(DiskBlock&&) = default;
|
||||
DiskBlock& operator=(DiskBlock&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const uint64_t& lba() const { return lba_; }
|
||||
uint64_t& mutable_lba() { return lba_; }
|
||||
void set_lba(const uint64_t& value) { lba_ = value; }
|
||||
|
||||
const uint64_t& size() const { return size_; }
|
||||
uint64_t& mutable_size() { return size_; }
|
||||
void set_size(const uint64_t& value) { size_ = value; }
|
||||
|
||||
private:
|
||||
uint64_t lba_;
|
||||
uint64_t size_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
class ReadRequest {
|
||||
public:
|
||||
ReadRequest() {}
|
||||
// Delete copy and move until implemented.
|
||||
ReadRequest(const ReadRequest&) = delete;
|
||||
ReadRequest(ReadRequest&&) = default;
|
||||
ReadRequest& operator=(ReadRequest&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const uint64_t& device_id() const { return device_id_; }
|
||||
uint64_t& mutable_device_id() { return device_id_; }
|
||||
void set_device_id(const uint64_t& value) { device_id_ = value; }
|
||||
|
||||
const DiskBlock& block() const { return block_; }
|
||||
DiskBlock& mutable_block() { return block_; }
|
||||
|
||||
private:
|
||||
uint64_t device_id_;
|
||||
DiskBlock block_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
class ReadManyRequest {
|
||||
public:
|
||||
ReadManyRequest() {}
|
||||
// Delete copy and move until implemented.
|
||||
ReadManyRequest(const ReadManyRequest&) = delete;
|
||||
ReadManyRequest(ReadManyRequest&&) = default;
|
||||
ReadManyRequest& operator=(ReadManyRequest&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const uint64_t& device_id() const { return device_id_; }
|
||||
uint64_t& mutable_device_id() { return device_id_; }
|
||||
void set_device_id(const uint64_t& value) { device_id_ = value; }
|
||||
|
||||
const glcr::Vector<DiskBlock>& blocks() const { return blocks_; }
|
||||
glcr::Vector<DiskBlock>& mutable_blocks() { return blocks_; }
|
||||
void add_blocks(DiskBlock&& value) { blocks_.PushBack(glcr::Move(value)); }
|
||||
|
||||
private:
|
||||
uint64_t device_id_;
|
||||
glcr::Vector<DiskBlock> blocks_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
class ReadResponse {
|
||||
public:
|
||||
ReadResponse() {}
|
||||
// Delete copy and move until implemented.
|
||||
ReadResponse(const ReadResponse&) = delete;
|
||||
ReadResponse(ReadResponse&&) = default;
|
||||
ReadResponse& operator=(ReadResponse&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const uint64_t& device_id() const { return device_id_; }
|
||||
uint64_t& mutable_device_id() { return device_id_; }
|
||||
void set_device_id(const uint64_t& value) { device_id_ = value; }
|
||||
|
||||
const uint64_t& size() const { return size_; }
|
||||
uint64_t& mutable_size() { return size_; }
|
||||
void set_size(const uint64_t& value) { size_ = value; }
|
||||
|
||||
const z_cap_t& memory() const { return memory_; }
|
||||
z_cap_t& mutable_memory() { return memory_; }
|
||||
void set_memory(const z_cap_t& value) { memory_ = value; }
|
||||
|
||||
private:
|
||||
uint64_t device_id_;
|
||||
uint64_t size_;
|
||||
z_cap_t memory_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
// Generated file -- DO NOT MODIFY.
|
||||
#include "denali.yunq.server.h"
|
||||
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <zcall.h>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kSentinel = 0xBEEFDEAD;
|
||||
const uint32_t kHeaderSize = 0x10;
|
||||
|
||||
void WriteError(glcr::ByteBuffer& buffer, glcr::ErrorCode err) {
|
||||
buffer.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer.WriteAt<uint32_t>(4, kHeaderSize);
|
||||
buffer.WriteAt<uint64_t>(8, err);
|
||||
}
|
||||
|
||||
void WriteHeader(glcr::ByteBuffer& buffer, uint64_t message_length) {
|
||||
buffer.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer.WriteAt<uint32_t>(4, kHeaderSize + message_length);
|
||||
buffer.WriteAt<uint64_t>(8, glcr::OK);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void DenaliServerBaseThreadBootstrap(void* server_base) {
|
||||
((DenaliServerBase*)server_base)->ServerThread();
|
||||
}
|
||||
|
||||
DenaliServerBase::~DenaliServerBase() {
|
||||
if (endpoint_ != 0) {
|
||||
check(ZCapRelease(endpoint_));
|
||||
}
|
||||
}
|
||||
|
||||
glcr::ErrorOr<z_cap_t> DenaliServerBase::CreateClientCap() {
|
||||
uint64_t client_cap;
|
||||
RET_ERR(ZCapDuplicate(endpoint_, ~(kZionPerm_Read), &client_cap));
|
||||
return client_cap;
|
||||
}
|
||||
|
||||
glcr::ErrorOr<DenaliClient> DenaliServerBase::CreateClient() {
|
||||
uint64_t client_cap;
|
||||
RET_ERR(ZCapDuplicate(endpoint_, ~(kZionPerm_Read), &client_cap));
|
||||
return DenaliClient(client_cap);
|
||||
}
|
||||
|
||||
Thread DenaliServerBase::RunServer() {
|
||||
return Thread(DenaliServerBaseThreadBootstrap, this);
|
||||
}
|
||||
|
||||
void DenaliServerBase::ServerThread() {
|
||||
glcr::ByteBuffer recv_buffer(0x1000);
|
||||
glcr::CapBuffer recv_cap(0x10);
|
||||
glcr::ByteBuffer resp_buffer(0x1000);
|
||||
glcr::CapBuffer resp_cap(0x10);
|
||||
z_cap_t reply_port_cap;
|
||||
|
||||
while (true) {
|
||||
uint64_t recv_cap_size = 0x10;
|
||||
uint64_t recv_buf_size = 0x1000;
|
||||
recv_cap.Reset();
|
||||
glcr::ErrorCode recv_err = static_cast<glcr::ErrorCode>(ZEndpointRecv(endpoint_, &recv_buf_size, recv_buffer.RawPtr(), &recv_cap_size, recv_cap.RawPtr(), &reply_port_cap));
|
||||
if (recv_err != glcr::OK) {
|
||||
dbgln("Error in receive: {x}", recv_err);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t resp_length = 0;
|
||||
|
||||
glcr::ErrorCode reply_err = glcr::OK;
|
||||
resp_cap.Reset();
|
||||
glcr::Status err = HandleRequest(recv_buffer, recv_cap, resp_buffer, resp_length, resp_cap);
|
||||
if (!err) {
|
||||
WriteError(resp_buffer, err.code());
|
||||
dbgln("Responding Error {}", err.message());
|
||||
reply_err = static_cast<glcr::ErrorCode>(ZReplyPortSend(reply_port_cap, kHeaderSize, resp_buffer.RawPtr(), 0, nullptr));
|
||||
} else {
|
||||
WriteHeader(resp_buffer, resp_length);
|
||||
reply_err = static_cast<glcr::ErrorCode>(ZReplyPortSend(reply_port_cap, kHeaderSize + resp_length, resp_buffer.RawPtr(), resp_cap.UsedSlots(), resp_cap.RawPtr()));
|
||||
}
|
||||
if (reply_err != glcr::OK) {
|
||||
dbgln("Error in reply: {x}", reply_err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
glcr::Status DenaliServerBase::HandleRequest(const glcr::ByteBuffer& request,
|
||||
const glcr::CapBuffer& req_caps,
|
||||
glcr::ByteBuffer& response, uint64_t& resp_length,
|
||||
glcr::CapBuffer& resp_caps) {
|
||||
if (request.At<uint32_t>(0) != kSentinel) {
|
||||
return glcr::InvalidArgument("Request Not Valid");
|
||||
}
|
||||
|
||||
uint64_t method_select = request.At<uint64_t>(8);
|
||||
|
||||
switch(method_select) {
|
||||
case 0: {
|
||||
|
||||
|
||||
ReadRequest yunq_request;
|
||||
yunq::MessageView request_view(request, kHeaderSize);
|
||||
RETURN_ERROR(yunq_request.ParseFromBytes(request_view, req_caps));
|
||||
|
||||
|
||||
|
||||
ReadResponse yunq_response;
|
||||
|
||||
|
||||
|
||||
RETURN_ERROR(HandleRead(yunq_request, yunq_response));
|
||||
|
||||
|
||||
|
||||
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
|
||||
|
||||
ReadManyRequest yunq_request;
|
||||
yunq::MessageView request_view(request, kHeaderSize);
|
||||
RETURN_ERROR(yunq_request.ParseFromBytes(request_view, req_caps));
|
||||
|
||||
|
||||
|
||||
ReadResponse yunq_response;
|
||||
|
||||
|
||||
|
||||
RETURN_ERROR(HandleReadMany(yunq_request, yunq_response));
|
||||
|
||||
|
||||
|
||||
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return glcr::Unimplemented("Method unimplemented by server.");
|
||||
}
|
||||
}
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
// Generated File -- DO NOT MODIFY.
|
||||
#pragma once
|
||||
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <glacier/status/status.h>
|
||||
#include <mammoth/proc/thread.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
#include "denali.yunq.h"
|
||||
#include "denali.yunq.client.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class DenaliServerBase {
|
||||
public:
|
||||
DenaliServerBase(z_cap_t Denali_cap) : endpoint_(Denali_cap) {}
|
||||
DenaliServerBase(const DenaliServerBase&) = delete;
|
||||
DenaliServerBase(DenaliServerBase&&) = delete;
|
||||
virtual ~DenaliServerBase();
|
||||
|
||||
glcr::ErrorOr<z_cap_t> CreateClientCap();
|
||||
glcr::ErrorOr<DenaliClient> CreateClient();
|
||||
|
||||
[[nodiscard]] Thread RunServer();
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] virtual glcr::Status HandleRead(const ReadRequest&, ReadResponse&) = 0;
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] virtual glcr::Status HandleReadMany(const ReadManyRequest&, ReadResponse&) = 0;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
z_cap_t endpoint_;
|
||||
|
||||
friend void DenaliServerBaseThreadBootstrap(void*);
|
||||
void ServerThread();
|
||||
|
||||
[[nodiscard]] glcr::Status HandleRequest(const glcr::ByteBuffer& request, const glcr::CapBuffer& req_caps,
|
||||
glcr::ByteBuffer& response, uint64_t& resp_length,
|
||||
glcr::CapBuffer& resp_caps);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
add_executable(victoriafalls
|
||||
fs/ext2/ext2_block_reader.cpp
|
||||
fs/ext2/ext2_driver.cpp
|
||||
fs/ext2/inode_table.cpp
|
||||
victoriafalls.cpp
|
||||
victoriafalls_server.cpp
|
||||
)
|
||||
|
||||
target_include_directories(victoriafalls
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||
|
||||
target_link_libraries(victoriafalls
|
||||
denali_yunq
|
||||
glacier
|
||||
mammoth
|
||||
victoriafalls_yunq
|
||||
yellowstone_yunq
|
||||
)
|
||||
|
||||
set_target_properties(victoriafalls PROPERTIES
|
||||
COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}"
|
||||
LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}"
|
||||
)
|
||||
|
||||
yunq_gen(lib/victoriafalls lib victoriafalls)
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct Superblock {
|
||||
uint32_t inodes_count;
|
||||
uint32_t blocks_count;
|
||||
uint32_t reserved_blocks_count;
|
||||
uint32_t free_blocks_count;
|
||||
uint32_t free_inodes_count;
|
||||
uint32_t first_data_blok;
|
||||
uint32_t log_block_size;
|
||||
uint32_t log_frag_size;
|
||||
uint32_t blocks_per_group;
|
||||
uint32_t frags_per_group;
|
||||
uint32_t inodes_per_group;
|
||||
uint32_t mtime;
|
||||
uint32_t wtime;
|
||||
uint16_t mnt_count;
|
||||
uint16_t max_mnt_count;
|
||||
uint16_t magic;
|
||||
uint16_t state;
|
||||
uint16_t errors;
|
||||
uint16_t minor_rev_level;
|
||||
uint32_t lastcheck;
|
||||
uint32_t checkinterval;
|
||||
uint32_t creator_os;
|
||||
uint32_t rev_level;
|
||||
uint16_t def_resuid;
|
||||
uint16_t def_resgid;
|
||||
uint32_t first_ino;
|
||||
uint16_t inode_size;
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct BlockGroupDescriptor {
|
||||
uint32_t block_bitmap;
|
||||
uint32_t inode_bitmap;
|
||||
uint32_t inode_table;
|
||||
uint16_t free_blocks_count;
|
||||
uint16_t free_inodes_count;
|
||||
uint16_t used_dirs_count;
|
||||
uint8_t reserved[14];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
struct Inode {
|
||||
uint16_t mode;
|
||||
uint16_t uid;
|
||||
uint32_t size;
|
||||
uint32_t atime;
|
||||
uint32_t ctime;
|
||||
uint32_t mtime;
|
||||
uint32_t dtime;
|
||||
uint16_t gid;
|
||||
uint16_t links_count;
|
||||
uint32_t blocks;
|
||||
uint32_t flags;
|
||||
uint32_t osd1;
|
||||
uint32_t block[15];
|
||||
uint32_t generation;
|
||||
uint32_t file_acl;
|
||||
uint32_t dir_acl;
|
||||
uint32_t faddr;
|
||||
uint32_t osd2[3];
|
||||
} __attribute__((__packed__));
|
||||
|
||||
constexpr uint8_t kExt2FtUnknown = 0;
|
||||
constexpr uint8_t kExt2FtFile = 1;
|
||||
constexpr uint8_t kExt2FtDirectory = 2;
|
||||
|
||||
struct DirEntry {
|
||||
uint32_t inode;
|
||||
uint16_t record_length;
|
||||
uint8_t name_len;
|
||||
uint8_t file_type;
|
||||
char name[256];
|
||||
} __attribute__((__packed__));
|
||||
|
|
@ -1,117 +0,0 @@
|
|||
#include "fs/ext2/ext2_block_reader.h"
|
||||
|
||||
#include <mammoth/util/debug.h>
|
||||
|
||||
glcr::ErrorOr<glcr::SharedPtr<Ext2BlockReader>> Ext2BlockReader::Init(
|
||||
const yellowstone::DenaliInfo& denali_info) {
|
||||
// Read 1024 bytes from 1024 offset.
|
||||
// FIXME: Don't assume 512 byte sectors somehow.
|
||||
DenaliClient client(denali_info.denali_endpoint());
|
||||
ReadRequest req;
|
||||
req.set_device_id(denali_info.device_id());
|
||||
req.mutable_block().set_lba(denali_info.lba_offset() + 2);
|
||||
req.mutable_block().set_size(2);
|
||||
ReadResponse resp;
|
||||
auto status = client.Read(req, resp);
|
||||
if (!status.ok()) {
|
||||
dbgln("Failed to read superblock: {}", status.message());
|
||||
return status.code();
|
||||
}
|
||||
mmth::OwnedMemoryRegion superblock =
|
||||
mmth::OwnedMemoryRegion::FromCapability(resp.memory());
|
||||
|
||||
return glcr::SharedPtr<Ext2BlockReader>(
|
||||
new Ext2BlockReader(glcr::Move(client), denali_info.device_id(),
|
||||
denali_info.lba_offset(), glcr::Move(superblock)));
|
||||
}
|
||||
|
||||
Superblock* Ext2BlockReader::GetSuperblock() {
|
||||
return reinterpret_cast<Superblock*>(super_block_region_.vaddr());
|
||||
}
|
||||
|
||||
uint64_t Ext2BlockReader::SectorsPerBlock() {
|
||||
return 1 << (GetSuperblock()->log_block_size + 1);
|
||||
}
|
||||
|
||||
uint64_t Ext2BlockReader::BlockSize() {
|
||||
return 1024 << (GetSuperblock()->log_block_size);
|
||||
}
|
||||
|
||||
uint64_t Ext2BlockReader::NumberOfBlockGroups() {
|
||||
return ((GetSuperblock()->blocks_count - 1) /
|
||||
GetSuperblock()->blocks_per_group) +
|
||||
1;
|
||||
}
|
||||
|
||||
uint64_t Ext2BlockReader::BgdtBlockNum() {
|
||||
return (BlockSize() == 1024) ? 2 : 1;
|
||||
}
|
||||
|
||||
uint64_t Ext2BlockReader::BgdtBlockSize() {
|
||||
return ((NumberOfBlockGroups() * sizeof(BlockGroupDescriptor) - 1) /
|
||||
BlockSize()) +
|
||||
1;
|
||||
}
|
||||
|
||||
uint64_t Ext2BlockReader::InodeSize() {
|
||||
constexpr uint64_t kDefaultInodeSize = 0x80;
|
||||
return GetSuperblock()->rev_level >= 1 ? GetSuperblock()->inode_size
|
||||
: kDefaultInodeSize;
|
||||
}
|
||||
|
||||
uint64_t Ext2BlockReader::InodeTableBlockSize() {
|
||||
return (InodeSize() * GetSuperblock()->inodes_per_group) / BlockSize();
|
||||
}
|
||||
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> Ext2BlockReader::ReadBlock(
|
||||
uint64_t block_number) {
|
||||
return ReadBlocks(block_number, 1);
|
||||
}
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> Ext2BlockReader::ReadBlocks(
|
||||
uint64_t block_number, uint64_t num_blocks) {
|
||||
ReadRequest req;
|
||||
req.set_device_id(device_id_);
|
||||
req.mutable_block().set_lba(lba_offset_ + block_number * SectorsPerBlock());
|
||||
req.mutable_block().set_size(num_blocks * SectorsPerBlock());
|
||||
ReadResponse resp;
|
||||
auto status = denali_.Read(req, resp);
|
||||
if (!status.ok()) {
|
||||
dbgln("Failed to read block: {}", status.code());
|
||||
return status.code();
|
||||
}
|
||||
return mmth::OwnedMemoryRegion::FromCapability(resp.memory());
|
||||
}
|
||||
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> Ext2BlockReader::ReadBlocks(
|
||||
const glcr::Vector<uint64_t>& block_list) {
|
||||
ReadManyRequest req;
|
||||
req.set_device_id(device_id_);
|
||||
for (uint64_t i = 0; i < block_list.size(); i++) {
|
||||
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++;
|
||||
}
|
||||
DiskBlock block;
|
||||
block.set_lba(curr_start);
|
||||
block.set_size(curr_run_len * SectorsPerBlock());
|
||||
req.add_blocks(glcr::Move(block));
|
||||
}
|
||||
ReadResponse resp;
|
||||
auto status = denali_.ReadMany(req, resp);
|
||||
if (!status.ok()) {
|
||||
dbgln("Failed to read blocks: {}", status.code());
|
||||
return status.code();
|
||||
}
|
||||
return mmth::OwnedMemoryRegion::FromCapability(resp.memory());
|
||||
}
|
||||
|
||||
Ext2BlockReader::Ext2BlockReader(DenaliClient&& denali, uint64_t device_id,
|
||||
uint64_t lba_offset,
|
||||
mmth::OwnedMemoryRegion&& super_block)
|
||||
: denali_(glcr::Move(denali)),
|
||||
device_id_(device_id),
|
||||
lba_offset_(lba_offset),
|
||||
super_block_region_(glcr::Move(super_block)) {}
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <denali/denali.yunq.client.h>
|
||||
#include <glacier/memory/shared_ptr.h>
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <mammoth/util/memory_region.h>
|
||||
#include <yellowstone/yellowstone.yunq.h>
|
||||
|
||||
#include "fs/ext2/ext2.h"
|
||||
|
||||
/* Simple Wrapper class around the denali client to translate blocks to sectors.
|
||||
*
|
||||
* By necessity contains the Ext Superblock (to make the translation
|
||||
* calculation).
|
||||
* */
|
||||
class Ext2BlockReader {
|
||||
public:
|
||||
static glcr::ErrorOr<glcr::SharedPtr<Ext2BlockReader>> Init(
|
||||
const yellowstone::DenaliInfo& denali_info);
|
||||
|
||||
// TODO: Consider creating a new class wrapper with these computations.
|
||||
Superblock* GetSuperblock();
|
||||
uint64_t BlockSize();
|
||||
uint64_t NumberOfBlockGroups();
|
||||
uint64_t BgdtBlockNum();
|
||||
uint64_t BgdtBlockSize();
|
||||
uint64_t InodeSize();
|
||||
// FIXME: This probably needs to take into account the block group number
|
||||
// because the last table will likely be smaller.
|
||||
uint64_t InodeTableBlockSize();
|
||||
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> ReadBlock(uint64_t block_number);
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> ReadBlocks(uint64_t block_number,
|
||||
uint64_t num_blocks);
|
||||
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> ReadBlocks(
|
||||
const glcr::Vector<uint64_t>& block_list);
|
||||
|
||||
private:
|
||||
DenaliClient denali_;
|
||||
uint64_t device_id_;
|
||||
uint64_t lba_offset_;
|
||||
mmth::OwnedMemoryRegion super_block_region_;
|
||||
|
||||
Ext2BlockReader(DenaliClient&& denali, uint64_t device_id,
|
||||
uint64_t lba_offset, mmth::OwnedMemoryRegion&& super_block);
|
||||
|
||||
uint64_t SectorsPerBlock();
|
||||
};
|
||||
|
|
@ -1,160 +0,0 @@
|
|||
#include "fs/ext2/ext2_driver.h"
|
||||
|
||||
#include <glacier/string/string.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
|
||||
#define EXT2_DEBUG 0
|
||||
|
||||
glcr::ErrorOr<Ext2Driver> Ext2Driver::Init(
|
||||
const yellowstone::DenaliInfo& denali_info) {
|
||||
ASSIGN_OR_RETURN(glcr::SharedPtr<Ext2BlockReader> reader,
|
||||
Ext2BlockReader::Init(glcr::Move(denali_info)));
|
||||
|
||||
ASSIGN_OR_RETURN(
|
||||
mmth::OwnedMemoryRegion bgdt,
|
||||
reader->ReadBlocks(reader->BgdtBlockNum(), reader->BgdtBlockSize()));
|
||||
glcr::UniquePtr<InodeTable> inode_table(
|
||||
new InodeTable(reader, glcr::Move(bgdt)));
|
||||
|
||||
return Ext2Driver(reader, glcr::Move(inode_table));
|
||||
}
|
||||
|
||||
glcr::ErrorCode Ext2Driver::ProbePartition() {
|
||||
Superblock* superblock = ext2_reader_->GetSuperblock();
|
||||
if (superblock->magic != 0xEF53) {
|
||||
dbgln("Invalid EXT2 magic code: {x}");
|
||||
return glcr::INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
#if EXT2_DEBUG
|
||||
dbgln("Block size: 0x{x}", 1024 << superblock->log_block_size);
|
||||
|
||||
dbgln("Blocks: 0x{x} (0x{x} per group)", superblock->blocks_count,
|
||||
superblock->blocks_per_group);
|
||||
dbgln("Inodes: 0x{x} (0x{x} per group)", superblock->inodes_count,
|
||||
superblock->inodes_per_group);
|
||||
dbgln("Inode size: 0x{x}", superblock->inode_size);
|
||||
|
||||
dbgln("Mounts: 0x{x} out of 0x{x}", superblock->mnt_count,
|
||||
superblock->max_mnt_count);
|
||||
dbgln("State: {x}", superblock->state);
|
||||
|
||||
dbgln("Created by: {x}", superblock->creator_os);
|
||||
#endif
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
glcr::ErrorOr<Inode*> Ext2Driver::GetInode(uint32_t inode_number) {
|
||||
return inode_table_->GetInode(inode_number);
|
||||
}
|
||||
|
||||
glcr::ErrorOr<glcr::Vector<DirEntry>> Ext2Driver::ReadDirectory(
|
||||
uint32_t inode_number) {
|
||||
ASSIGN_OR_RETURN(Inode * inode, inode_table_->GetInode(inode_number));
|
||||
if (!(inode->mode & 0x4000)) {
|
||||
dbgln("Reading non directory.");
|
||||
return glcr::INVALID_ARGUMENT;
|
||||
}
|
||||
ASSIGN_OR_RETURN(mmth::OwnedMemoryRegion dir, ReadInode(inode_number, inode));
|
||||
|
||||
glcr::Vector<DirEntry> directory;
|
||||
|
||||
uint64_t addr = dir.vaddr();
|
||||
while (addr < dir.vaddr() + ext2_reader_->BlockSize()) {
|
||||
DirEntry* entry = reinterpret_cast<DirEntry*>(addr);
|
||||
directory.PushBack(*entry);
|
||||
glcr::StringView name(entry->name, entry->name_len);
|
||||
#if EXT2_DEBUG
|
||||
switch (entry->file_type) {
|
||||
case kExt2FtFile:
|
||||
dbgln("FILE (0x{x}): {}", entry->inode, name);
|
||||
break;
|
||||
case kExt2FtDirectory:
|
||||
dbgln("DIR (0x{x}): {}", entry->inode, name);
|
||||
break;
|
||||
default:
|
||||
dbgln("UNK (0x{x}): {}", entry->inode, name);
|
||||
}
|
||||
#endif
|
||||
addr += entry->record_length;
|
||||
}
|
||||
return directory;
|
||||
}
|
||||
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> Ext2Driver::ReadFile(
|
||||
uint64_t inode_number) {
|
||||
ASSIGN_OR_RETURN(Inode * inode, inode_table_->GetInode(inode_number));
|
||||
|
||||
if (!(inode->mode & 0x8000)) {
|
||||
dbgln("Reading non file.");
|
||||
return glcr::INVALID_ARGUMENT;
|
||||
}
|
||||
return ReadInode(inode_number, inode);
|
||||
}
|
||||
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> Ext2Driver::ReadInode(uint64_t inode_num,
|
||||
Inode* inode) {
|
||||
if (inode_cache_.Contains(inode_num)) {
|
||||
return inode_cache_.at(inode_num).Duplicate();
|
||||
}
|
||||
// This calculation is cursed.
|
||||
uint64_t real_block_cnt =
|
||||
(inode->blocks - 1) / (ext2_reader_->BlockSize() / 512) + 1;
|
||||
|
||||
if (inode->block[14]) {
|
||||
dbgln("Can't handle triply-indirect blocks yet.");
|
||||
return glcr::UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
mmth::OwnedMemoryRegion double_indirect_block;
|
||||
if (inode->block[13]) {
|
||||
ASSIGN_OR_RETURN(double_indirect_block,
|
||||
ext2_reader_->ReadBlock(inode->block[13]));
|
||||
}
|
||||
|
||||
mmth::OwnedMemoryRegion indirect_block;
|
||||
if (inode->block[12]) {
|
||||
ASSIGN_OR_RETURN(indirect_block, ext2_reader_->ReadBlock(inode->block[12]));
|
||||
}
|
||||
|
||||
glcr::Vector<uint64_t> blocks_to_read;
|
||||
for (uint64_t i = 0; i < 12 && i < real_block_cnt; i++) {
|
||||
blocks_to_read.PushBack(inode->block[i]);
|
||||
}
|
||||
|
||||
uint32_t* indr_block_array =
|
||||
reinterpret_cast<uint32_t*>(indirect_block.vaddr());
|
||||
for (uint64_t i = 12; i < 268 && i < real_block_cnt; i++) {
|
||||
uint64_t offset = i - 12;
|
||||
blocks_to_read.PushBack(indr_block_array[offset]);
|
||||
}
|
||||
|
||||
uint32_t* dbl_indr_block_array =
|
||||
reinterpret_cast<uint32_t*>(double_indirect_block.vaddr());
|
||||
for (uint64_t i = 0; i < 256; i++) {
|
||||
uint64_t block = 268 + (256 * i);
|
||||
if (block >= real_block_cnt) {
|
||||
break;
|
||||
}
|
||||
ASSIGN_OR_RETURN(mmth::OwnedMemoryRegion single_indr_block,
|
||||
ext2_reader_->ReadBlock(dbl_indr_block_array[i]));
|
||||
uint32_t* single_indr_block_array =
|
||||
reinterpret_cast<uint32_t*>(single_indr_block.vaddr());
|
||||
for (uint64_t j = 0; j < 256; j++) {
|
||||
uint64_t block_inner = block + j;
|
||||
if (block_inner >= real_block_cnt) {
|
||||
break;
|
||||
}
|
||||
if (single_indr_block_array[j] != 0) {
|
||||
blocks_to_read.PushBack(single_indr_block_array[j]);
|
||||
} else {
|
||||
dbgln("WARN skipping 0 block in inode");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ASSIGN_OR_RETURN(auto inode_mem, ext2_reader_->ReadBlocks(blocks_to_read));
|
||||
RET_ERR(inode_cache_.Insert(glcr::Move(inode_num), inode_mem.Duplicate()));
|
||||
return inode_mem;
|
||||
}
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/container/hash_map.h>
|
||||
#include <glacier/memory/move.h>
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
#include <yellowstone/yellowstone.yunq.h>
|
||||
|
||||
#include "fs/ext2/ext2.h"
|
||||
#include "fs/ext2/ext2_block_reader.h"
|
||||
#include "fs/ext2/inode_table.h"
|
||||
|
||||
class Ext2Driver {
|
||||
public:
|
||||
static glcr::ErrorOr<Ext2Driver> Init(
|
||||
const yellowstone::DenaliInfo& denali_info);
|
||||
|
||||
glcr::ErrorCode ProbePartition();
|
||||
|
||||
glcr::ErrorOr<Inode*> GetInode(uint32_t inode_number);
|
||||
|
||||
glcr::ErrorOr<glcr::Vector<DirEntry>> ReadDirectory(uint32_t inode_number);
|
||||
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> ReadFile(uint64_t inode_number);
|
||||
|
||||
private:
|
||||
glcr::SharedPtr<Ext2BlockReader> ext2_reader_;
|
||||
glcr::UniquePtr<InodeTable> inode_table_;
|
||||
glcr::HashMap<uint64_t, mmth::OwnedMemoryRegion> inode_cache_;
|
||||
|
||||
Ext2Driver(const glcr::SharedPtr<Ext2BlockReader>& reader,
|
||||
glcr::UniquePtr<InodeTable> inode_table)
|
||||
: ext2_reader_(reader), inode_table_(glcr::Move(inode_table)) {}
|
||||
|
||||
glcr::ErrorOr<mmth::OwnedMemoryRegion> ReadInode(uint64_t inode_num,
|
||||
Inode* inode);
|
||||
};
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
#include "fs/ext2/inode_table.h"
|
||||
|
||||
InodeTable::InodeTable(const glcr::SharedPtr<Ext2BlockReader>& reader,
|
||||
mmth::OwnedMemoryRegion&& bgdt_region)
|
||||
: ext2_reader_(reader),
|
||||
bgdt_region_(glcr::Move(bgdt_region)),
|
||||
bgdt_(reinterpret_cast<BlockGroupDescriptor*>(bgdt_region_.vaddr())) {
|
||||
inode_tables_.Resize(ext2_reader_->NumberOfBlockGroups());
|
||||
}
|
||||
|
||||
glcr::ErrorOr<Inode*> InodeTable::GetInode(uint32_t inode_num) {
|
||||
uint64_t inodes_per_group = ext2_reader_->GetSuperblock()->inodes_per_group;
|
||||
uint64_t block_group_num = (inode_num - 1) / inodes_per_group;
|
||||
ASSIGN_OR_RETURN(Inode * root, GetRootOfInodeTable(block_group_num));
|
||||
uint64_t local_index = (inode_num - 1) % inodes_per_group;
|
||||
return reinterpret_cast<Inode*>(reinterpret_cast<uint64_t>(root) +
|
||||
local_index * ext2_reader_->InodeSize());
|
||||
}
|
||||
|
||||
glcr::ErrorOr<Inode*> InodeTable::GetRootOfInodeTable(
|
||||
uint64_t block_group_num) {
|
||||
if (block_group_num > ext2_reader_->NumberOfBlockGroups()) {
|
||||
return glcr::INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
if (!inode_tables_[block_group_num]) {
|
||||
ASSIGN_OR_RETURN(
|
||||
inode_tables_[block_group_num],
|
||||
ext2_reader_->ReadBlocks(bgdt_[block_group_num].inode_table,
|
||||
ext2_reader_->InodeTableBlockSize()));
|
||||
}
|
||||
return reinterpret_cast<Inode*>(inode_tables_[block_group_num].vaddr());
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/container/vector.h>
|
||||
#include <mammoth/util/memory_region.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "fs/ext2/ext2_block_reader.h"
|
||||
|
||||
class InodeTable {
|
||||
public:
|
||||
InodeTable(const glcr::SharedPtr<Ext2BlockReader>& driver,
|
||||
mmth::OwnedMemoryRegion&& bgdt_region);
|
||||
|
||||
glcr::ErrorOr<Inode*> GetInode(uint32_t inode_num);
|
||||
|
||||
private:
|
||||
glcr::SharedPtr<Ext2BlockReader> ext2_reader_;
|
||||
mmth::OwnedMemoryRegion bgdt_region_;
|
||||
BlockGroupDescriptor* bgdt_;
|
||||
|
||||
glcr::Vector<mmth::OwnedMemoryRegion> inode_tables_;
|
||||
|
||||
glcr::ErrorOr<Inode*> GetRootOfInodeTable(uint64_t block_group_num);
|
||||
};
|
||||
|
|
@ -1,23 +0,0 @@
|
|||
interface VFS {
|
||||
method OpenFile(OpenFileRequest) -> (OpenFileResponse);
|
||||
method GetDirectory(GetDirectoryRequest) -> (Directory);
|
||||
}
|
||||
|
||||
message OpenFileRequest {
|
||||
string path;
|
||||
}
|
||||
|
||||
message OpenFileResponse {
|
||||
string path;
|
||||
u64 size;
|
||||
capability memory;
|
||||
}
|
||||
|
||||
message GetDirectoryRequest {
|
||||
string path;
|
||||
}
|
||||
|
||||
message Directory {
|
||||
// , separated list of filenames until we have repeated strings.
|
||||
string filenames;
|
||||
}
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
// Generated file - DO NOT MODIFY
|
||||
#include "victoriafalls.yunq.client.h"
|
||||
|
||||
#include <glacier/buffer/byte_buffer.h>
|
||||
#include <glacier/buffer/cap_buffer.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <zcall.h>
|
||||
|
||||
|
||||
|
||||
|
||||
VFSClient::~VFSClient() {
|
||||
if (endpoint_ != 0) {
|
||||
check(ZCapRelease(endpoint_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
glcr::Status VFSClient::OpenFile(const OpenFileRequest& request, OpenFileResponse& response) {
|
||||
|
||||
uint64_t buffer_size = kBufferSize;
|
||||
uint64_t cap_size = kCapBufferSize;
|
||||
|
||||
const uint32_t kSentinel = 0xBEEFDEAD;
|
||||
buffer_.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer_.WriteAt<uint64_t>(8, 0);
|
||||
|
||||
cap_buffer_.Reset();
|
||||
|
||||
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
|
||||
|
||||
|
||||
buffer_.WriteAt<uint32_t>(4, 16 + length);
|
||||
|
||||
z_cap_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), cap_buffer_.UsedSlots(), cap_buffer_.RawPtr(), &reply_port_cap));
|
||||
|
||||
// FIXME: Add a way to zero out the first buffer.
|
||||
RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr()));
|
||||
|
||||
if (buffer_.At<uint32_t>(0) != kSentinel) {
|
||||
return glcr::InvalidResponse("Got an invalid response from server.");
|
||||
}
|
||||
|
||||
// Check Response Code.
|
||||
RET_ERR(buffer_.At<uint64_t>(8));
|
||||
|
||||
|
||||
yunq::MessageView resp_view(buffer_, 16);
|
||||
RETURN_ERROR(response.ParseFromBytes(resp_view, cap_buffer_));
|
||||
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
glcr::Status VFSClient::GetDirectory(const GetDirectoryRequest& request, Directory& response) {
|
||||
|
||||
uint64_t buffer_size = kBufferSize;
|
||||
uint64_t cap_size = kCapBufferSize;
|
||||
|
||||
const uint32_t kSentinel = 0xBEEFDEAD;
|
||||
buffer_.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer_.WriteAt<uint64_t>(8, 1);
|
||||
|
||||
cap_buffer_.Reset();
|
||||
|
||||
uint64_t length = request.SerializeToBytes(buffer_, /*offset=*/16, cap_buffer_);
|
||||
|
||||
|
||||
buffer_.WriteAt<uint32_t>(4, 16 + length);
|
||||
|
||||
z_cap_t reply_port_cap;
|
||||
RET_ERR(ZEndpointSend(endpoint_, 16 + length, buffer_.RawPtr(), cap_buffer_.UsedSlots(), cap_buffer_.RawPtr(), &reply_port_cap));
|
||||
|
||||
// FIXME: Add a way to zero out the first buffer.
|
||||
RET_ERR(ZReplyPortRecv(reply_port_cap, &buffer_size, buffer_.RawPtr(), &cap_size, cap_buffer_.RawPtr()));
|
||||
|
||||
if (buffer_.At<uint32_t>(0) != kSentinel) {
|
||||
return glcr::InvalidResponse("Got an invalid response from server.");
|
||||
}
|
||||
|
||||
// Check Response Code.
|
||||
RET_ERR(buffer_.At<uint64_t>(8));
|
||||
|
||||
|
||||
yunq::MessageView resp_view(buffer_, 16);
|
||||
RETURN_ERROR(response.ParseFromBytes(resp_view, cap_buffer_));
|
||||
|
||||
|
||||
return glcr::OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
// Generated file - DO NOT MODIFY
|
||||
#pragma once
|
||||
|
||||
#include <glacier/buffer/byte_buffer.h>
|
||||
#include <glacier/buffer/cap_buffer.h>
|
||||
#include <glacier/status/error.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
#include "victoriafalls.yunq.h"
|
||||
|
||||
|
||||
class VFSClient {
|
||||
public:
|
||||
VFSClient(z_cap_t VFS_cap) : endpoint_(VFS_cap) {}
|
||||
VFSClient(const VFSClient&) = delete;
|
||||
VFSClient(VFSClient&& other) : endpoint_(other.endpoint_) {other.endpoint_ = 0;};
|
||||
~VFSClient();
|
||||
|
||||
z_cap_t Capability() { return endpoint_; }
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] glcr::Status OpenFile(const OpenFileRequest& request, OpenFileResponse& response);
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] glcr::Status GetDirectory(const GetDirectoryRequest& request, Directory& response);
|
||||
|
||||
|
||||
private:
|
||||
z_cap_t endpoint_;
|
||||
uint64_t kBufferSize = 0x1000;
|
||||
glcr::ByteBuffer buffer_{kBufferSize};
|
||||
uint64_t kCapBufferSize = 0x10;
|
||||
glcr::CapBuffer cap_buffer_{kCapBufferSize};
|
||||
};
|
||||
|
||||
|
|
@ -1,173 +0,0 @@
|
|||
// Generated file -- DO NOT MODIFY.
|
||||
#include "victoriafalls.yunq.h"
|
||||
|
||||
#include <yunq/message_view.h>
|
||||
#include <yunq/serialize.h>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
const uint64_t header_size = 24; // 4x uint32, 1x uint64
|
||||
|
||||
struct ExtPointer {
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
glcr::Status OpenFileRequest::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status OpenFileRequest::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status OpenFileRequest::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse path.
|
||||
ASSIGN_OR_RETURN(path_, message.ReadField<glcr::String>(0));
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 1);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t OpenFileRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 1, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t OpenFileRequest::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write path.
|
||||
serializer.WriteField<glcr::String>(0, path_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
glcr::Status OpenFileResponse::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
// Parse memory.
|
||||
ASSIGN_OR_RETURN(memory_, message.ReadCapability(2));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status OpenFileResponse::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
// Parse memory.
|
||||
ASSIGN_OR_RETURN(memory_, message.ReadCapability(2, caps));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status OpenFileResponse::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse path.
|
||||
ASSIGN_OR_RETURN(path_, message.ReadField<glcr::String>(0));
|
||||
// Parse size.
|
||||
ASSIGN_OR_RETURN(size_, message.ReadField<uint64_t>(1));
|
||||
// Parse memory.
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t OpenFileResponse::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 3);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t OpenFileResponse::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 3, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t OpenFileResponse::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write path.
|
||||
serializer.WriteField<glcr::String>(0, path_);
|
||||
// Write size.
|
||||
serializer.WriteField<uint64_t>(1, size_);
|
||||
// Write memory.
|
||||
serializer.WriteCapability(2, memory_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
glcr::Status GetDirectoryRequest::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status GetDirectoryRequest::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status GetDirectoryRequest::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse path.
|
||||
ASSIGN_OR_RETURN(path_, message.ReadField<glcr::String>(0));
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t GetDirectoryRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 1);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t GetDirectoryRequest::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 1, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t GetDirectoryRequest::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write path.
|
||||
serializer.WriteField<glcr::String>(0, path_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
glcr::Status Directory::ParseFromBytes(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status Directory::ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer& caps) {
|
||||
RETURN_ERROR(ParseFromBytesInternal(message));
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status Directory::ParseFromBytesInternal(const yunq::MessageView& message) {
|
||||
RETURN_ERROR(message.CheckHeader());
|
||||
// Parse filenames.
|
||||
ASSIGN_OR_RETURN(filenames_, message.ReadField<glcr::String>(0));
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
uint64_t Directory::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset) const {
|
||||
yunq::Serializer serializer(bytes, offset, 1);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t Directory::SerializeToBytes(glcr::ByteBuffer& bytes, uint64_t offset, glcr::CapBuffer& caps) const {
|
||||
yunq::Serializer serializer(bytes, offset, 1, caps);
|
||||
return SerializeInternal(serializer);
|
||||
}
|
||||
|
||||
uint64_t Directory::SerializeInternal(yunq::Serializer& serializer) const {
|
||||
// Write filenames.
|
||||
serializer.WriteField<glcr::String>(0, filenames_);
|
||||
|
||||
serializer.WriteHeader();
|
||||
|
||||
return serializer.size();
|
||||
}
|
||||
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
// Generated file - DO NOT MODIFY
|
||||
#pragma once
|
||||
|
||||
#include <glacier/buffer/byte_buffer.h>
|
||||
#include <glacier/buffer/cap_buffer.h>
|
||||
#include <glacier/status/status.h>
|
||||
#include <glacier/container/vector.h>
|
||||
#include <glacier/string/string.h>
|
||||
#include <yunq/message_view.h>
|
||||
#include <yunq/serialize.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
|
||||
class OpenFileRequest {
|
||||
public:
|
||||
OpenFileRequest() {}
|
||||
// Delete copy and move until implemented.
|
||||
OpenFileRequest(const OpenFileRequest&) = delete;
|
||||
OpenFileRequest(OpenFileRequest&&) = default;
|
||||
OpenFileRequest& operator=(OpenFileRequest&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const glcr::String& path() const { return path_; }
|
||||
glcr::String& mutable_path() { return path_; }
|
||||
void set_path(const glcr::String& value) { path_ = value; }
|
||||
|
||||
private:
|
||||
glcr::String path_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
class OpenFileResponse {
|
||||
public:
|
||||
OpenFileResponse() {}
|
||||
// Delete copy and move until implemented.
|
||||
OpenFileResponse(const OpenFileResponse&) = delete;
|
||||
OpenFileResponse(OpenFileResponse&&) = default;
|
||||
OpenFileResponse& operator=(OpenFileResponse&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const glcr::String& path() const { return path_; }
|
||||
glcr::String& mutable_path() { return path_; }
|
||||
void set_path(const glcr::String& value) { path_ = value; }
|
||||
|
||||
const uint64_t& size() const { return size_; }
|
||||
uint64_t& mutable_size() { return size_; }
|
||||
void set_size(const uint64_t& value) { size_ = value; }
|
||||
|
||||
const z_cap_t& memory() const { return memory_; }
|
||||
z_cap_t& mutable_memory() { return memory_; }
|
||||
void set_memory(const z_cap_t& value) { memory_ = value; }
|
||||
|
||||
private:
|
||||
glcr::String path_;
|
||||
uint64_t size_;
|
||||
z_cap_t memory_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
class GetDirectoryRequest {
|
||||
public:
|
||||
GetDirectoryRequest() {}
|
||||
// Delete copy and move until implemented.
|
||||
GetDirectoryRequest(const GetDirectoryRequest&) = delete;
|
||||
GetDirectoryRequest(GetDirectoryRequest&&) = default;
|
||||
GetDirectoryRequest& operator=(GetDirectoryRequest&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const glcr::String& path() const { return path_; }
|
||||
glcr::String& mutable_path() { return path_; }
|
||||
void set_path(const glcr::String& value) { path_ = value; }
|
||||
|
||||
private:
|
||||
glcr::String path_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
class Directory {
|
||||
public:
|
||||
Directory() {}
|
||||
// Delete copy and move until implemented.
|
||||
Directory(const Directory&) = delete;
|
||||
Directory(Directory&&) = default;
|
||||
Directory& operator=(Directory&&) = default;
|
||||
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message);
|
||||
[[nodiscard]] glcr::Status ParseFromBytes(const yunq::MessageView& message, const glcr::CapBuffer&);
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset) const;
|
||||
uint64_t SerializeToBytes(glcr::ByteBuffer&, uint64_t offset, glcr::CapBuffer&) const;
|
||||
|
||||
const glcr::String& filenames() const { return filenames_; }
|
||||
glcr::String& mutable_filenames() { return filenames_; }
|
||||
void set_filenames(const glcr::String& value) { filenames_ = value; }
|
||||
|
||||
private:
|
||||
glcr::String filenames_;
|
||||
|
||||
// Parses everything except for caps.
|
||||
glcr::Status ParseFromBytesInternal(const yunq::MessageView& message);
|
||||
|
||||
uint64_t SerializeInternal(yunq::Serializer& serializer) const;
|
||||
};
|
||||
|
||||
|
|
@ -1,152 +0,0 @@
|
|||
// Generated file -- DO NOT MODIFY.
|
||||
#include "victoriafalls.yunq.server.h"
|
||||
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <zcall.h>
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
const uint32_t kSentinel = 0xBEEFDEAD;
|
||||
const uint32_t kHeaderSize = 0x10;
|
||||
|
||||
void WriteError(glcr::ByteBuffer& buffer, glcr::ErrorCode err) {
|
||||
buffer.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer.WriteAt<uint32_t>(4, kHeaderSize);
|
||||
buffer.WriteAt<uint64_t>(8, err);
|
||||
}
|
||||
|
||||
void WriteHeader(glcr::ByteBuffer& buffer, uint64_t message_length) {
|
||||
buffer.WriteAt<uint32_t>(0, kSentinel);
|
||||
buffer.WriteAt<uint32_t>(4, kHeaderSize + message_length);
|
||||
buffer.WriteAt<uint64_t>(8, glcr::OK);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
|
||||
void VFSServerBaseThreadBootstrap(void* server_base) {
|
||||
((VFSServerBase*)server_base)->ServerThread();
|
||||
}
|
||||
|
||||
VFSServerBase::~VFSServerBase() {
|
||||
if (endpoint_ != 0) {
|
||||
check(ZCapRelease(endpoint_));
|
||||
}
|
||||
}
|
||||
|
||||
glcr::ErrorOr<z_cap_t> VFSServerBase::CreateClientCap() {
|
||||
uint64_t client_cap;
|
||||
RET_ERR(ZCapDuplicate(endpoint_, ~(kZionPerm_Read), &client_cap));
|
||||
return client_cap;
|
||||
}
|
||||
|
||||
glcr::ErrorOr<VFSClient> VFSServerBase::CreateClient() {
|
||||
uint64_t client_cap;
|
||||
RET_ERR(ZCapDuplicate(endpoint_, ~(kZionPerm_Read), &client_cap));
|
||||
return VFSClient(client_cap);
|
||||
}
|
||||
|
||||
Thread VFSServerBase::RunServer() {
|
||||
return Thread(VFSServerBaseThreadBootstrap, this);
|
||||
}
|
||||
|
||||
void VFSServerBase::ServerThread() {
|
||||
glcr::ByteBuffer recv_buffer(0x1000);
|
||||
glcr::CapBuffer recv_cap(0x10);
|
||||
glcr::ByteBuffer resp_buffer(0x1000);
|
||||
glcr::CapBuffer resp_cap(0x10);
|
||||
z_cap_t reply_port_cap;
|
||||
|
||||
while (true) {
|
||||
uint64_t recv_cap_size = 0x10;
|
||||
uint64_t recv_buf_size = 0x1000;
|
||||
recv_cap.Reset();
|
||||
glcr::ErrorCode recv_err = static_cast<glcr::ErrorCode>(ZEndpointRecv(endpoint_, &recv_buf_size, recv_buffer.RawPtr(), &recv_cap_size, recv_cap.RawPtr(), &reply_port_cap));
|
||||
if (recv_err != glcr::OK) {
|
||||
dbgln("Error in receive: {x}", recv_err);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint64_t resp_length = 0;
|
||||
|
||||
glcr::ErrorCode reply_err = glcr::OK;
|
||||
resp_cap.Reset();
|
||||
glcr::Status err = HandleRequest(recv_buffer, recv_cap, resp_buffer, resp_length, resp_cap);
|
||||
if (!err) {
|
||||
WriteError(resp_buffer, err.code());
|
||||
dbgln("Responding Error {}", err.message());
|
||||
reply_err = static_cast<glcr::ErrorCode>(ZReplyPortSend(reply_port_cap, kHeaderSize, resp_buffer.RawPtr(), 0, nullptr));
|
||||
} else {
|
||||
WriteHeader(resp_buffer, resp_length);
|
||||
reply_err = static_cast<glcr::ErrorCode>(ZReplyPortSend(reply_port_cap, kHeaderSize + resp_length, resp_buffer.RawPtr(), resp_cap.UsedSlots(), resp_cap.RawPtr()));
|
||||
}
|
||||
if (reply_err != glcr::OK) {
|
||||
dbgln("Error in reply: {x}", reply_err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
glcr::Status VFSServerBase::HandleRequest(const glcr::ByteBuffer& request,
|
||||
const glcr::CapBuffer& req_caps,
|
||||
glcr::ByteBuffer& response, uint64_t& resp_length,
|
||||
glcr::CapBuffer& resp_caps) {
|
||||
if (request.At<uint32_t>(0) != kSentinel) {
|
||||
return glcr::InvalidArgument("Request Not Valid");
|
||||
}
|
||||
|
||||
uint64_t method_select = request.At<uint64_t>(8);
|
||||
|
||||
switch(method_select) {
|
||||
case 0: {
|
||||
|
||||
|
||||
OpenFileRequest yunq_request;
|
||||
yunq::MessageView request_view(request, kHeaderSize);
|
||||
RETURN_ERROR(yunq_request.ParseFromBytes(request_view, req_caps));
|
||||
|
||||
|
||||
|
||||
OpenFileResponse yunq_response;
|
||||
|
||||
|
||||
|
||||
RETURN_ERROR(HandleOpenFile(yunq_request, yunq_response));
|
||||
|
||||
|
||||
|
||||
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
|
||||
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
|
||||
|
||||
GetDirectoryRequest yunq_request;
|
||||
yunq::MessageView request_view(request, kHeaderSize);
|
||||
RETURN_ERROR(yunq_request.ParseFromBytes(request_view, req_caps));
|
||||
|
||||
|
||||
|
||||
Directory yunq_response;
|
||||
|
||||
|
||||
|
||||
RETURN_ERROR(HandleGetDirectory(yunq_request, yunq_response));
|
||||
|
||||
|
||||
|
||||
resp_length = yunq_response.SerializeToBytes(response, kHeaderSize, resp_caps);
|
||||
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return glcr::Unimplemented("Method unimplemented by server.");
|
||||
}
|
||||
}
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
// Generated File -- DO NOT MODIFY.
|
||||
#pragma once
|
||||
|
||||
#include <glacier/status/error_or.h>
|
||||
#include <glacier/status/status.h>
|
||||
#include <mammoth/proc/thread.h>
|
||||
#include <ztypes.h>
|
||||
|
||||
#include "victoriafalls.yunq.h"
|
||||
#include "victoriafalls.yunq.client.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class VFSServerBase {
|
||||
public:
|
||||
VFSServerBase(z_cap_t VFS_cap) : endpoint_(VFS_cap) {}
|
||||
VFSServerBase(const VFSServerBase&) = delete;
|
||||
VFSServerBase(VFSServerBase&&) = delete;
|
||||
virtual ~VFSServerBase();
|
||||
|
||||
glcr::ErrorOr<z_cap_t> CreateClientCap();
|
||||
glcr::ErrorOr<VFSClient> CreateClient();
|
||||
|
||||
[[nodiscard]] Thread RunServer();
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] virtual glcr::Status HandleOpenFile(const OpenFileRequest&, OpenFileResponse&) = 0;
|
||||
|
||||
|
||||
|
||||
[[nodiscard]] virtual glcr::Status HandleGetDirectory(const GetDirectoryRequest&, Directory&) = 0;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
z_cap_t endpoint_;
|
||||
|
||||
friend void VFSServerBaseThreadBootstrap(void*);
|
||||
void ServerThread();
|
||||
|
||||
[[nodiscard]] glcr::Status HandleRequest(const glcr::ByteBuffer& request, const glcr::CapBuffer& req_caps,
|
||||
glcr::ByteBuffer& response, uint64_t& resp_length,
|
||||
glcr::CapBuffer& resp_caps);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
#include <mammoth/util/debug.h>
|
||||
#include <mammoth/util/init.h>
|
||||
#include <yellowstone/yellowstone.yunq.client.h>
|
||||
|
||||
#include "fs/ext2/ext2_driver.h"
|
||||
#include "victoriafalls_server.h"
|
||||
|
||||
using yellowstone::DenaliInfo;
|
||||
using yellowstone::RegisterEndpointRequest;
|
||||
using yellowstone::YellowstoneClient;
|
||||
|
||||
uint64_t main(uint64_t init_cap) {
|
||||
ParseInitPort(init_cap);
|
||||
|
||||
dbgln("VFs Started");
|
||||
|
||||
YellowstoneClient yellowstone(gInitEndpointCap);
|
||||
DenaliInfo denali_info;
|
||||
check(yellowstone.GetDenali(denali_info));
|
||||
ASSIGN_OR_RETURN(Ext2Driver ext2, Ext2Driver::Init(denali_info));
|
||||
|
||||
ASSIGN_OR_RETURN(auto server, VFSServer::Create(ext2));
|
||||
|
||||
Thread server_thread = server->RunServer();
|
||||
|
||||
RegisterEndpointRequest req;
|
||||
req.set_endpoint_name("victoriafalls");
|
||||
ASSIGN_OR_RETURN(auto client_cap, server->CreateClientCap());
|
||||
req.set_endpoint_capability(client_cap);
|
||||
check(yellowstone.RegisterEndpoint(req));
|
||||
|
||||
RET_ERR(server_thread.Join());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
#include "victoriafalls_server.h"
|
||||
|
||||
#include <glacier/string/str_split.h>
|
||||
#include <mammoth/util/debug.h>
|
||||
#include <zcall.h>
|
||||
|
||||
glcr::ErrorOr<glcr::UniquePtr<VFSServer>> VFSServer::Create(
|
||||
Ext2Driver& driver) {
|
||||
z_cap_t endpoint_cap;
|
||||
RET_ERR(ZEndpointCreate(&endpoint_cap));
|
||||
return glcr::UniquePtr<VFSServer>(new VFSServer(endpoint_cap, driver));
|
||||
}
|
||||
|
||||
glcr::Status VFSServer::HandleOpenFile(const OpenFileRequest& request,
|
||||
OpenFileResponse& response) {
|
||||
auto path_tokens = glcr::StrSplit(request.path(), '/');
|
||||
// Require all paths to be absolute rather than relative.
|
||||
// If the path starts with '/' then the first token will be empty.
|
||||
if (path_tokens.at(0) != "") {
|
||||
return glcr::InvalidArgument("Open file supports only absolute paths.");
|
||||
}
|
||||
|
||||
ASSIGN_OR_RETURN(auto files, driver_.ReadDirectory(2));
|
||||
for (uint64_t i = 1; i < path_tokens.size() - 1; i++) {
|
||||
bool found_token = false;
|
||||
for (uint64_t j = 0; j < files.size() && !found_token; j++) {
|
||||
if (path_tokens.at(i) ==
|
||||
glcr::StringView(files.at(j).name, files.at(j).name_len)) {
|
||||
ASSIGN_OR_RETURN(files, driver_.ReadDirectory(files.at(j).inode));
|
||||
found_token = true;
|
||||
}
|
||||
}
|
||||
if (!found_token) {
|
||||
return glcr::NotFound(glcr::StrFormat("Directory '{}' not found.",
|
||||
glcr::String(path_tokens.at(i))));
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t inode_num;
|
||||
mmth::OwnedMemoryRegion region;
|
||||
for (uint64_t j = 0; j < files.size(); j++) {
|
||||
if (path_tokens.at(path_tokens.size() - 1) ==
|
||||
glcr::StringView(files.at(j).name, files.at(j).name_len)) {
|
||||
inode_num = files.at(j).inode;
|
||||
ASSIGN_OR_RETURN(region, driver_.ReadFile(files.at(j).inode));
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!region) {
|
||||
return glcr::NotFound(
|
||||
glcr::StrFormat("File '{}' not found.",
|
||||
glcr::String(path_tokens.at(path_tokens.size() - 1))));
|
||||
}
|
||||
|
||||
response.set_path(request.path());
|
||||
// FIXME: There isn't really a reason we need to map the file into memory then
|
||||
// duplicate the cap. In the future just get the cap from the read then pass
|
||||
// it to the caller directly.
|
||||
response.set_memory(region.DuplicateCap());
|
||||
// TODO: Consider folding this up into the actual read call.
|
||||
ASSIGN_OR_RETURN(Inode * inode, driver_.GetInode(inode_num));
|
||||
// FIXME: This technically only sets the lower 32 bits.
|
||||
response.set_size(inode->size);
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
||||
glcr::Status VFSServer::HandleGetDirectory(const GetDirectoryRequest& request,
|
||||
Directory& response) {
|
||||
auto path_tokens = glcr::StrSplit(request.path(), '/');
|
||||
|
||||
if (path_tokens.at(0) != "") {
|
||||
return glcr::InvalidArgument("Get Directory only supports absolute path.");
|
||||
}
|
||||
|
||||
// If there is a trailing slash we can get rid of the empty string.
|
||||
if (path_tokens.at(path_tokens.size() - 1) == "") {
|
||||
path_tokens.PopBack();
|
||||
}
|
||||
|
||||
ASSIGN_OR_RETURN(auto files, driver_.ReadDirectory(2));
|
||||
for (uint64_t i = 1; i < path_tokens.size(); i++) {
|
||||
bool found_token = false;
|
||||
for (uint64_t j = 0; j < files.size() && !found_token; j++) {
|
||||
if (path_tokens.at(i) ==
|
||||
glcr::StringView(files.at(j).name, files.at(j).name_len)) {
|
||||
ASSIGN_OR_RETURN(files, driver_.ReadDirectory(files.at(j).inode));
|
||||
found_token = true;
|
||||
}
|
||||
}
|
||||
if (!found_token) {
|
||||
return glcr::NotFound(glcr::StrFormat("Directory '{}' not found.",
|
||||
glcr::String(path_tokens.at(i))));
|
||||
}
|
||||
}
|
||||
|
||||
glcr::VariableStringBuilder filelist;
|
||||
for (const DirEntry& file : files) {
|
||||
filelist.PushBack(glcr::StringView(file.name, file.name_len));
|
||||
filelist.PushBack(',');
|
||||
}
|
||||
// Remove trailing comma.
|
||||
if (filelist.size() > 0) {
|
||||
filelist.DeleteLast();
|
||||
}
|
||||
|
||||
response.set_filenames(filelist.ToString());
|
||||
|
||||
return glcr::Status::Ok();
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <glacier/memory/unique_ptr.h>
|
||||
|
||||
#include "fs/ext2/ext2_driver.h"
|
||||
#include "victoriafalls/victoriafalls.yunq.server.h"
|
||||
|
||||
class VFSServer : public VFSServerBase {
|
||||
public:
|
||||
static glcr::ErrorOr<glcr::UniquePtr<VFSServer>> Create(Ext2Driver& driver);
|
||||
|
||||
glcr::Status HandleOpenFile(const OpenFileRequest&,
|
||||
OpenFileResponse&) override;
|
||||
|
||||
glcr::Status HandleGetDirectory(const GetDirectoryRequest&,
|
||||
Directory&) override;
|
||||
|
||||
private:
|
||||
// FIXME: Don't store this as a reference.
|
||||
Ext2Driver& driver_;
|
||||
|
||||
VFSServer(z_cap_t endpoint_cap, Ext2Driver& driver)
|
||||
: VFSServerBase(endpoint_cap), driver_(driver) {}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue