summaryrefslogtreecommitdiff
path: root/Kernel/FileSystem
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/FileSystem')
-rw-r--r--Kernel/FileSystem/BlockBasedFileSystem.cpp76
-rw-r--r--Kernel/FileSystem/BlockBasedFileSystem.h16
-rw-r--r--Kernel/FileSystem/DevPtsFS.cpp4
-rw-r--r--Kernel/FileSystem/DevPtsFS.h4
-rw-r--r--Kernel/FileSystem/Ext2FileSystem.cpp92
-rw-r--r--Kernel/FileSystem/Ext2FileSystem.h4
-rw-r--r--Kernel/FileSystem/FIFO.cpp4
-rw-r--r--Kernel/FileSystem/FIFO.h4
-rw-r--r--Kernel/FileSystem/File.h5
-rw-r--r--Kernel/FileSystem/FileDescription.cpp9
-rw-r--r--Kernel/FileSystem/FileDescription.h6
-rw-r--r--Kernel/FileSystem/FileSystem.h1
-rw-r--r--Kernel/FileSystem/Inode.cpp7
-rw-r--r--Kernel/FileSystem/Inode.h6
-rw-r--r--Kernel/FileSystem/InodeFile.cpp4
-rw-r--r--Kernel/FileSystem/InodeFile.h4
-rw-r--r--Kernel/FileSystem/InodeWatcher.cpp12
-rw-r--r--Kernel/FileSystem/InodeWatcher.h4
-rw-r--r--Kernel/FileSystem/Plan9FileSystem.cpp19
-rw-r--r--Kernel/FileSystem/Plan9FileSystem.h4
-rw-r--r--Kernel/FileSystem/ProcFS.cpp52
-rw-r--r--Kernel/FileSystem/ProcFS.h12
-rw-r--r--Kernel/FileSystem/TmpFS.cpp16
-rw-r--r--Kernel/FileSystem/TmpFS.h4
-rw-r--r--Kernel/FileSystem/VirtualFileSystem.cpp3
25 files changed, 217 insertions, 155 deletions
diff --git a/Kernel/FileSystem/BlockBasedFileSystem.cpp b/Kernel/FileSystem/BlockBasedFileSystem.cpp
index e5880e0897..2df34a58bb 100644
--- a/Kernel/FileSystem/BlockBasedFileSystem.cpp
+++ b/Kernel/FileSystem/BlockBasedFileSystem.cpp
@@ -119,7 +119,7 @@ BlockBasedFS::~BlockBasedFS()
{
}
-bool BlockBasedFS::write_block(unsigned index, const u8* data, size_t count, size_t offset, bool allow_cache)
+int BlockBasedFS::write_block(unsigned index, const UserOrKernelBuffer& data, size_t count, size_t offset, bool allow_cache)
{
ASSERT(m_logical_block_size);
ASSERT(offset + count <= block_size());
@@ -133,9 +133,9 @@ bool BlockBasedFS::write_block(unsigned index, const u8* data, size_t count, siz
file_description().seek(base_offset, SEEK_SET);
auto nwritten = file_description().write(data, count);
if (nwritten.is_error())
- return false;
+ return -EIO; // TODO: Return error code as-is, could be -EFAULT!
ASSERT(nwritten.value() == count);
- return true;
+ return 0;
}
auto& entry = cache().get(index);
@@ -143,15 +143,16 @@ bool BlockBasedFS::write_block(unsigned index, const u8* data, size_t count, siz
// Fill the cache first.
read_block(index, nullptr, block_size());
}
- memcpy(entry.data + offset, data, count);
+ if (!data.read(entry.data + offset, count))
+ return -EFAULT;
entry.is_dirty = true;
entry.has_data = true;
cache().set_dirty(true);
- return true;
+ return 0;
}
-bool BlockBasedFS::raw_read(unsigned index, u8* buffer)
+bool BlockBasedFS::raw_read(unsigned index, UserOrKernelBuffer& buffer)
{
u32 base_offset = static_cast<u32>(index) * static_cast<u32>(m_logical_block_size);
file_description().seek(base_offset, SEEK_SET);
@@ -160,7 +161,7 @@ bool BlockBasedFS::raw_read(unsigned index, u8* buffer)
ASSERT(nread.value() == m_logical_block_size);
return true;
}
-bool BlockBasedFS::raw_write(unsigned index, const u8* buffer)
+bool BlockBasedFS::raw_write(unsigned index, const UserOrKernelBuffer& buffer)
{
u32 base_offset = static_cast<u32>(index) * static_cast<u32>(m_logical_block_size);
file_description().seek(base_offset, SEEK_SET);
@@ -170,37 +171,39 @@ bool BlockBasedFS::raw_write(unsigned index, const u8* buffer)
return true;
}
-bool BlockBasedFS::raw_read_blocks(unsigned index, size_t count, u8* buffer)
+bool BlockBasedFS::raw_read_blocks(unsigned index, size_t count, UserOrKernelBuffer& buffer)
{
+ auto current = buffer;
for (unsigned block = index; block < (index + count); block++) {
- if (!raw_read(block, buffer))
+ if (!raw_read(block, current))
return false;
- buffer += logical_block_size();
+ current = current.offset(logical_block_size());
}
return true;
}
-bool BlockBasedFS::raw_write_blocks(unsigned index, size_t count, const u8* buffer)
+bool BlockBasedFS::raw_write_blocks(unsigned index, size_t count, const UserOrKernelBuffer& buffer)
{
+ auto current = buffer;
for (unsigned block = index; block < (index + count); block++) {
- if (!raw_write(block, buffer))
+ if (!raw_write(block, current))
return false;
- buffer += logical_block_size();
+ current = current.offset(logical_block_size());
}
return true;
}
-bool BlockBasedFS::write_blocks(unsigned index, unsigned count, const u8* data, bool allow_cache)
+int BlockBasedFS::write_blocks(unsigned index, unsigned count, const UserOrKernelBuffer& data, bool allow_cache)
{
ASSERT(m_logical_block_size);
#ifdef BBFS_DEBUG
klog() << "BlockBasedFileSystem::write_blocks " << index << " x" << count;
#endif
for (unsigned i = 0; i < count; ++i)
- write_block(index + i, data + i * block_size(), block_size(), 0, allow_cache);
- return true;
+ write_block(index + i, data.offset(i * block_size()), block_size(), 0, allow_cache);
+ return 0;
}
-bool BlockBasedFS::read_block(unsigned index, u8* buffer, size_t count, size_t offset, bool allow_cache) const
+int BlockBasedFS::read_block(unsigned index, UserOrKernelBuffer* buffer, size_t count, size_t offset, bool allow_cache) const
{
ASSERT(m_logical_block_size);
ASSERT(offset + count <= block_size());
@@ -212,44 +215,45 @@ bool BlockBasedFS::read_block(unsigned index, u8* buffer, size_t count, size_t o
const_cast<BlockBasedFS*>(this)->flush_specific_block_if_needed(index);
u32 base_offset = static_cast<u32>(index) * static_cast<u32>(block_size()) + static_cast<u32>(offset);
file_description().seek(base_offset, SEEK_SET);
- auto nread = file_description().read(buffer, count);
+ auto nread = file_description().read(*buffer, count);
if (nread.is_error())
- return false;
+ return -EIO;
ASSERT(nread.value() == count);
- return true;
+ return 0;
}
auto& entry = cache().get(index);
if (!entry.has_data) {
u32 base_offset = static_cast<u32>(index) * static_cast<u32>(block_size());
file_description().seek(base_offset, SEEK_SET);
- auto nread = file_description().read(entry.data, block_size());
+ auto entry_data_buffer = UserOrKernelBuffer::for_kernel_buffer(entry.data);
+ auto nread = file_description().read(entry_data_buffer, block_size());
if (nread.is_error())
- return false;
+ return -EIO;
ASSERT(nread.value() == block_size());
entry.has_data = true;
}
- if (buffer)
- memcpy(buffer, entry.data + offset, count);
- return true;
+ if (buffer && !buffer->write(entry.data + offset, count))
+ return -EFAULT;
+ return 0;
}
-bool BlockBasedFS::read_blocks(unsigned index, unsigned count, u8* buffer, bool allow_cache) const
+int BlockBasedFS::read_blocks(unsigned index, unsigned count, UserOrKernelBuffer& buffer, bool allow_cache) const
{
ASSERT(m_logical_block_size);
if (!count)
return false;
if (count == 1)
- return read_block(index, buffer, block_size(), 0, allow_cache);
- u8* out = buffer;
-
+ return read_block(index, &buffer, block_size(), 0, allow_cache);
+ auto out = buffer;
for (unsigned i = 0; i < count; ++i) {
- if (!read_block(index + i, out, block_size(), 0, allow_cache))
- return false;
- out += block_size();
+ auto err = read_block(index + i, &out, block_size(), 0, allow_cache);
+ if (err < 0)
+ return err;
+ out = out.offset(block_size());
}
- return true;
+ return 0;
}
void BlockBasedFS::flush_specific_block_if_needed(unsigned index)
@@ -262,7 +266,8 @@ void BlockBasedFS::flush_specific_block_if_needed(unsigned index)
u32 base_offset = static_cast<u32>(entry.block_index) * static_cast<u32>(block_size());
file_description().seek(base_offset, SEEK_SET);
// FIXME: Should this error path be surfaced somehow?
- (void)file_description().write(entry.data, block_size());
+ auto entry_data_buffer = UserOrKernelBuffer::for_kernel_buffer(entry.data);
+ (void)file_description().write(entry_data_buffer, block_size());
entry.is_dirty = false;
}
});
@@ -280,7 +285,8 @@ void BlockBasedFS::flush_writes_impl()
u32 base_offset = static_cast<u32>(entry.block_index) * static_cast<u32>(block_size());
file_description().seek(base_offset, SEEK_SET);
// FIXME: Should this error path be surfaced somehow?
- (void)file_description().write(entry.data, block_size());
+ auto entry_data_buffer = UserOrKernelBuffer::for_kernel_buffer(entry.data);
+ (void)file_description().write(entry_data_buffer, block_size());
++count;
entry.is_dirty = false;
});
diff --git a/Kernel/FileSystem/BlockBasedFileSystem.h b/Kernel/FileSystem/BlockBasedFileSystem.h
index b9f7bdf601..fcf096aec3 100644
--- a/Kernel/FileSystem/BlockBasedFileSystem.h
+++ b/Kernel/FileSystem/BlockBasedFileSystem.h
@@ -42,17 +42,17 @@ public:
protected:
explicit BlockBasedFS(FileDescription&);
- bool read_block(unsigned index, u8* buffer, size_t count, size_t offset = 0, bool allow_cache = true) const;
- bool read_blocks(unsigned index, unsigned count, u8* buffer, bool allow_cache = true) const;
+ int read_block(unsigned index, UserOrKernelBuffer* buffer, size_t count, size_t offset = 0, bool allow_cache = true) const;
+ int read_blocks(unsigned index, unsigned count, UserOrKernelBuffer& buffer, bool allow_cache = true) const;
- bool raw_read(unsigned index, u8* buffer);
- bool raw_write(unsigned index, const u8* buffer);
+ bool raw_read(unsigned index, UserOrKernelBuffer& buffer);
+ bool raw_write(unsigned index, const UserOrKernelBuffer& buffer);
- bool raw_read_blocks(unsigned index, size_t count, u8* buffer);
- bool raw_write_blocks(unsigned index, size_t count, const u8* buffer);
+ bool raw_read_blocks(unsigned index, size_t count, UserOrKernelBuffer& buffer);
+ bool raw_write_blocks(unsigned index, size_t count, const UserOrKernelBuffer& buffer);
- bool write_block(unsigned index, const u8* buffer, size_t count, size_t offset = 0, bool allow_cache = true);
- bool write_blocks(unsigned index, unsigned count, const u8*, bool allow_cache = true);
+ int write_block(unsigned index, const UserOrKernelBuffer& buffer, size_t count, size_t offset = 0, bool allow_cache = true);
+ int write_blocks(unsigned index, unsigned count, const UserOrKernelBuffer&, bool allow_cache = true);
size_t m_logical_block_size { 512 };
diff --git a/Kernel/FileSystem/DevPtsFS.cpp b/Kernel/FileSystem/DevPtsFS.cpp
index 01b78c44c0..d05437591a 100644
--- a/Kernel/FileSystem/DevPtsFS.cpp
+++ b/Kernel/FileSystem/DevPtsFS.cpp
@@ -120,12 +120,12 @@ DevPtsFSInode::~DevPtsFSInode()
{
}
-ssize_t DevPtsFSInode::read_bytes(off_t, ssize_t, u8*, FileDescription*) const
+ssize_t DevPtsFSInode::read_bytes(off_t, ssize_t, UserOrKernelBuffer&, FileDescription*) const
{
ASSERT_NOT_REACHED();
}
-ssize_t DevPtsFSInode::write_bytes(off_t, ssize_t, const u8*, FileDescription*)
+ssize_t DevPtsFSInode::write_bytes(off_t, ssize_t, const UserOrKernelBuffer&, FileDescription*)
{
ASSERT_NOT_REACHED();
}
diff --git a/Kernel/FileSystem/DevPtsFS.h b/Kernel/FileSystem/DevPtsFS.h
index 3c302180fe..8ac7571136 100644
--- a/Kernel/FileSystem/DevPtsFS.h
+++ b/Kernel/FileSystem/DevPtsFS.h
@@ -67,12 +67,12 @@ private:
DevPtsFSInode(DevPtsFS&, unsigned index, SlavePTY*);
// ^Inode
- virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
+ virtual ssize_t read_bytes(off_t, ssize_t, UserOrKernelBuffer& buffer, FileDescription*) const override;
virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override;
- virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;
+ virtual ssize_t write_bytes(off_t, ssize_t, const UserOrKernelBuffer& buffer, FileDescription*) override;
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override;
virtual KResult add_child(Inode&, const StringView& name, mode_t) override;
virtual KResult remove_child(const StringView& name) override;
diff --git a/Kernel/FileSystem/Ext2FileSystem.cpp b/Kernel/FileSystem/Ext2FileSystem.cpp
index cbc9a93968..52b3037c68 100644
--- a/Kernel/FileSystem/Ext2FileSystem.cpp
+++ b/Kernel/FileSystem/Ext2FileSystem.cpp
@@ -88,7 +88,8 @@ bool Ext2FS::flush_super_block()
{
LOCKER(m_lock);
ASSERT((sizeof(ext2_super_block) % logical_block_size()) == 0);
- bool success = raw_write_blocks(2, (sizeof(ext2_super_block) / logical_block_size()), (const u8*)&m_super_block);
+ auto super_block_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&m_super_block);
+ bool success = raw_write_blocks(2, (sizeof(ext2_super_block) / logical_block_size()), super_block_buffer);
ASSERT(success);
return true;
}
@@ -104,7 +105,8 @@ bool Ext2FS::initialize()
{
LOCKER(m_lock);
ASSERT((sizeof(ext2_super_block) % logical_block_size()) == 0);
- bool success = raw_read_blocks(2, (sizeof(ext2_super_block) / logical_block_size()), (u8*)&m_super_block);
+ auto super_block_buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)&m_super_block);
+ bool success = raw_read_blocks(2, (sizeof(ext2_super_block) / logical_block_size()), super_block_buffer);
ASSERT(success);
auto& super_block = this->super_block();
@@ -139,7 +141,8 @@ bool Ext2FS::initialize()
unsigned blocks_to_read = ceil_div(m_block_group_count * sizeof(ext2_group_desc), block_size());
BlockIndex first_block_of_bgdt = block_size() == 1024 ? 2 : 1;
m_cached_group_descriptor_table = KBuffer::create_with_size(block_size() * blocks_to_read, Region::Access::Read | Region::Access::Write, "Ext2FS: Block group descriptors");
- read_blocks(first_block_of_bgdt, blocks_to_read, m_cached_group_descriptor_table.value().data());
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(m_cached_group_descriptor_table.value().data());
+ read_blocks(first_block_of_bgdt, blocks_to_read, buffer);
#ifdef EXT2_DEBUG
for (unsigned i = 1; i <= m_block_group_count; ++i) {
@@ -291,8 +294,9 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in
--remaining_blocks;
}
stream.fill_to_end(0);
- bool success = write_block(e2inode.i_block[EXT2_IND_BLOCK], block_contents.data(), block_size());
- ASSERT(success);
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(block_contents.data());
+ int err = write_block(e2inode.i_block[EXT2_IND_BLOCK], buffer, block_size());
+ ASSERT(err >= 0);
}
if (!remaining_blocks)
@@ -329,7 +333,8 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in
memset(dind_block_contents.data(), 0, dind_block_contents.size());
dind_block_dirty = true;
} else {
- read_block(e2inode.i_block[EXT2_DIND_BLOCK], dind_block_contents.data(), block_size());
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(dind_block_contents.data());
+ read_block(e2inode.i_block[EXT2_DIND_BLOCK], &buffer, block_size());
}
auto* dind_block_as_pointers = (unsigned*)dind_block_contents.data();
@@ -351,7 +356,8 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in
memset(ind_block_contents.data(), 0, dind_block_contents.size());
ind_block_dirty = true;
} else {
- read_block(indirect_block_index, ind_block_contents.data(), block_size());
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(ind_block_contents.data());
+ read_block(indirect_block_index, &buffer, block_size());
}
auto* ind_block_as_pointers = (unsigned*)ind_block_contents.data();
@@ -376,8 +382,9 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in
}
if (ind_block_dirty) {
- bool success = write_block(indirect_block_index, ind_block_contents.data(), block_size());
- ASSERT(success);
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(ind_block_contents.data());
+ int err = write_block(indirect_block_index, buffer, block_size());
+ ASSERT(err >= 0);
}
}
for (unsigned i = indirect_block_count; i < entries_per_block; ++i) {
@@ -388,8 +395,9 @@ bool Ext2FS::write_block_list_for_inode(InodeIndex inode_index, ext2_inode& e2in
}
if (dind_block_dirty) {
- bool success = write_block(e2inode.i_block[EXT2_DIND_BLOCK], dind_block_contents.data(), block_size());
- ASSERT(success);
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(dind_block_contents.data());
+ int err = write_block(e2inode.i_block[EXT2_DIND_BLOCK], buffer, block_size());
+ ASSERT(err >= 0);
}
}
@@ -462,7 +470,8 @@ Vector<Ext2FS::BlockIndex> Ext2FS::block_list_for_inode_impl(const ext2_inode& e
unsigned count = min(blocks_remaining, entries_per_block);
size_t read_size = count * sizeof(__u32);
auto array_block = ByteBuffer::create_uninitialized(read_size);
- read_block(array_block_index, array_block.data(), read_size, 0);
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(array_block.data());
+ read_block(array_block_index, &buffer, read_size, 0);
ASSERT(array_block);
auto* array = reinterpret_cast<const __u32*>(array_block.data());
for (BlockIndex i = 0; i < count; ++i)
@@ -532,7 +541,8 @@ void Ext2FS::flush_block_group_descriptor_table()
LOCKER(m_lock);
unsigned blocks_to_write = ceil_div(m_block_group_count * sizeof(ext2_group_desc), block_size());
unsigned first_block_of_bgdt = block_size() == 1024 ? 2 : 1;
- write_blocks(first_block_of_bgdt, blocks_to_write, (const u8*)block_group_descriptors());
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer((u8*)block_group_descriptors());
+ write_blocks(first_block_of_bgdt, blocks_to_write, buffer);
}
void Ext2FS::flush_writes()
@@ -548,7 +558,8 @@ void Ext2FS::flush_writes()
}
for (auto& cached_bitmap : m_cached_bitmaps) {
if (cached_bitmap->dirty) {
- write_block(cached_bitmap->bitmap_block_index, cached_bitmap->buffer.data(), block_size());
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(cached_bitmap->buffer.data());
+ write_block(cached_bitmap->bitmap_block_index, buffer, block_size());
cached_bitmap->dirty = false;
#ifdef EXT2_DEBUG
dbg() << "Flushed bitmap block " << cached_bitmap->bitmap_block_index;
@@ -653,12 +664,13 @@ RefPtr<Inode> Ext2FS::get_inode(InodeIdentifier inode) const
return {};
auto new_inode = adopt(*new Ext2FSInode(const_cast<Ext2FS&>(*this), inode.index()));
- read_block(block_index, reinterpret_cast<u8*>(&new_inode->m_raw_inode), sizeof(ext2_inode), offset);
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(reinterpret_cast<u8*>(&new_inode->m_raw_inode));
+ read_block(block_index, &buffer, sizeof(ext2_inode), offset);
m_inode_cache.set(inode.index(), new_inode);
return new_inode;
}
-ssize_t Ext2FSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDescription* description) const
+ssize_t Ext2FSInode::read_bytes(off_t offset, ssize_t count, UserOrKernelBuffer& buffer, FileDescription* description) const
{
Locker inode_locker(m_lock);
ASSERT(offset >= 0);
@@ -670,7 +682,8 @@ ssize_t Ext2FSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDes
if (is_symlink() && size() < max_inline_symlink_length) {
ASSERT(offset == 0);
ssize_t nread = min((off_t)size() - offset, static_cast<off_t>(count));
- memcpy(buffer, ((const u8*)m_raw_inode.i_block) + offset, (size_t)nread);
+ if (!buffer.write(((const u8*)m_raw_inode.i_block) + offset, (size_t)nread))
+ return -EFAULT;
return nread;
}
@@ -697,10 +710,9 @@ ssize_t Ext2FSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDes
ssize_t nread = 0;
size_t remaining_count = min((off_t)count, (off_t)size() - offset);
- u8* out = buffer;
#ifdef EXT2_DEBUG
- dbg() << "Ext2FS: Reading up to " << count << " bytes " << offset << " bytes into inode " << identifier() << " to " << (const void*)buffer;
+ dbg() << "Ext2FS: Reading up to " << count << " bytes " << offset << " bytes into inode " << identifier() << " to " << buffer.user_or_kernel_ptr();
#endif
for (size_t bi = first_block_logical_index; remaining_count && bi <= last_block_logical_index; ++bi) {
@@ -708,14 +720,14 @@ ssize_t Ext2FSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDes
ASSERT(block_index);
size_t offset_into_block = (bi == first_block_logical_index) ? offset_into_first_block : 0;
size_t num_bytes_to_copy = min(block_size - offset_into_block, remaining_count);
- bool success = fs().read_block(block_index, out, num_bytes_to_copy, offset_into_block, allow_cache);
- if (!success) {
+ auto buffer_offset = buffer.offset(nread);
+ int err = fs().read_block(block_index, &buffer_offset, num_bytes_to_copy, offset_into_block, allow_cache);
+ if (err < 0) {
klog() << "ext2fs: read_bytes: read_block(" << block_index << ") failed (lbi: " << bi << ")";
- return -EIO;
+ return err;
}
remaining_count -= num_bytes_to_copy;
nread += num_bytes_to_copy;
- out += num_bytes_to_copy;
}
return nread;
@@ -760,9 +772,9 @@ KResult Ext2FSInode::resize(u64 new_size)
}
}
- bool success = fs().write_block_list_for_inode(index(), m_raw_inode, block_list);
- if (!success)
- return KResult(-EIO);
+ int err = fs().write_block_list_for_inode(index(), m_raw_inode, block_list);
+ if (err < 0)
+ return KResult(err);
m_raw_inode.i_size = new_size;
set_metadata_dirty(true);
@@ -771,7 +783,7 @@ KResult Ext2FSInode::resize(u64 new_size)
return KSuccess;
}
-ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const u8* data, FileDescription* description)
+ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const UserOrKernelBuffer& data, FileDescription* description)
{
ASSERT(offset >= 0);
ASSERT(count >= 0);
@@ -787,9 +799,10 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const u8* data, Fi
ASSERT(offset == 0);
if (max((size_t)(offset + count), (size_t)m_raw_inode.i_size) < max_inline_symlink_length) {
#ifdef EXT2_DEBUG
- dbg() << "Ext2FS: write_bytes poking into i_block array for inline symlink '" << StringView(data, count) << " ' (" << count << " bytes)";
+ dbg() << "Ext2FS: write_bytes poking into i_block array for inline symlink '" << data.copy_into_string(count) << " ' (" << count << " bytes)";
#endif
- memcpy(((u8*)m_raw_inode.i_block) + offset, data, (size_t)count);
+ if (!data.read(((u8*)m_raw_inode.i_block) + offset, (size_t)count))
+ return -EFAULT;
if ((size_t)(offset + count) > (size_t)m_raw_inode.i_size)
m_raw_inode.i_size = offset + count;
set_metadata_dirty(true);
@@ -824,10 +837,9 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const u8* data, Fi
ssize_t nwritten = 0;
size_t remaining_count = min((off_t)count, (off_t)new_size - offset);
- const u8* in = data;
#ifdef EXT2_DEBUG
- dbg() << "Ext2FS: Writing " << count << " bytes " << offset << " bytes into inode " << identifier() << " from " << (const void*)data;
+ dbg() << "Ext2FS: Writing " << count << " bytes " << offset << " bytes into inode " << identifier() << " from " << data.user_or_kernel_ptr();
#endif
for (size_t bi = first_block_logical_index; remaining_count && bi <= last_block_logical_index; ++bi) {
@@ -836,15 +848,14 @@ ssize_t Ext2FSInode::write_bytes(off_t offset, ssize_t count, const u8* data, Fi
#ifdef EXT2_DEBUG
dbg() << "Ext2FS: Writing block " << m_block_list[bi] << " (offset_into_block: " << offset_into_block << ")";
#endif
- bool success = fs().write_block(m_block_list[bi], in, num_bytes_to_copy, offset_into_block, allow_cache);
- if (!success) {
+ int err = fs().write_block(m_block_list[bi], data.offset(nwritten), num_bytes_to_copy, offset_into_block, allow_cache);
+ if (err < 0) {
dbg() << "Ext2FS: write_block(" << m_block_list[bi] << ") failed (bi: " << bi << ")";
ASSERT_NOT_REACHED();
- return -EIO;
+ return err;
}
remaining_count -= num_bytes_to_copy;
nwritten += num_bytes_to_copy;
- in += num_bytes_to_copy;
}
#ifdef EXT2_DEBUG
@@ -958,7 +969,8 @@ bool Ext2FSInode::write_directory(const Vector<Ext2FSDirectoryEntry>& entries)
stream.fill_to_end(0);
- ssize_t nwritten = write_bytes(0, directory_data.size(), directory_data.data(), nullptr);
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(directory_data.data());
+ ssize_t nwritten = write_bytes(0, directory_data.size(), buffer, nullptr);
if (nwritten < 0)
return false;
set_metadata_dirty(true);
@@ -1087,7 +1099,8 @@ bool Ext2FS::write_ext2_inode(unsigned inode, const ext2_inode& e2inode)
unsigned offset;
if (!find_block_containing_inode(inode, block_index, offset))
return false;
- return write_block(block_index, reinterpret_cast<const u8*>(&e2inode), inode_size(), offset);
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>((const u8*)&e2inode));
+ return write_block(block_index, buffer, inode_size(), offset) >= 0;
}
Vector<Ext2FS::BlockIndex> Ext2FS::allocate_blocks(GroupIndex preferred_group_index, size_t count)
@@ -1314,8 +1327,9 @@ Ext2FS::CachedBitmap& Ext2FS::get_bitmap_block(BlockIndex bitmap_block_index)
}
auto block = KBuffer::create_with_size(block_size(), Region::Access::Read | Region::Access::Write, "Ext2FS: Cached bitmap block");
- bool success = read_block(bitmap_block_index, block.data(), block_size());
- ASSERT(success);
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(block.data());
+ int err = read_block(bitmap_block_index, &buffer, block_size());
+ ASSERT(err >= 0);
m_cached_bitmaps.append(make<CachedBitmap>(bitmap_block_index, move(block)));
return *m_cached_bitmaps.last();
}
diff --git a/Kernel/FileSystem/Ext2FileSystem.h b/Kernel/FileSystem/Ext2FileSystem.h
index bdaa3255ca..7d28b84ff2 100644
--- a/Kernel/FileSystem/Ext2FileSystem.h
+++ b/Kernel/FileSystem/Ext2FileSystem.h
@@ -58,12 +58,12 @@ public:
private:
// ^Inode
- virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
+ virtual ssize_t read_bytes(off_t, ssize_t, UserOrKernelBuffer& buffer, FileDescription*) const override;
virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override;
- virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) override;
+ virtual ssize_t write_bytes(off_t, ssize_t, const UserOrKernelBuffer& data, FileDescription*) override;
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override;
virtual KResult add_child(Inode& child, const StringView& name, mode_t) override;
virtual KResult remove_child(const StringView& name) override;
diff --git a/Kernel/FileSystem/FIFO.cpp b/Kernel/FileSystem/FIFO.cpp
index 3f9c1e33a1..2aa6c55cd9 100644
--- a/Kernel/FileSystem/FIFO.cpp
+++ b/Kernel/FileSystem/FIFO.cpp
@@ -145,14 +145,14 @@ bool FIFO::can_write(const FileDescription&, size_t) const
return m_buffer.space_for_writing() || !m_readers;
}
-KResultOr<size_t> FIFO::read(FileDescription&, size_t, u8* buffer, size_t size)
+KResultOr<size_t> FIFO::read(FileDescription&, size_t, UserOrKernelBuffer& buffer, size_t size)
{
if (!m_writers && m_buffer.is_empty())
return 0;
return m_buffer.read(buffer, size);
}
-KResultOr<size_t> FIFO::write(FileDescription&, size_t, const u8* buffer, size_t size)
+KResultOr<size_t> FIFO::write(FileDescription&, size_t, const UserOrKernelBuffer& buffer, size_t size)
{
if (!m_readers) {
Thread::current()->send_signal(SIGPIPE, Process::current());
diff --git a/Kernel/FileSystem/FIFO.h b/Kernel/FileSystem/FIFO.h
index 81b04597f2..8e3a146012 100644
--- a/Kernel/FileSystem/FIFO.h
+++ b/Kernel/FileSystem/FIFO.h
@@ -57,8 +57,8 @@ public:
private:
// ^File
- virtual KResultOr<size_t> write(FileDescription&, size_t, const u8*, size_t) override;
- virtual KResultOr<size_t> read(FileDescription&, size_t, u8*, size_t) override;
+ virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) override;
+ virtual KResultOr<size_t> read(FileDescription&, size_t, UserOrKernelBuffer&, size_t) override;
virtual KResult stat(::stat&) const override;
virtual bool can_read(const FileDescription&, size_t) const override;
virtual bool can_write(const FileDescription&, size_t) const override;
diff --git a/Kernel/FileSystem/File.h b/Kernel/FileSystem/File.h
index 150f04f518..b2400b803b 100644
--- a/Kernel/FileSystem/File.h
+++ b/Kernel/FileSystem/File.h
@@ -34,6 +34,7 @@
#include <Kernel/Forward.h>
#include <Kernel/KResult.h>
#include <Kernel/UnixTypes.h>
+#include <Kernel/UserOrKernelBuffer.h>
#include <Kernel/VirtualAddress.h>
namespace Kernel {
@@ -77,8 +78,8 @@ public:
virtual bool can_read(const FileDescription&, size_t) const = 0;
virtual bool can_write(const FileDescription&, size_t) const = 0;
- virtual KResultOr<size_t> read(FileDescription&, size_t, u8*, size_t) = 0;
- virtual KResultOr<size_t> write(FileDescription&, size_t, const u8*, size_t) = 0;
+ virtual KResultOr<size_t> read(FileDescription&, size_t, UserOrKernelBuffer&, size_t) = 0;
+ virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) = 0;
virtual int ioctl(FileDescription&, unsigned request, FlatPtr arg);
virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared);
virtual KResult stat(::stat&) const { return KResult(-EBADF); }
diff --git a/Kernel/FileSystem/FileDescription.cpp b/Kernel/FileSystem/FileDescription.cpp
index 80153e6225..8c88dfc816 100644
--- a/Kernel/FileSystem/FileDescription.cpp
+++ b/Kernel/FileSystem/FileDescription.cpp
@@ -116,7 +116,7 @@ off_t FileDescription::seek(off_t offset, int whence)
return m_current_offset;
}
-KResultOr<size_t> FileDescription::read(u8* buffer, size_t count)
+KResultOr<size_t> FileDescription::read(UserOrKernelBuffer& buffer, size_t count)
{
LOCKER(m_lock);
Checked<size_t> new_offset = m_current_offset;
@@ -130,7 +130,7 @@ KResultOr<size_t> FileDescription::read(u8* buffer, size_t count)
return nread_or_error;
}
-KResultOr<size_t> FileDescription::write(const u8* data, size_t size)
+KResultOr<size_t> FileDescription::write(const UserOrKernelBuffer& data, size_t size)
{
LOCKER(m_lock);
Checked<size_t> new_offset = m_current_offset;
@@ -162,7 +162,7 @@ KResultOr<KBuffer> FileDescription::read_entire_file()
return m_inode->read_entire(this);
}
-ssize_t FileDescription::get_dir_entries(u8* buffer, ssize_t size)
+ssize_t FileDescription::get_dir_entries(UserOrKernelBuffer& buffer, ssize_t size)
{
LOCKER(m_lock, Lock::Mode::Shared);
if (!is_directory())
@@ -195,7 +195,8 @@ ssize_t FileDescription::get_dir_entries(u8* buffer, ssize_t size)
if (static_cast<size_t>(size) < temp_buffer.size())
return -EINVAL;
- copy_to_user(buffer, temp_buffer.data(), temp_buffer.size());
+ if (!buffer.write(temp_buffer.data(), temp_buffer.size()))
+ return -EFAULT;
return stream.offset();
}
diff --git a/Kernel/FileSystem/FileDescription.h b/Kernel/FileSystem/FileDescription.h
index 3427ad1e18..60d85db945 100644
--- a/Kernel/FileSystem/FileDescription.h
+++ b/Kernel/FileSystem/FileDescription.h
@@ -60,8 +60,8 @@ public:
KResult close();
off_t seek(off_t, int whence);
- KResultOr<size_t> read(u8*, size_t);
- KResultOr<size_t> write(const u8* data, size_t);
+ KResultOr<size_t> read(UserOrKernelBuffer&, size_t);
+ KResultOr<size_t> write(const UserOrKernelBuffer& data, size_t);
KResult stat(::stat&);
KResult chmod(mode_t);
@@ -69,7 +69,7 @@ public:
bool can_read() const;
bool can_write() const;
- ssize_t get_dir_entries(u8* buffer, ssize_t);
+ ssize_t get_dir_entries(UserOrKernelBuffer& buffer, ssize_t);
KResultOr<KBuffer> read_entire_file();
diff --git a/Kernel/FileSystem/FileSystem.h b/Kernel/FileSystem/FileSystem.h
index 19fea4bafd..99a8131ca4 100644
--- a/Kernel/FileSystem/FileSystem.h
+++ b/Kernel/FileSystem/FileSystem.h
@@ -34,6 +34,7 @@
#include <Kernel/KResult.h>
#include <Kernel/Lock.h>
#include <Kernel/UnixTypes.h>
+#include <Kernel/UserOrKernelBuffer.h>
namespace Kernel {
diff --git a/Kernel/FileSystem/Inode.cpp b/Kernel/FileSystem/Inode.cpp
index e78f87bf59..b0e91bafc5 100644
--- a/Kernel/FileSystem/Inode.cpp
+++ b/Kernel/FileSystem/Inode.cpp
@@ -73,7 +73,10 @@ KResultOr<KBuffer> Inode::read_entire(FileDescription* descriptor) const
u8 buffer[4096];
off_t offset = 0;
for (;;) {
- nread = read_bytes(offset, sizeof(buffer), buffer, descriptor);
+ auto buf = UserOrKernelBuffer::for_kernel_buffer(buffer);
+ nread = read_bytes(offset, sizeof(buffer), buf, descriptor);
+ if (nread < 0)
+ return KResult(nread);
ASSERT(nread <= (ssize_t)sizeof(buffer));
if (nread <= 0)
break;
@@ -124,7 +127,7 @@ void Inode::will_be_destroyed()
flush_metadata();
}
-void Inode::inode_contents_changed(off_t offset, ssize_t size, const u8* data)
+void Inode::inode_contents_changed(off_t offset, ssize_t size, const UserOrKernelBuffer& data)
{
if (m_shared_vmobject)
m_shared_vmobject->inode_contents_changed({}, offset, size, data);
diff --git a/Kernel/FileSystem/Inode.h b/Kernel/FileSystem/Inode.h
index f9ed0db158..d506ab0d18 100644
--- a/Kernel/FileSystem/Inode.h
+++ b/Kernel/FileSystem/Inode.h
@@ -69,10 +69,10 @@ public:
KResultOr<KBuffer> read_entire(FileDescription* = nullptr) const;
- virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const = 0;
+ virtual ssize_t read_bytes(off_t, ssize_t, UserOrKernelBuffer& buffer, FileDescription*) const = 0;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const = 0;
virtual RefPtr<Inode> lookup(StringView name) = 0;
- virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) = 0;
+ virtual ssize_t write_bytes(off_t, ssize_t, const UserOrKernelBuffer& data, FileDescription*) = 0;
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) = 0;
virtual KResult add_child(Inode&, const StringView& name, mode_t) = 0;
virtual KResult remove_child(const StringView& name) = 0;
@@ -122,7 +122,7 @@ public:
protected:
Inode(FS& fs, unsigned index);
void set_metadata_dirty(bool);
- void inode_contents_changed(off_t, ssize_t, const u8*);
+ void inode_contents_changed(off_t, ssize_t, const UserOrKernelBuffer&);
void inode_size_changed(size_t old_size, size_t new_size);
KResult prepare_to_write_data();
diff --git a/Kernel/FileSystem/InodeFile.cpp b/Kernel/FileSystem/InodeFile.cpp
index c2657fe969..bc4d243957 100644
--- a/Kernel/FileSystem/InodeFile.cpp
+++ b/Kernel/FileSystem/InodeFile.cpp
@@ -44,7 +44,7 @@ InodeFile::~InodeFile()
{
}
-KResultOr<size_t> InodeFile::read(FileDescription& description, size_t offset, u8* buffer, size_t count)
+KResultOr<size_t> InodeFile::read(FileDescription& description, size_t offset, UserOrKernelBuffer& buffer, size_t count)
{
ssize_t nread = m_inode->read_bytes(offset, count, buffer, &description);
if (nread > 0)
@@ -54,7 +54,7 @@ KResultOr<size_t> InodeFile::read(FileDescription& description, size_t offset, u
return nread;
}
-KResultOr<size_t> InodeFile::write(FileDescription& description, size_t offset, const u8* data, size_t count)
+KResultOr<size_t> InodeFile::write(FileDescription& description, size_t offset, const UserOrKernelBuffer& data, size_t count)
{
ssize_t nwritten = m_inode->write_bytes(offset, count, data, &description);
if (nwritten > 0) {
diff --git a/Kernel/FileSystem/InodeFile.h b/Kernel/FileSystem/InodeFile.h
index ab64201b3b..e051476b2b 100644
--- a/Kernel/FileSystem/InodeFile.h
+++ b/Kernel/FileSystem/InodeFile.h
@@ -47,8 +47,8 @@ public:
virtual bool can_read(const FileDescription&, size_t) const override { return true; }
virtual bool can_write(const FileDescription&, size_t) const override { return true; }
- virtual KResultOr<size_t> read(FileDescription&, size_t, u8*, size_t) override;
- virtual KResultOr<size_t> write(FileDescription&, size_t, const u8*, size_t) override;
+ virtual KResultOr<size_t> read(FileDescription&, size_t, UserOrKernelBuffer&, size_t) override;
+ virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) override;
virtual KResultOr<Region*> mmap(Process&, FileDescription&, VirtualAddress preferred_vaddr, size_t offset, size_t size, int prot, bool shared) override;
virtual String absolute_path(const FileDescription&) const override;
diff --git a/Kernel/FileSystem/InodeWatcher.cpp b/Kernel/FileSystem/InodeWatcher.cpp
index a4612a588d..6e76cc69b6 100644
--- a/Kernel/FileSystem/InodeWatcher.cpp
+++ b/Kernel/FileSystem/InodeWatcher.cpp
@@ -57,7 +57,7 @@ bool InodeWatcher::can_write(const FileDescription&, size_t) const
return true;
}
-KResultOr<size_t> InodeWatcher::read(FileDescription&, size_t, u8* buffer, size_t buffer_size)
+KResultOr<size_t> InodeWatcher::read(FileDescription&, size_t, UserOrKernelBuffer& buffer, size_t buffer_size)
{
LOCKER(m_lock);
ASSERT(!m_queue.is_empty() || !m_inode);
@@ -68,11 +68,17 @@ KResultOr<size_t> InodeWatcher::read(FileDescription&, size_t, u8* buffer, size_
// FIXME: What should we do if the output buffer is too small?
ASSERT(buffer_size >= (int)sizeof(Event));
auto event = m_queue.dequeue();
- memcpy(buffer, &event, sizeof(event));
+ ssize_t nwritten = buffer.write_buffered<sizeof(event)>(sizeof(event), [&](u8* data, size_t data_bytes) {
+ memcpy(data, &event, sizeof(event));
+ return (ssize_t)data_bytes;
+ });
+ if (nwritten < 0)
+ return KResult(nwritten);
+ ASSERT((size_t)nwritten == sizeof(event));
return sizeof(event);
}
-KResultOr<size_t> InodeWatcher::write(FileDescription&, size_t, const u8*, size_t)
+KResultOr<size_t> InodeWatcher::write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t)
{
return KResult(-EIO);
}
diff --git a/Kernel/FileSystem/InodeWatcher.h b/Kernel/FileSystem/InodeWatcher.h
index 31a094b88f..cd371e2f1a 100644
--- a/Kernel/FileSystem/InodeWatcher.h
+++ b/Kernel/FileSystem/InodeWatcher.h
@@ -55,8 +55,8 @@ public:
virtual bool can_read(const FileDescription&, size_t) const override;
virtual bool can_write(const FileDescription&, size_t) const override;
- virtual KResultOr<size_t> read(FileDescription&, size_t, u8*, size_t) override;
- virtual KResultOr<size_t> write(FileDescription&, size_t, const u8*, size_t) override;
+ virtual KResultOr<size_t> read(FileDescription&, size_t, UserOrKernelBuffer&, size_t) override;
+ virtual KResultOr<size_t> write(FileDescription&, size_t, const UserOrKernelBuffer&, size_t) override;
virtual String absolute_path(const FileDescription&) const override;
virtual const char* class_name() const override { return "InodeWatcher"; };
diff --git a/Kernel/FileSystem/Plan9FileSystem.cpp b/Kernel/FileSystem/Plan9FileSystem.cpp
index 952a176066..975883df67 100644
--- a/Kernel/FileSystem/Plan9FileSystem.cpp
+++ b/Kernel/FileSystem/Plan9FileSystem.cpp
@@ -426,7 +426,8 @@ KResult Plan9FS::post_message(Message& message)
if (Thread::current()->block<Thread::WriteBlocker>(nullptr, description).was_interrupted())
return KResult(-EINTR);
}
- auto nwritten_or_error = description.write(data, size);
+ auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>(data));
+ auto nwritten_or_error = description.write(data_buffer, size);
if (nwritten_or_error.is_error())
return nwritten_or_error.error();
auto nwritten = nwritten_or_error.value();
@@ -445,7 +446,8 @@ KResult Plan9FS::do_read(u8* data, size_t size)
if (Thread::current()->block<Thread::ReadBlocker>(nullptr, description).was_interrupted())
return KResult(-EINTR);
}
- auto nread_or_error = description.read(data, size);
+ auto data_buffer = UserOrKernelBuffer::for_kernel_buffer(data);
+ auto nread_or_error = description.read(data_buffer, size);
if (nread_or_error.is_error())
return nread_or_error.error();
auto nread = nread_or_error.value();
@@ -677,7 +679,7 @@ KResult Plan9FSInode::ensure_open_for_mode(int mode)
}
}
-ssize_t Plan9FSInode::read_bytes(off_t offset, ssize_t size, u8* buffer, FileDescription*) const
+ssize_t Plan9FSInode::read_bytes(off_t offset, ssize_t size, UserOrKernelBuffer& buffer, FileDescription*) const
{
auto result = const_cast<Plan9FSInode&>(*this).ensure_open_for_mode(O_RDONLY);
if (result.is_error())
@@ -710,12 +712,13 @@ ssize_t Plan9FSInode::read_bytes(off_t offset, ssize_t size, u8* buffer, FileDes
// Guard against the server returning more data than requested.
size_t nread = min(data.length(), (size_t)size);
- memcpy(buffer, data.characters_without_null_termination(), nread);
+ if (!buffer.write(data.characters_without_null_termination(), nread))
+ return -EFAULT;
return nread;
}
-ssize_t Plan9FSInode::write_bytes(off_t offset, ssize_t size, const u8* data, FileDescription*)
+ssize_t Plan9FSInode::write_bytes(off_t offset, ssize_t size, const UserOrKernelBuffer& data, FileDescription*)
{
auto result = ensure_open_for_mode(O_WRONLY);
if (result.is_error())
@@ -723,9 +726,13 @@ ssize_t Plan9FSInode::write_bytes(off_t offset, ssize_t size, const u8* data, Fi
size = fs().adjust_buffer_size(size);
+ auto data_copy = data.copy_into_string(size); // FIXME: this seems ugly
+ if (data_copy.is_null())
+ return -EFAULT;
+
Plan9FS::Message message { fs(), Plan9FS::Message::Type::Twrite };
message << fid() << (u64)offset;
- message.append_data({ data, (size_t)size });
+ message.append_data(data_copy);
result = fs().post_message_and_wait_for_a_reply(message);
if (result.is_error())
return result.error();
diff --git a/Kernel/FileSystem/Plan9FileSystem.h b/Kernel/FileSystem/Plan9FileSystem.h
index 77af39e47a..5851cbe8dd 100644
--- a/Kernel/FileSystem/Plan9FileSystem.h
+++ b/Kernel/FileSystem/Plan9FileSystem.h
@@ -124,8 +124,8 @@ public:
// ^Inode
virtual InodeMetadata metadata() const override;
virtual void flush_metadata() override;
- virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
- virtual ssize_t write_bytes(off_t, ssize_t, const u8* data, FileDescription*) override;
+ virtual ssize_t read_bytes(off_t, ssize_t, UserOrKernelBuffer& buffer, FileDescription*) const override;
+ virtual ssize_t write_bytes(off_t, ssize_t, const UserOrKernelBuffer& data, FileDescription*) override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override;
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override;
diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp
index 0fe482cf36..eef030b29f 100644
--- a/Kernel/FileSystem/ProcFS.cpp
+++ b/Kernel/FileSystem/ProcFS.cpp
@@ -976,21 +976,33 @@ static ByteBuffer read_sys_bool(InodeIdentifier inode_id)
return buffer;
}
-static ssize_t write_sys_bool(InodeIdentifier inode_id, const ByteBuffer& data)
+static ssize_t write_sys_bool(InodeIdentifier inode_id, const UserOrKernelBuffer& buffer, size_t size)
{
auto& variable = SysVariable::for_inode(inode_id);
ASSERT(variable.type == SysVariable::Type::Boolean);
- if (data.is_empty() || !(data[0] == '0' || data[0] == '1'))
- return data.size();
+ char value = 0;
+ bool did_read = false;
+ ssize_t nread = buffer.read_buffered<1>(1, [&](const u8* data, size_t) {
+ if (did_read)
+ return 0;
+ value = (char)data[0];
+ did_read = true;
+ return 1;
+ });
+ if (nread < 0)
+ return nread;
+ ASSERT(nread == 0 || (nread == 1 && did_read));
+ if (nread == 0 || !(value == '0' || value == '1'))
+ return (ssize_t)size;
auto* lockable_bool = reinterpret_cast<Lockable<bool>*>(variable.address);
{
LOCKER(lockable_bool->lock());
- lockable_bool->resource() = data[0] == '1';
+ lockable_bool->resource() = value == '1';
}
variable.notify();
- return data.size();
+ return (ssize_t)size;
}
static ByteBuffer read_sys_string(InodeIdentifier inode_id)
@@ -1003,18 +1015,22 @@ static ByteBuffer read_sys_string(InodeIdentifier inode_id)
return lockable_string->resource().to_byte_buffer();
}
-static ssize_t write_sys_string(InodeIdentifier inode_id, const ByteBuffer& data)
+static ssize_t write_sys_string(InodeIdentifier inode_id, const UserOrKernelBuffer& buffer, size_t size)
{
auto& variable = SysVariable::for_inode(inode_id);
ASSERT(variable.type == SysVariable::Type::String);
+ auto string_copy = buffer.copy_into_string(size);
+ if (string_copy.is_null())
+ return -EFAULT;
+
{
auto* lockable_string = reinterpret_cast<Lockable<String>*>(variable.address);
LOCKER(lockable_string->lock());
- lockable_string->resource() = String((const char*)data.data(), data.size());
+ lockable_string->resource() = move(string_copy);
}
variable.notify();
- return data.size();
+ return (ssize_t)size;
}
void ProcFS::add_sys_bool(String&& name, Lockable<bool>& var, Function<void()>&& notify_callback)
@@ -1180,13 +1196,13 @@ InodeMetadata ProcFSInode::metadata() const
return metadata;
}
-ssize_t ProcFSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDescription* description) const
+ssize_t ProcFSInode::read_bytes(off_t offset, ssize_t count, UserOrKernelBuffer& buffer, FileDescription* description) const
{
#ifdef PROCFS_DEBUG
dbg() << "ProcFS: read_bytes " << index();
#endif
ASSERT(offset >= 0);
- ASSERT(buffer);
+ ASSERT(buffer.user_or_kernel_ptr());
auto* directory_entry = fs().get_directory_entry(identifier());
@@ -1240,7 +1256,8 @@ ssize_t ProcFSInode::read_bytes(off_t offset, ssize_t count, u8* buffer, FileDes
return 0;
ssize_t nread = min(static_cast<off_t>(data.value().size() - offset), static_cast<off_t>(count));
- memcpy(buffer, data.value().data() + offset, nread);
+ if (!buffer.write(data.value().data() + offset, nread))
+ return -EFAULT;
if (nread == 0 && description && description->generator_cache().has_value())
description->generator_cache().clear();
@@ -1461,7 +1478,7 @@ void ProcFSInode::flush_metadata()
{
}
-ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, FileDescription*)
+ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const UserOrKernelBuffer& buffer, FileDescription*)
{
auto result = prepare_to_write_data();
if (result.is_error())
@@ -1469,8 +1486,8 @@ ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, F
auto* directory_entry = fs().get_directory_entry(identifier());
- Function<ssize_t(InodeIdentifier, const ByteBuffer&)> callback_tmp;
- Function<ssize_t(InodeIdentifier, const ByteBuffer&)>* write_callback { nullptr };
+ Function<ssize_t(InodeIdentifier, const UserOrKernelBuffer&, size_t)> callback_tmp;
+ Function<ssize_t(InodeIdentifier, const UserOrKernelBuffer&, size_t)>* write_callback { nullptr };
if (directory_entry == nullptr) {
if (to_proc_parent_directory(identifier()) == PDI_Root_sys) {
@@ -1496,9 +1513,10 @@ ssize_t ProcFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, F
ASSERT(is_persistent_inode(identifier()));
// FIXME: Being able to write into ProcFS at a non-zero offset seems like something we should maybe support..
ASSERT(offset == 0);
- bool success = (*write_callback)(identifier(), ByteBuffer::wrap(const_cast<u8*>(buffer), size));
- ASSERT(success);
- return 0;
+ ssize_t nwritten = (*write_callback)(identifier(), buffer, (size_t)size);
+ if (nwritten < 0)
+ klog() << "ProcFS: Writing " << size << " bytes failed: " << nwritten;
+ return nwritten;
}
KResultOr<NonnullRefPtr<Custody>> ProcFSInode::resolve_as_link(Custody& base, RefPtr<Custody>* out_parent, int options, int symlink_recursion_level) const
diff --git a/Kernel/FileSystem/ProcFS.h b/Kernel/FileSystem/ProcFS.h
index a68df543f0..5d2d3fb124 100644
--- a/Kernel/FileSystem/ProcFS.h
+++ b/Kernel/FileSystem/ProcFS.h
@@ -59,7 +59,7 @@ private:
struct ProcFSDirectoryEntry {
ProcFSDirectoryEntry() { }
- ProcFSDirectoryEntry(const char* a_name, unsigned a_proc_file_type, bool a_supervisor_only, Function<Optional<KBuffer>(InodeIdentifier)>&& a_read_callback = nullptr, Function<ssize_t(InodeIdentifier, const ByteBuffer&)>&& a_write_callback = nullptr, RefPtr<ProcFSInode>&& a_inode = nullptr)
+ ProcFSDirectoryEntry(const char* a_name, unsigned a_proc_file_type, bool a_supervisor_only, Function<Optional<KBuffer>(InodeIdentifier)>&& a_read_callback = nullptr, Function<ssize_t(InodeIdentifier, const UserOrKernelBuffer&, size_t)>&& a_write_callback = nullptr, RefPtr<ProcFSInode>&& a_inode = nullptr)
: name(a_name)
, proc_file_type(a_proc_file_type)
, supervisor_only(a_supervisor_only)
@@ -73,7 +73,7 @@ private:
unsigned proc_file_type { 0 };
bool supervisor_only { false };
Function<Optional<KBuffer>(InodeIdentifier)> read_callback;
- Function<ssize_t(InodeIdentifier, const ByteBuffer&)> write_callback;
+ Function<ssize_t(InodeIdentifier, const UserOrKernelBuffer&, size_t)> write_callback;
RefPtr<ProcFSInode> inode;
InodeIdentifier identifier(unsigned fsid) const;
};
@@ -96,12 +96,12 @@ public:
private:
// ^Inode
- virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
+ virtual ssize_t read_bytes(off_t, ssize_t, UserOrKernelBuffer& buffer, FileDescription*) const override;
virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override;
- virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;
+ virtual ssize_t write_bytes(off_t, ssize_t, const UserOrKernelBuffer& buffer, FileDescription*) override;
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override;
virtual KResult add_child(Inode&, const StringView& name, mode_t) override;
virtual KResult remove_child(const StringView& name) override;
@@ -123,12 +123,12 @@ public:
private:
// ^Inode
- virtual ssize_t read_bytes(off_t, ssize_t, u8*, FileDescription*) const override { ASSERT_NOT_REACHED(); }
+ virtual ssize_t read_bytes(off_t, ssize_t, UserOrKernelBuffer&, FileDescription*) const override { ASSERT_NOT_REACHED(); }
virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override { ASSERT_NOT_REACHED(); }
virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override {};
- virtual ssize_t write_bytes(off_t, ssize_t, const u8*, FileDescription*) override { ASSERT_NOT_REACHED(); }
+ virtual ssize_t write_bytes(off_t, ssize_t, const UserOrKernelBuffer&, FileDescription*) override { ASSERT_NOT_REACHED(); }
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override;
virtual KResult add_child(Inode&, const StringView& name, mode_t) override;
virtual KResult remove_child(const StringView& name) override;
diff --git a/Kernel/FileSystem/TmpFS.cpp b/Kernel/FileSystem/TmpFS.cpp
index 04ac98d33d..31222d6e87 100644
--- a/Kernel/FileSystem/TmpFS.cpp
+++ b/Kernel/FileSystem/TmpFS.cpp
@@ -141,7 +141,7 @@ KResult TmpFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntry
return KSuccess;
}
-ssize_t TmpFSInode::read_bytes(off_t offset, ssize_t size, u8* buffer, FileDescription*) const
+ssize_t TmpFSInode::read_bytes(off_t offset, ssize_t size, UserOrKernelBuffer& buffer, FileDescription*) const
{
LOCKER(m_lock, Lock::Mode::Shared);
ASSERT(!is_directory());
@@ -157,11 +157,12 @@ ssize_t TmpFSInode::read_bytes(off_t offset, ssize_t size, u8* buffer, FileDescr
if (static_cast<off_t>(size) > m_metadata.size - offset)
size = m_metadata.size - offset;
- memcpy(buffer, m_content.value().data() + offset, size);
+ if (!buffer.write(m_content.value().data() + offset, size))
+ return -EFAULT;
return size;
}
-ssize_t TmpFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, FileDescription*)
+ssize_t TmpFSInode::write_bytes(off_t offset, ssize_t size, const UserOrKernelBuffer& buffer, FileDescription*)
{
LOCKER(m_lock);
ASSERT(!is_directory());
@@ -199,7 +200,8 @@ ssize_t TmpFSInode::write_bytes(off_t offset, ssize_t size, const u8* buffer, Fi
inode_size_changed(old_size, new_size);
}
- memcpy(m_content.value().data() + offset, buffer, size);
+ if (!buffer.read(m_content.value().data() + offset, size)) // TODO: partial reads?
+ return -EFAULT;
inode_contents_changed(offset, size, buffer);
return size;
@@ -343,8 +345,10 @@ KResult TmpFSInode::truncate(u64 size)
if (old_size != (size_t)size) {
inode_size_changed(old_size, size);
- if (m_content.has_value())
- inode_contents_changed(0, size, m_content.value().data());
+ if (m_content.has_value()) {
+ auto buffer = UserOrKernelBuffer::for_kernel_buffer(m_content.value().data());
+ inode_contents_changed(0, size, buffer);
+ }
}
return KSuccess;
diff --git a/Kernel/FileSystem/TmpFS.h b/Kernel/FileSystem/TmpFS.h
index bb77e6b946..02eed3f17f 100644
--- a/Kernel/FileSystem/TmpFS.h
+++ b/Kernel/FileSystem/TmpFS.h
@@ -74,12 +74,12 @@ public:
const TmpFS& fs() const { return static_cast<const TmpFS&>(Inode::fs()); }
// ^Inode
- virtual ssize_t read_bytes(off_t, ssize_t, u8* buffer, FileDescription*) const override;
+ virtual ssize_t read_bytes(off_t, ssize_t, UserOrKernelBuffer& buffer, FileDescription*) const override;
virtual InodeMetadata metadata() const override;
virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override;
virtual RefPtr<Inode> lookup(StringView name) override;
virtual void flush_metadata() override;
- virtual ssize_t write_bytes(off_t, ssize_t, const u8* buffer, FileDescription*) override;
+ virtual ssize_t write_bytes(off_t, ssize_t, const UserOrKernelBuffer& buffer, FileDescription*) override;
virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override;
virtual KResult add_child(Inode&, const StringView& name, mode_t) override;
virtual KResult remove_child(const StringView& name) override;
diff --git a/Kernel/FileSystem/VirtualFileSystem.cpp b/Kernel/FileSystem/VirtualFileSystem.cpp
index ea06d462c3..c0c93dfecb 100644
--- a/Kernel/FileSystem/VirtualFileSystem.cpp
+++ b/Kernel/FileSystem/VirtualFileSystem.cpp
@@ -707,7 +707,8 @@ KResult VFS::symlink(StringView target, StringView linkpath, Custody& base)
if (inode_or_error.is_error())
return inode_or_error.error();
auto& inode = inode_or_error.value();
- ssize_t nwritten = inode->write_bytes(0, target.length(), (const u8*)target.characters_without_null_termination(), nullptr);
+ auto target_buffer = UserOrKernelBuffer::for_kernel_buffer(const_cast<u8*>((const u8*)target.characters_without_null_termination()));
+ ssize_t nwritten = inode->write_bytes(0, target.length(), target_buffer, nullptr);
if (nwritten < 0)
return KResult(nwritten);
return KSuccess;