mirror of
https://github.com/RGBCube/serenity
synced 2025-07-10 09:17:34 +00:00
Reworked Inode to have a dirty bit and subclass-implemented flush_metadata().
This way we can defer disk writes as long as we like. There's no automatic flushing happening just yet.
This commit is contained in:
parent
d506c857ab
commit
1f44cd9dd9
11 changed files with 82 additions and 58 deletions
|
@ -1090,6 +1090,9 @@ int Process::sys$utime(const char* pathname, const Unix::utimbuf* buf)
|
||||||
auto descriptor = VFS::the().open(move(path), error, 0, cwd_inode()->identifier());
|
auto descriptor = VFS::the().open(move(path), error, 0, cwd_inode()->identifier());
|
||||||
if (!descriptor)
|
if (!descriptor)
|
||||||
return error;
|
return error;
|
||||||
|
auto& inode = *descriptor->inode();
|
||||||
|
if (inode.fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
Unix::time_t atime;
|
Unix::time_t atime;
|
||||||
Unix::time_t mtime;
|
Unix::time_t mtime;
|
||||||
if (buf) {
|
if (buf) {
|
||||||
|
@ -1100,7 +1103,10 @@ int Process::sys$utime(const char* pathname, const Unix::utimbuf* buf)
|
||||||
mtime = now;
|
mtime = now;
|
||||||
atime = now;
|
atime = now;
|
||||||
}
|
}
|
||||||
return descriptor->set_atime_and_mtime(atime, mtime);
|
inode.set_atime(atime);
|
||||||
|
inode.set_mtime(atime);
|
||||||
|
inode.flush_metadata();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Process::sys$access(const char* pathname, int mode)
|
int Process::sys$access(const char* pathname, int mode)
|
||||||
|
|
|
@ -304,6 +304,21 @@ void Ext2FSInode::populate_metadata() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ext2FSInode::flush_metadata()
|
||||||
|
{
|
||||||
|
m_raw_inode.i_size = m_metadata.size;
|
||||||
|
m_raw_inode.i_mode = m_metadata.mode;
|
||||||
|
m_raw_inode.i_uid = m_metadata.uid;
|
||||||
|
m_raw_inode.i_gid = m_metadata.gid;
|
||||||
|
m_raw_inode.i_links_count = m_metadata.linkCount;
|
||||||
|
m_raw_inode.i_atime = m_metadata.atime;
|
||||||
|
m_raw_inode.i_ctime = m_metadata.ctime;
|
||||||
|
m_raw_inode.i_mtime = m_metadata.mtime;
|
||||||
|
m_raw_inode.i_dtime = m_metadata.dtime;
|
||||||
|
m_raw_inode.i_blocks = m_metadata.blockCount;
|
||||||
|
fs().write_ext2_inode(index(), m_raw_inode);
|
||||||
|
}
|
||||||
|
|
||||||
RetainPtr<Inode> Ext2FS::get_inode(InodeIdentifier inode) const
|
RetainPtr<Inode> Ext2FS::get_inode(InodeIdentifier inode) const
|
||||||
{
|
{
|
||||||
ASSERT(inode.fsid() == id());
|
ASSERT(inode.fsid() == id());
|
||||||
|
@ -716,22 +731,6 @@ bool Ext2FS::modify_link_count(InodeIndex inode, int delta)
|
||||||
return write_ext2_inode(inode, *e2inode);
|
return write_ext2_inode(inode, *e2inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Ext2FS::set_atime_and_mtime(InodeIdentifier inode, dword atime, dword mtime)
|
|
||||||
{
|
|
||||||
ASSERT(inode.fsid() == id());
|
|
||||||
|
|
||||||
auto e2inode = lookup_ext2_inode(inode.index());
|
|
||||||
if (!e2inode)
|
|
||||||
return -EIO;
|
|
||||||
|
|
||||||
dbgprintf("changing inode %u atime from %u to %u\n", inode.index(), e2inode->i_atime, atime);
|
|
||||||
dbgprintf("changing inode %u mtime from %u to %u\n", inode.index(), e2inode->i_mtime, mtime);
|
|
||||||
e2inode->i_mtime = mtime;
|
|
||||||
e2inode->i_atime = atime;
|
|
||||||
|
|
||||||
return write_ext2_inode(inode.index(), *e2inode);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Ext2FS::write_ext2_inode(unsigned inode, const ext2_inode& e2inode)
|
bool Ext2FS::write_ext2_inode(unsigned inode, const ext2_inode& e2inode)
|
||||||
{
|
{
|
||||||
unsigned blockIndex;
|
unsigned blockIndex;
|
||||||
|
|
|
@ -21,12 +21,13 @@ public:
|
||||||
bool is_symlink() const { return isSymbolicLink(m_raw_inode.i_mode); }
|
bool is_symlink() const { return isSymbolicLink(m_raw_inode.i_mode); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^CoreInode
|
// ^Inode
|
||||||
virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override;
|
virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override;
|
||||||
virtual void populate_metadata() const override;
|
virtual void populate_metadata() const override;
|
||||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) override;
|
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) override;
|
||||||
virtual InodeIdentifier lookup(const String& name) override;
|
virtual InodeIdentifier lookup(const String& name) override;
|
||||||
virtual String reverse_lookup(InodeIdentifier) override;
|
virtual String reverse_lookup(InodeIdentifier) override;
|
||||||
|
virtual void flush_metadata() override;
|
||||||
|
|
||||||
void populate_lookup_cache();
|
void populate_lookup_cache();
|
||||||
|
|
||||||
|
@ -72,7 +73,6 @@ private:
|
||||||
virtual InodeIdentifier root_inode() const override;
|
virtual InodeIdentifier root_inode() const override;
|
||||||
virtual bool write_inode(InodeIdentifier, const ByteBuffer&) override;
|
virtual bool write_inode(InodeIdentifier, const ByteBuffer&) override;
|
||||||
virtual InodeMetadata inode_metadata(InodeIdentifier) const override;
|
virtual InodeMetadata inode_metadata(InodeIdentifier) const override;
|
||||||
virtual int set_atime_and_mtime(InodeIdentifier, dword atime, dword mtime) override;
|
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) override;
|
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) override;
|
||||||
virtual ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, size_t count, byte* buffer, FileDescriptor*) const override;
|
virtual ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, size_t count, byte* buffer, FileDescriptor*) const override;
|
||||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) override;
|
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) override;
|
||||||
|
|
|
@ -143,7 +143,7 @@ ssize_t FileDescriptor::read(byte* buffer, size_t count)
|
||||||
// FIXME: What should happen to m_currentOffset?
|
// FIXME: What should happen to m_currentOffset?
|
||||||
return m_vnode->characterDevice()->read(buffer, count);
|
return m_vnode->characterDevice()->read(buffer, count);
|
||||||
}
|
}
|
||||||
ssize_t nread = m_vnode->fileSystem()->read_inode_bytes(m_vnode->inode, m_current_offset, count, buffer, this);
|
ssize_t nread = m_vnode->fs()->read_inode_bytes(m_vnode->inode, m_current_offset, count, buffer, this);
|
||||||
m_current_offset += nread;
|
m_current_offset += nread;
|
||||||
return nread;
|
return nread;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ ByteBuffer FileDescriptor::read_entire_file()
|
||||||
|
|
||||||
if (m_vnode->core_inode())
|
if (m_vnode->core_inode())
|
||||||
return m_vnode->core_inode()->read_entire(this);
|
return m_vnode->core_inode()->read_entire(this);
|
||||||
return m_vnode->fileSystem()->read_entire_inode(m_vnode->inode, this);
|
return m_vnode->fs()->read_entire_inode(m_vnode->inode, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileDescriptor::is_directory() const
|
bool FileDescriptor::is_directory() const
|
||||||
|
@ -288,17 +288,3 @@ FileDescriptor::FileDescriptor(FIFO& fifo, FIFO::Direction direction)
|
||||||
{
|
{
|
||||||
m_fifo->open(direction);
|
m_fifo->open(direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
int FileDescriptor::set_atime_and_mtime(time_t atime, time_t mtime)
|
|
||||||
{
|
|
||||||
if (!m_vnode || !m_vnode->core_inode())
|
|
||||||
return -EBADF;
|
|
||||||
return m_vnode->core_inode()->set_atime_and_mtime(atime, mtime);
|
|
||||||
}
|
|
||||||
|
|
||||||
int FileDescriptor::set_ctime(time_t ctime)
|
|
||||||
{
|
|
||||||
(void) ctime;
|
|
||||||
// FIXME: Implement.
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
InodeMetadata metadata() const { return m_vnode->metadata(); }
|
InodeMetadata metadata() const { return m_vnode->metadata(); }
|
||||||
|
|
||||||
Vnode* vnode() { return m_vnode.ptr(); }
|
Vnode* vnode() { return m_vnode.ptr(); }
|
||||||
|
Inode* inode() { return m_vnode ? m_vnode->core_inode() : nullptr; }
|
||||||
|
|
||||||
#ifdef SERENITY
|
#ifdef SERENITY
|
||||||
bool is_blocking() const { return m_is_blocking; }
|
bool is_blocking() const { return m_is_blocking; }
|
||||||
|
@ -64,9 +65,6 @@ public:
|
||||||
|
|
||||||
ByteBuffer& generator_cache() { return m_generator_cache; }
|
ByteBuffer& generator_cache() { return m_generator_cache; }
|
||||||
|
|
||||||
int set_atime_and_mtime(time_t, time_t);
|
|
||||||
int set_ctime(time_t);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class VFS;
|
friend class VFS;
|
||||||
explicit FileDescriptor(RetainPtr<Vnode>&&);
|
explicit FileDescriptor(RetainPtr<Vnode>&&);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#include <AK/Assertions.h>
|
#include <AK/Assertions.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
|
#include <LibC/errno_numbers.h>
|
||||||
#include "FileSystem.h"
|
#include "FileSystem.h"
|
||||||
|
|
||||||
static dword s_lastFileSystemID;
|
static dword s_lastFileSystemID;
|
||||||
|
@ -60,7 +61,7 @@ ByteBuffer Inode::read_entire(FileDescriptor* descriptor)
|
||||||
ASSERT(offset <= (ssize_t)initial_size); // FIXME: Support dynamically growing the buffer.
|
ASSERT(offset <= (ssize_t)initial_size); // FIXME: Support dynamically growing the buffer.
|
||||||
}
|
}
|
||||||
if (nread < 0) {
|
if (nread < 0) {
|
||||||
kprintf("CoreInode::read_entire: ERROR: %d\n", nread);
|
kprintf("Inode::read_entire: ERROR: %d\n", nread);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,7 +129,35 @@ Inode::~Inode()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int Inode::set_atime_and_mtime(Unix::time_t atime, Unix::time_t mtime)
|
int Inode::set_atime(Unix::time_t ts)
|
||||||
{
|
{
|
||||||
return fs().set_atime_and_mtime(identifier(), atime, mtime);
|
if (fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
|
if (m_metadata.atime == ts)
|
||||||
|
return 0;
|
||||||
|
m_metadata.atime = ts;
|
||||||
|
m_dirty = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inode::set_ctime(Unix::time_t ts)
|
||||||
|
{
|
||||||
|
if (fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
|
if (m_metadata.ctime == ts)
|
||||||
|
return 0;
|
||||||
|
m_metadata.ctime = ts;
|
||||||
|
m_dirty = true;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Inode::set_mtime(Unix::time_t ts)
|
||||||
|
{
|
||||||
|
if (fs().is_readonly())
|
||||||
|
return -EROFS;
|
||||||
|
if (m_metadata.mtime == ts)
|
||||||
|
return 0;
|
||||||
|
m_metadata.mtime = ts;
|
||||||
|
m_dirty = true;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,8 @@ public:
|
||||||
|
|
||||||
virtual ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, size_t count, byte* buffer, FileDescriptor*) const = 0;
|
virtual ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, size_t count, byte* buffer, FileDescriptor*) const = 0;
|
||||||
|
|
||||||
|
bool is_readonly() const { return m_readonly; }
|
||||||
|
|
||||||
struct DirectoryEntry {
|
struct DirectoryEntry {
|
||||||
DirectoryEntry(const char* name, InodeIdentifier, byte fileType);
|
DirectoryEntry(const char* name, InodeIdentifier, byte fileType);
|
||||||
DirectoryEntry(const char* name, size_t name_length, InodeIdentifier, byte fileType);
|
DirectoryEntry(const char* name, size_t name_length, InodeIdentifier, byte fileType);
|
||||||
|
@ -44,7 +46,6 @@ public:
|
||||||
byte fileType { 0 };
|
byte fileType { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual int set_atime_and_mtime(InodeIdentifier, dword atime, dword mtime) = 0;
|
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) = 0;
|
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) = 0;
|
||||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) = 0;
|
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) = 0;
|
||||||
|
|
||||||
|
@ -59,6 +60,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
dword m_fsid { 0 };
|
dword m_fsid { 0 };
|
||||||
|
bool m_readonly { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
class Inode : public Retainable<Inode> {
|
class Inode : public Retainable<Inode> {
|
||||||
|
@ -85,7 +87,13 @@ public:
|
||||||
virtual InodeIdentifier lookup(const String& name) = 0;
|
virtual InodeIdentifier lookup(const String& name) = 0;
|
||||||
virtual String reverse_lookup(InodeIdentifier) = 0;
|
virtual String reverse_lookup(InodeIdentifier) = 0;
|
||||||
|
|
||||||
int set_atime_and_mtime(Unix::time_t atime, Unix::time_t mtime);
|
bool is_dirty() const { return m_dirty; }
|
||||||
|
|
||||||
|
int set_atime(Unix::time_t);
|
||||||
|
int set_ctime(Unix::time_t);
|
||||||
|
int set_mtime(Unix::time_t);
|
||||||
|
|
||||||
|
virtual void flush_metadata() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Inode(FS& fs, unsigned index)
|
Inode(FS& fs, unsigned index)
|
||||||
|
@ -95,11 +103,13 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void populate_metadata() const = 0;
|
virtual void populate_metadata() const = 0;
|
||||||
|
void set_dirty(bool b) { m_dirty = b; }
|
||||||
|
|
||||||
mutable InodeMetadata m_metadata;
|
mutable InodeMetadata m_metadata;
|
||||||
private:
|
private:
|
||||||
FS& m_fs;
|
FS& m_fs;
|
||||||
unsigned m_index { 0 };
|
unsigned m_index { 0 };
|
||||||
|
bool m_dirty { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
inline FS* InodeIdentifier::fs()
|
inline FS* InodeIdentifier::fs()
|
||||||
|
|
|
@ -146,14 +146,6 @@ InodeMetadata SynthFS::inode_metadata(InodeIdentifier inode) const
|
||||||
return (*it).value->m_metadata;
|
return (*it).value->m_metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SynthFS::set_atime_and_mtime(InodeIdentifier, dword atime, dword mtime)
|
|
||||||
{
|
|
||||||
(void) atime;
|
|
||||||
(void) mtime;
|
|
||||||
kprintf("FIXME: Implement SyntheticFileSystem::setModificationTime().\n");
|
|
||||||
return -ENOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
InodeIdentifier SynthFS::create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, unsigned size, int& error)
|
InodeIdentifier SynthFS::create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t mode, unsigned size, int& error)
|
||||||
{
|
{
|
||||||
(void) parentInode;
|
(void) parentInode;
|
||||||
|
@ -318,3 +310,7 @@ String SynthFSInode::reverse_lookup(InodeIdentifier child_id)
|
||||||
}
|
}
|
||||||
return { };
|
return { };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SynthFSInode::flush_metadata()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ public:
|
||||||
virtual InodeIdentifier root_inode() const override;
|
virtual InodeIdentifier root_inode() const override;
|
||||||
virtual bool write_inode(InodeIdentifier, const ByteBuffer&) override;
|
virtual bool write_inode(InodeIdentifier, const ByteBuffer&) override;
|
||||||
virtual InodeMetadata inode_metadata(InodeIdentifier) const override;
|
virtual InodeMetadata inode_metadata(InodeIdentifier) const override;
|
||||||
virtual int set_atime_and_mtime(InodeIdentifier, dword atime, dword mtime) override;
|
|
||||||
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) override;
|
virtual InodeIdentifier create_inode(InodeIdentifier parentInode, const String& name, Unix::mode_t, unsigned size, int& error) override;
|
||||||
virtual ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, size_t count, byte* buffer, FileDescriptor*) const override;
|
virtual ssize_t read_inode_bytes(InodeIdentifier, Unix::off_t offset, size_t count, byte* buffer, FileDescriptor*) const override;
|
||||||
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) override;
|
virtual InodeIdentifier create_directory(InodeIdentifier parentInode, const String& name, Unix::mode_t, int& error) override;
|
||||||
|
@ -49,12 +48,13 @@ public:
|
||||||
virtual ~SynthFSInode() override;
|
virtual ~SynthFSInode() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// ^CoreInode
|
// ^Inode
|
||||||
virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override;
|
virtual ssize_t read_bytes(Unix::off_t, size_t, byte* buffer, FileDescriptor*) override;
|
||||||
virtual void populate_metadata() const override;
|
virtual void populate_metadata() const override;
|
||||||
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) override;
|
virtual bool traverse_as_directory(Function<bool(const FS::DirectoryEntry&)>) override;
|
||||||
virtual InodeIdentifier lookup(const String& name) override;
|
virtual InodeIdentifier lookup(const String& name) override;
|
||||||
virtual String reverse_lookup(InodeIdentifier) override;
|
virtual String reverse_lookup(InodeIdentifier) override;
|
||||||
|
virtual void flush_metadata() override;
|
||||||
|
|
||||||
SynthFS& fs();
|
SynthFS& fs();
|
||||||
const SynthFS& fs() const;
|
const SynthFS& fs() const;
|
||||||
|
|
|
@ -170,8 +170,8 @@ bool VFS::mount_root(RetainPtr<FS>&& fileSystem)
|
||||||
m_root_vnode = move(node);
|
m_root_vnode = move(node);
|
||||||
|
|
||||||
kprintf("VFS: mounted root on %s{%p}\n",
|
kprintf("VFS: mounted root on %s{%p}\n",
|
||||||
m_root_vnode->fileSystem()->class_name(),
|
m_root_vnode->fs()->class_name(),
|
||||||
m_root_vnode->fileSystem());
|
m_root_vnode->fs());
|
||||||
|
|
||||||
m_mounts.append(move(mount));
|
m_mounts.append(move(mount));
|
||||||
return true;
|
return true;
|
||||||
|
@ -278,7 +278,7 @@ RetainPtr<FileDescriptor> VFS::create(const String& path, InodeIdentifier base,
|
||||||
// FIXME: Do the real thing, not just this fake thing!
|
// FIXME: Do the real thing, not just this fake thing!
|
||||||
(void) path;
|
(void) path;
|
||||||
(void) base;
|
(void) base;
|
||||||
m_root_vnode->fileSystem()->create_inode(m_root_vnode->fileSystem()->root_inode(), "empty", 0100644, 0, error);
|
m_root_vnode->fs()->create_inode(m_root_vnode->fs()->root_inode(), "empty", 0100644, 0, error);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,8 +49,8 @@ public:
|
||||||
void retain();
|
void retain();
|
||||||
void release();
|
void release();
|
||||||
|
|
||||||
FS* fileSystem() { return inode.fs(); }
|
FS* fs() { return inode.fs(); }
|
||||||
const FS* fileSystem() const { return inode.fs(); }
|
const FS* fs() const { return inode.fs(); }
|
||||||
|
|
||||||
VFS* vfs() { return m_vfs; }
|
VFS* vfs() { return m_vfs; }
|
||||||
const VFS* vfs() const { return m_vfs; }
|
const VFS* vfs() const { return m_vfs; }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue