From 83d2b21f09189f20478de18a244f3ec1e6918e75 Mon Sep 17 00:00:00 2001 From: Dennis Bonke Date: Thu, 5 Oct 2023 00:50:22 +0200 Subject: [PATCH] fs: Implement O_APPEND for ext2 --- drivers/libblockfs/src/ext2fs.hpp | 1 + drivers/libblockfs/src/libblockfs.cpp | 6 +++- posix/subsystem/src/extern_fs.cpp | 31 ++++++++++++++------ posix/subsystem/src/file.hpp | 9 +++--- posix/subsystem/src/fs.hpp | 1 + posix/subsystem/src/requests.cpp | 6 +++- protocols/fs/fs.bragi | 2 ++ protocols/fs/include/protocols/fs/server.hpp | 2 +- protocols/fs/src/server.cpp | 2 +- protocols/posix/posix.bragi | 3 +- 10 files changed, 45 insertions(+), 18 deletions(-) diff --git a/drivers/libblockfs/src/ext2fs.hpp b/drivers/libblockfs/src/ext2fs.hpp index 73c4dac1d..4e6d68906 100644 --- a/drivers/libblockfs/src/ext2fs.hpp +++ b/drivers/libblockfs/src/ext2fs.hpp @@ -312,6 +312,7 @@ struct OpenFile { std::shared_ptr inode; uint64_t offset; Flock flock; + bool append; }; } } // namespace blockfs::ext2fs diff --git a/drivers/libblockfs/src/libblockfs.cpp b/drivers/libblockfs/src/libblockfs.cpp index 5d21e7ac3..31bfa0848 100644 --- a/drivers/libblockfs/src/libblockfs.cpp +++ b/drivers/libblockfs/src/libblockfs.cpp @@ -164,6 +164,9 @@ async::result> write(void *object, c } auto self = static_cast(object); + if(self->append) { + self->offset = self->inode->fileSize(); + } co_await self->inode->fs.write(self->inode.get(), self->offset, buffer, length); self->offset += length; co_return length; @@ -330,10 +333,11 @@ getStats(std::shared_ptr object) { } async::result -open(std::shared_ptr object) { +open(std::shared_ptr object, bool append) { auto self = std::static_pointer_cast(object); auto file = smarter::make_shared(self); co_await self->readyJump.wait(); + file->append = append; helix::UniqueLane local_ctrl, remote_ctrl; helix::UniqueLane local_pt, remote_pt; diff --git a/posix/subsystem/src/extern_fs.cpp b/posix/subsystem/src/extern_fs.cpp index de500f410..fc1accdf0 100644 --- a/posix/subsystem/src/extern_fs.cpp +++ b/posix/subsystem/src/extern_fs.cpp @@ -207,9 +207,9 @@ struct OpenFile final : File { public: OpenFile(helix::UniqueLane control, helix::UniqueLane lane, - std::shared_ptr mount, std::shared_ptr link) + std::shared_ptr mount, std::shared_ptr link, bool append) : File{StructName::get("externfs.file"), std::move(mount), std::move(link)}, - _control{std::move(control)}, _file{std::move(lane)} { } + _control{std::move(control)}, _file{std::move(lane)}, _append(append) { } ~OpenFile() { // It's not necessary to do any cleanup here. @@ -247,6 +247,7 @@ struct OpenFile final : File { private: helix::UniqueLane _control; protocols::fs::File _file; + bool _append; }; struct RegularNode final : Node { @@ -261,10 +262,10 @@ struct RegularNode final : Node { // Regular files do not support O_NONBLOCK. semantic_flags &= ~semanticNonBlock; - if(semantic_flags & ~(semanticRead | semanticWrite)){ + if(semantic_flags & ~(semanticRead | semanticWrite | semanticAppend)){ std::cout << "\e[31mposix: open() received illegal arguments:" << std::bitset<32>(semantic_flags) - << "\nOnly semanticRead (0x2) and semanticWrite(0x4) are allowed.\e[39m" + << "\nOnly semanticRead (0x2), semanticWrite (0x4) and semanticAppend (0x8) are allowed.\e[39m" << std::endl; co_return Error::illegalArguments; } @@ -274,8 +275,14 @@ struct RegularNode final : Node { helix::PullDescriptor pull_ctrl; helix::PullDescriptor pull_passthrough; + bool append = false; + if(semantic_flags & semanticAppend) { + append = true; + } + managarm::fs::CntRequest req; req.set_req_type(managarm::fs::CntReqType::NODE_OPEN); + req.set_append(append); auto ser = req.SerializeAsString(); auto &&transmit = helix::submitAsync(getLane(), helix::Dispatcher::global(), @@ -296,7 +303,7 @@ struct RegularNode final : Node { assert(resp.error() == managarm::fs::Errors::SUCCESS); auto file = smarter::make_shared(pull_ctrl.descriptor(), - pull_passthrough.descriptor(), std::move(mount), std::move(link)); + pull_passthrough.descriptor(), std::move(mount), std::move(link), append); file->setupWeakFile(file); co_return File::constructHandle(std::move(file)); } @@ -742,10 +749,10 @@ struct DirectoryNode final : Node { // Regular files do not support O_NONBLOCK. semantic_flags &= ~semanticNonBlock; - if(semantic_flags & ~(semanticRead | semanticWrite)){ + if(semantic_flags & ~(semanticRead | semanticWrite | semanticAppend)){ std::cout << "\e[31mposix: open() received illegal arguments:" << std::bitset<32>(semantic_flags) - << "\nOnly semanticRead (0x2) and semanticWrite(0x4) are allowed.\e[39m" + << "\nOnly semanticRead (0x2), semanticWrite (0x4) and semanticAppend (0x8) are allowed.\e[39m" << std::endl; co_return Error::illegalArguments; } @@ -755,8 +762,14 @@ struct DirectoryNode final : Node { helix::PullDescriptor pull_ctrl; helix::PullDescriptor pull_passthrough; + bool append = false; + if(semantic_flags & semanticAppend) { + append = true; + } + managarm::fs::CntRequest req; req.set_req_type(managarm::fs::CntReqType::NODE_OPEN); + req.set_append(append); auto ser = req.SerializeAsString(); auto &&transmit = helix::submitAsync(getLane(), helix::Dispatcher::global(), @@ -777,7 +790,7 @@ struct DirectoryNode final : Node { assert(resp.error() == managarm::fs::Errors::SUCCESS); auto file = smarter::make_shared(pull_ctrl.descriptor(), - pull_passthrough.descriptor(), std::move(mount), std::move(link)); + pull_passthrough.descriptor(), std::move(mount), std::move(link), append); file->setupWeakFile(file); co_return File::constructHandle(std::move(file)); } @@ -951,7 +964,7 @@ std::shared_ptr createRoot(helix::UniqueLane sb_lane, helix::UniqueLane smarter::shared_ptr createFile(helix::UniqueLane lane, std::shared_ptr mount, std::shared_ptr link) { auto file = smarter::make_shared(helix::UniqueLane{}, - std::move(lane), std::move(mount), std::move(link)); + std::move(lane), std::move(mount), std::move(link), false); file->setupWeakFile(file); return File::constructHandle(std::move(file)); } diff --git a/posix/subsystem/src/file.hpp b/posix/subsystem/src/file.hpp index c80063980..174add738 100644 --- a/posix/subsystem/src/file.hpp +++ b/posix/subsystem/src/file.hpp @@ -223,13 +223,13 @@ struct File : private smarter::crtp_counter { return smarter::shared_ptr{smarter::adopt_rc, file, file}; } - File(StructName struct_name, DefaultOps default_ops = 0) - : _structName{struct_name}, _defaultOps{default_ops}, _isOpen{true} { } + File(StructName struct_name, DefaultOps default_ops = 0, bool append = false) + : _structName{struct_name}, _defaultOps{default_ops}, _isOpen{true}, _append{append} { } File(StructName struct_name, std::shared_ptr mount, std::shared_ptr link, - DefaultOps default_ops = 0) + DefaultOps default_ops = 0, bool append = false) : _structName{struct_name}, _mount{std::move(mount)}, _link{std::move(link)}, - _defaultOps{default_ops}, _isOpen{true} { } + _defaultOps{default_ops}, _isOpen{true}, _append{append} { } virtual ~File(); @@ -373,6 +373,7 @@ struct File : private smarter::crtp_counter { DefaultOps _defaultOps; bool _isOpen; + bool _append; }; struct DummyFile final : File { diff --git a/posix/subsystem/src/fs.hpp b/posix/subsystem/src/fs.hpp index 934d068c4..518b92934 100644 --- a/posix/subsystem/src/fs.hpp +++ b/posix/subsystem/src/fs.hpp @@ -89,6 +89,7 @@ using SemanticFlags = uint32_t; inline constexpr SemanticFlags semanticNonBlock = 1; inline constexpr SemanticFlags semanticRead = 2; inline constexpr SemanticFlags semanticWrite = 4; +inline constexpr SemanticFlags semanticAppend = 8; // Represents an inode on an actual file system (i.e. not in the VFS). struct FsNode { diff --git a/posix/subsystem/src/requests.cpp b/posix/subsystem/src/requests.cpp index 3fc9c008a..3f8f60607 100644 --- a/posix/subsystem/src/requests.cpp +++ b/posix/subsystem/src/requests.cpp @@ -1534,7 +1534,8 @@ async::result serveRequests(std::shared_ptr self, | managarm::posix::OpenFlags::OF_WRONLY | managarm::posix::OpenFlags::OF_RDWR | managarm::posix::OpenFlags::OF_PATH - | managarm::posix::OpenFlags::OF_NOCTTY))) { + | managarm::posix::OpenFlags::OF_NOCTTY + | managarm::posix::OpenFlags::OF_APPEND))) { std::cout << "posix: OPENAT flags not recognized: " << req->flags() << std::endl; co_await sendErrorResponse(managarm::posix::Errors::ILLEGAL_ARGUMENTS); continue; @@ -1551,6 +1552,9 @@ async::result serveRequests(std::shared_ptr self, else if (req->flags() & managarm::posix::OpenFlags::OF_RDWR) semantic_flags |= semanticRead | semanticWrite; + if(req->flags() & managarm::posix::OpenFlags::OF_APPEND) + semantic_flags |= semanticAppend; + ViewPath relative_to; smarter::shared_ptr file; std::shared_ptr target_link; diff --git a/protocols/fs/fs.bragi b/protocols/fs/fs.bragi index dcded73b6..33524b357 100644 --- a/protocols/fs/fs.bragi +++ b/protocols/fs/fs.bragi @@ -266,6 +266,8 @@ head(128): tag(69) int64 pgid; tag(84) int32 seals; + + tag(85) byte append; } } diff --git a/protocols/fs/include/protocols/fs/server.hpp b/protocols/fs/include/protocols/fs/server.hpp index 88ae50f96..c5be391d1 100644 --- a/protocols/fs/include/protocols/fs/server.hpp +++ b/protocols/fs/include/protocols/fs/server.hpp @@ -219,7 +219,7 @@ struct NodeOperations { async::result> (*unlink)(std::shared_ptr object, std::string name); - async::result (*open)(std::shared_ptr object); + async::result (*open)(std::shared_ptr object, bool append); async::result (*readSymlink)(std::shared_ptr object); diff --git a/protocols/fs/src/server.cpp b/protocols/fs/src/server.cpp index 6e7af8acf..61fdcc42a 100644 --- a/protocols/fs/src/server.cpp +++ b/protocols/fs/src/server.cpp @@ -1532,7 +1532,7 @@ async::detached serveNode(helix::UniqueLane lane, std::shared_ptr node, ); HEL_CHECK(send_resp.error()); }else if(req.req_type() == managarm::fs::CntReqType::NODE_OPEN) { - auto result = co_await node_ops->open(node); + auto result = co_await node_ops->open(node, req.append()); managarm::fs::SvrResponse resp; resp.set_error(managarm::fs::Errors::SUCCESS); diff --git a/protocols/posix/posix.bragi b/protocols/posix/posix.bragi index 86237c81c..4d86bf8da 100644 --- a/protocols/posix/posix.bragi +++ b/protocols/posix/posix.bragi @@ -110,7 +110,8 @@ consts OpenFlags uint32 { OF_RDWR = 32, OF_TRUNC = 64, OF_PATH = 128, - OF_NOCTTY = 512 + OF_NOCTTY = 512, + OF_APPEND = 1024 } message CntRequest 1 {