Add basic character device support. Start with null and zero.

This commit is contained in:
Andreas Kling 2018-10-14 02:59:22 +02:00
parent fa3b11ac64
commit 93556d6743
Notes: sideshowbarker 2024-07-19 18:48:27 +09:00
14 changed files with 157 additions and 2 deletions

View file

@ -0,0 +1,7 @@
#include "CharacterDevice.h"
CharacterDevice::~CharacterDevice()
{
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <AK/Types.h>
#include "Limits.h"
class CharacterDevice {
public:
virtual ~CharacterDevice();
virtual ssize_t read(byte* buffer, size_t bufferSize) = 0;
virtual ssize_t write(const byte* buffer, size_t bufferSize) = 0;
protected:
CharacterDevice() { }
};

View file

@ -1,5 +1,6 @@
#include "FileHandle.h"
#include "FileSystem.h"
#include "CharacterDevice.h"
FileHandle::FileHandle(RetainPtr<VirtualFileSystem::Node>&& vnode)
: m_vnode(std::move(vnode))
@ -10,8 +11,15 @@ FileHandle::~FileHandle()
{
}
ByteBuffer FileHandle::read() const
ByteBuffer FileHandle::read()
{
if (m_vnode->isCharacterDevice()) {
auto buffer = ByteBuffer::createUninitialized(1024);
ssize_t nread = m_vnode->characterDevice()->read(buffer.pointer(), buffer.size());
buffer.trim(nread);
return buffer;
}
return m_vnode->fileSystem()->readInode(m_vnode->inode);
}

View file

@ -8,7 +8,7 @@ public:
explicit FileHandle(RetainPtr<VirtualFileSystem::Node>&&);
~FileHandle();
ByteBuffer read() const;
ByteBuffer read();
private:
friend class VirtualFileSystem;

View file

@ -0,0 +1,6 @@
#pragma once
typedef dword size_t;
typedef signed_dword ssize_t;
static const size_t GoodBufferSize = 4096;

View file

@ -20,6 +20,7 @@ VFS_OBJS = \
InodeIdentifier.o \
CharacterDevice.o \
ZeroDevice.o \
NullDevice.o \
test.o
OBJS = $(AK_OBJS) $(VFS_OBJS)

View file

@ -0,0 +1,25 @@
#include "NullDevice.h"
#include "Limits.h"
#include <AK/StdLib.h>
#include <cstring>
#include <cstdio>
NullDevice::NullDevice()
{
}
NullDevice::~NullDevice()
{
}
ssize_t NullDevice::read(byte*, size_t)
{
printf("read from null\n");
return 0;
}
ssize_t NullDevice::write(const byte*, size_t bufferSize)
{
return min(GoodBufferSize, bufferSize);
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "CharacterDevice.h"
class NullDevice final : public CharacterDevice {
public:
NullDevice();
virtual ~NullDevice();
ssize_t read(byte* buffer, size_t bufferSize) override;
ssize_t write(const byte* buffer, size_t bufferSize) override;
};

View file

@ -7,6 +7,11 @@
//#define VFS_DEBUG
static dword encodedDevice(unsigned major, unsigned minor)
{
return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
}
VirtualFileSystem::VirtualFileSystem()
{
m_maxNodeCount = 16;
@ -28,6 +33,17 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr<Node>
if (!metadata.isValid())
return nullptr;
CharacterDevice* characterDevice = nullptr;
if (metadata.isCharacterDevice()) {
auto it = m_characterDevices.find(encodedDevice(metadata.majorDevice, metadata.minorDevice));
if (it != m_characterDevices.end()) {
characterDevice = (*it).value;
} else {
printf("[VFS] makeNode() no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice);
return nullptr;
}
}
auto vnode = allocateNode();
ASSERT(vnode);
@ -41,6 +57,7 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr<Node>
#endif
m_inode2vnode.set(inode, vnode.ptr());
vnode->m_characterDevice = characterDevice;
return vnode;
}
@ -118,6 +135,7 @@ void VirtualFileSystem::freeNode(Node* node)
m_inode2vnode.remove(node->inode);
node->inode.fileSystem()->release();
node->inode = InodeIdentifier();
node->m_characterDevice = nullptr;
m_nodeFreeList.append(std::move(node));
}
@ -415,3 +433,7 @@ VirtualFileSystem::Mount::Mount(InodeIdentifier host, RetainPtr<FileSystem>&& gu
{
}
void VirtualFileSystem::registerCharacterDevice(unsigned major, unsigned minor, CharacterDevice& device)
{
m_characterDevices.set(encodedDevice(major, minor), &device);
}

View file

@ -7,6 +7,7 @@
#include <AK/Vector.h>
#include "InodeIdentifier.h"
class CharacterDevice;
class FileHandle;
class FileSystem;
@ -17,6 +18,9 @@ public:
bool inUse() const { return inode.isValid(); }
bool isCharacterDevice() const { return m_characterDevice; }
CharacterDevice* characterDevice() { return m_characterDevice; }
void retain();
void release();
@ -27,6 +31,7 @@ public:
friend class VirtualFileSystem;
VirtualFileSystem* vfs { nullptr };
unsigned retainCount { 0 };
CharacterDevice* m_characterDevice { nullptr };
};
VirtualFileSystem();
@ -52,6 +57,8 @@ public:
bool touch(const String&path);
void registerCharacterDevice(unsigned major, unsigned minor, CharacterDevice&);
private:
template<typename F> void enumerateDirectoryInode(InodeIdentifier, F func);
InodeIdentifier resolvePath(const String& path);
@ -80,6 +87,7 @@ private:
Mount* findMountForGuest(InodeIdentifier);
HashMap<InodeIdentifier, Node*> m_inode2vnode;
HashMap<dword, Node*> m_device2vnode;
Vector<OwnPtr<Mount>> m_mounts;
@ -89,5 +97,7 @@ private:
Vector<Node*> m_nodeFreeList;
RetainPtr<Node> m_rootNode;
HashMap<dword, CharacterDevice*> m_characterDevices;
};

View file

@ -0,0 +1,27 @@
#include "ZeroDevice.h"
#include "Limits.h"
#include <AK/StdLib.h>
#include <cstring>
#include <cstdio>
ZeroDevice::ZeroDevice()
{
}
ZeroDevice::~ZeroDevice()
{
}
ssize_t ZeroDevice::read(byte* buffer, size_t bufferSize)
{
printf("read from zero device\n");
size_t count = min(GoodBufferSize, bufferSize);
memset(buffer, 0, count);
return count;
}
ssize_t ZeroDevice::write(const byte*, size_t bufferSize)
{
return min(GoodBufferSize, bufferSize);
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "CharacterDevice.h"
class ZeroDevice final : public CharacterDevice {
public:
ZeroDevice();
virtual ~ZeroDevice();
ssize_t read(byte* buffer, size_t bufferSize) override;
ssize_t write(const byte* buffer, size_t bufferSize) override;
};

Binary file not shown.

View file

@ -3,6 +3,8 @@
#include "VirtualFileSystem.h"
#include "FileHandle.h"
#include "SyntheticFileSystem.h"
#include "ZeroDevice.h"
#include "NullDevice.h"
#include <cstring>
#include <AK/SimpleMalloc.h>
#include <AK/kmalloc.h>
@ -17,6 +19,12 @@ int main(int c, char** v)
VirtualFileSystem vfs;
auto zero = make<ZeroDevice>();
vfs.registerCharacterDevice(1, 5, *zero);
auto null = make<NullDevice>();
vfs.registerCharacterDevice(1, 3, *null);
if (!vfs.mountRoot(makeFileSystem(filename))) {
printf("Failed to mount root :(\n");
return 1;