Sfoglia il codice sorgente

Add sync() syscall and a /bin/sync.

It walks all the live Inode objects and flushes pending metadata changes
wherever needed.

This could be optimized by keeping a separate list of dirty Inodes,
but let's not get ahead of ourselves.
Andreas Kling 6 anni fa
parent
commit
ed7ae6c02c

+ 0 - 1
Kernel/Process.cpp

@@ -1105,7 +1105,6 @@ int Process::sys$utime(const char* pathname, const Unix::utimbuf* buf)
     }
     }
     inode.set_atime(atime);
     inode.set_atime(atime);
     inode.set_mtime(mtime);
     inode.set_mtime(mtime);
-    inode.flush_metadata();
     return 0;
     return 0;
 }
 }
 
 

+ 8 - 0
Kernel/Syscall.cpp

@@ -44,6 +44,12 @@ void initialize()
     kprintf("syscall: int 0x80 handler installed\n");
     kprintf("syscall: int 0x80 handler installed\n");
 }
 }
 
 
+static int sync()
+{
+    VFS::the().sync();
+    return 0;
+}
+
 static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, dword arg3)
 static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2, dword arg3)
 {
 {
     ASSERT_INTERRUPTS_ENABLED();
     ASSERT_INTERRUPTS_ENABLED();
@@ -179,6 +185,8 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
         return current->sys$times((Unix::tms*)arg1);
         return current->sys$times((Unix::tms*)arg1);
     case Syscall::SC_utime:
     case Syscall::SC_utime:
         return current->sys$utime((const char*)arg1, (const Unix::utimbuf*)arg2);
         return current->sys$utime((const char*)arg1, (const Unix::utimbuf*)arg2);
+    case Syscall::SC_sync:
+        return sync();
     default:
     default:
         kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
         kprintf("<%u> int0x80: Unknown function %u requested {%x, %x, %x}\n", current->pid(), function, arg1, arg2, arg3);
         break;
         break;

+ 1 - 0
Kernel/Syscall.h

@@ -65,6 +65,7 @@
     __ENUMERATE_SYSCALL(mkdir) \
     __ENUMERATE_SYSCALL(mkdir) \
     __ENUMERATE_SYSCALL(times) \
     __ENUMERATE_SYSCALL(times) \
     __ENUMERATE_SYSCALL(utime) \
     __ENUMERATE_SYSCALL(utime) \
+    __ENUMERATE_SYSCALL(sync) \
 
 
 
 
 #define DO_SYSCALL_A0(function) Syscall::invoke((dword)(function))
 #define DO_SYSCALL_A0(function) Syscall::invoke((dword)(function))

+ 1 - 2
Kernel/sync.sh

@@ -23,14 +23,13 @@ cp -v ../Userland/cat mnt/bin/cat
 cp -v ../Userland/uname mnt/bin/uname
 cp -v ../Userland/uname mnt/bin/uname
 cp -v ../Userland/clear mnt/bin/clear
 cp -v ../Userland/clear mnt/bin/clear
 cp -v ../Userland/tst mnt/bin/tst
 cp -v ../Userland/tst mnt/bin/tst
-cp -v ../Userland/ft mnt/bin/ft
-cp -v ../Userland/ft2 mnt/bin/ft2
 cp -v ../Userland/mm mnt/bin/mm
 cp -v ../Userland/mm mnt/bin/mm
 cp -v ../Userland/kill mnt/bin/kill
 cp -v ../Userland/kill mnt/bin/kill
 cp -v ../Userland/tty mnt/bin/tty
 cp -v ../Userland/tty mnt/bin/tty
 cp -v ../Userland/strsignal mnt/bin/strsignal
 cp -v ../Userland/strsignal mnt/bin/strsignal
 cp -v ../Userland/mkdir mnt/bin/mkdir
 cp -v ../Userland/mkdir mnt/bin/mkdir
 cp -v ../Userland/touch mnt/bin/touch
 cp -v ../Userland/touch mnt/bin/touch
+cp -v ../Userland/sync mnt/bin/sync
 sh sync-local.sh
 sh sync-local.sh
 cp -v kernel.map mnt/
 cp -v kernel.map mnt/
 ln -s dir_a mnt/dir_cur
 ln -s dir_a mnt/dir_cur

+ 5 - 0
LibC/unistd.cpp

@@ -294,4 +294,9 @@ void _exit(int status)
     assert(false);
     assert(false);
 }
 }
 
 
+void sync()
+{
+    Syscall::invoke(Syscall::SC_sync);
+}
+
 }
 }

+ 1 - 0
LibC/unistd.h

@@ -11,6 +11,7 @@ extern char** environ;
 inline int getpagesize() { return 4096; }
 inline int getpagesize() { return 4096; }
 pid_t fork();
 pid_t fork();
 int execve(const char* filename, const char** argv, const char** envp);
 int execve(const char* filename, const char** argv, const char** envp);
+void sync();
 void _exit(int status);
 void _exit(int status);
 pid_t getsid(pid_t);
 pid_t getsid(pid_t);
 pid_t setsid();
 pid_t setsid();

+ 1 - 0
Userland/.gitignore

@@ -22,3 +22,4 @@ strsignal
 fgrep
 fgrep
 mkdir
 mkdir
 touch
 touch
+sync

+ 5 - 1
Userland/Makefile

@@ -44,7 +44,8 @@ APPS = \
        fgrep \
        fgrep \
        tty \
        tty \
        mkdir \
        mkdir \
-       touch
+       touch \
+       sync
 
 
 ARCH_FLAGS =
 ARCH_FLAGS =
 STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
 STANDARD_FLAGS = -std=c++17 -nostdinc++ -nostdlib -nostdinc
@@ -130,6 +131,9 @@ mkdir: mkdir.o
 touch: touch.o
 touch: touch.o
 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
 
 
+sync: sync.o
+	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
+
 .cpp.o:
 .cpp.o:
 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
 
 

+ 8 - 0
Userland/sync.cpp

@@ -0,0 +1,8 @@
+#include <stdio.h>
+#include <unistd.h>
+
+int main(int, char**)
+{
+    sync();
+    return 0;
+}

+ 1 - 0
VirtualFileSystem/Ext2FileSystem.cpp

@@ -306,6 +306,7 @@ void Ext2FSInode::populate_metadata() const
 
 
 void Ext2FSInode::flush_metadata()
 void Ext2FSInode::flush_metadata()
 {
 {
+    dbgprintf("Ext2FSInode: flush_metadata for inode %u\n", index());
     m_raw_inode.i_size = m_metadata.size;
     m_raw_inode.i_size = m_metadata.size;
     m_raw_inode.i_mode = m_metadata.mode;
     m_raw_inode.i_mode = m_metadata.mode;
     m_raw_inode.i_uid = m_metadata.uid;
     m_raw_inode.i_uid = m_metadata.uid;

+ 35 - 10
VirtualFileSystem/FileSystem.cpp

@@ -4,36 +4,45 @@
 #include "FileSystem.h"
 #include "FileSystem.h"
 
 
 static dword s_lastFileSystemID;
 static dword s_lastFileSystemID;
-static HashMap<dword, FS*>* map;
+static HashMap<dword, FS*>* s_fs_map;
+static HashTable<Inode*>* s_inode_set;
 
 
-static HashMap<dword, FS*>& fileSystems()
+static HashMap<dword, FS*>& all_fses()
 {
 {
-    if (!map)
-        map = new HashMap<dword, FS*>();
-    return *map;
+    if (!s_fs_map)
+        s_fs_map = new HashMap<dword, FS*>();
+    return *s_fs_map;
+}
+
+static HashTable<Inode*>& all_inodes()
+{
+    if (!s_inode_set)
+        s_inode_set = new HashTable<Inode*>();
+    return *s_inode_set;
 }
 }
 
 
 void FS::initializeGlobals()
 void FS::initializeGlobals()
 {
 {
     s_lastFileSystemID = 0;
     s_lastFileSystemID = 0;
-    map = 0;
+    s_fs_map = nullptr;
+    s_inode_set = nullptr;
 }
 }
 
 
 FS::FS()
 FS::FS()
     : m_fsid(++s_lastFileSystemID)
     : m_fsid(++s_lastFileSystemID)
 {
 {
-    fileSystems().set(m_fsid, this);
+    all_fses().set(m_fsid, this);
 }
 }
 
 
 FS::~FS()
 FS::~FS()
 {
 {
-    fileSystems().remove(m_fsid);
+    all_fses().remove(m_fsid);
 }
 }
 
 
 FS* FS::from_fsid(dword id)
 FS* FS::from_fsid(dword id)
 {
 {
-    auto it = fileSystems().find(id);
-    if (it != fileSystems().end())
+    auto it = all_fses().find(id);
+    if (it != all_fses().end())
         return (*it).value;
         return (*it).value;
     return nullptr;
     return nullptr;
 }
 }
@@ -125,8 +134,16 @@ FS::DirectoryEntry::DirectoryEntry(const char* n, size_t nl, InodeIdentifier i,
     name[nl] = '\0';
     name[nl] = '\0';
 }
 }
 
 
+Inode::Inode(FS& fs, unsigned index)
+    : m_fs(fs)
+    , m_index(index)
+{
+    all_inodes().set(this);
+}
+
 Inode::~Inode()
 Inode::~Inode()
 {
 {
+    all_inodes().remove(this);
 }
 }
 
 
 void Inode::will_be_destroyed()
 void Inode::will_be_destroyed()
@@ -167,3 +184,11 @@ int Inode::set_mtime(Unix::time_t ts)
     m_metadata_dirty = true;
     m_metadata_dirty = true;
     return 0;
     return 0;
 }
 }
+
+void FS::sync()
+{
+    for (auto* inode : all_inodes()) {
+        if (inode->is_metadata_dirty())
+            inode->flush_metadata();
+    }
+}

+ 2 - 5
VirtualFileSystem/FileSystem.h

@@ -26,6 +26,7 @@ public:
 
 
     dword id() const { return m_fsid; }
     dword id() const { return m_fsid; }
     static FS* from_fsid(dword);
     static FS* from_fsid(dword);
+    static void sync();
 
 
     virtual bool initialize() = 0;
     virtual bool initialize() = 0;
     virtual const char* class_name() const = 0;
     virtual const char* class_name() const = 0;
@@ -98,11 +99,7 @@ public:
     void will_be_destroyed();
     void will_be_destroyed();
 
 
 protected:
 protected:
-    Inode(FS& fs, unsigned index)
-        : m_fs(fs)
-        , m_index(index)
-    {
-    }
+    Inode(FS& fs, unsigned index);
 
 
     virtual void populate_metadata() const = 0;
     virtual void populate_metadata() const = 0;
     void set_metadata_dirty(bool b) { m_metadata_dirty = b; }
     void set_metadata_dirty(bool b) { m_metadata_dirty = b; }

+ 8 - 5
VirtualFileSystem/VirtualFileSystem.cpp

@@ -47,13 +47,11 @@ VFS::~VFS()
 
 
 auto VFS::makeNode(InodeIdentifier inode) -> RetainPtr<Vnode>
 auto VFS::makeNode(InodeIdentifier inode) -> RetainPtr<Vnode>
 {
 {
-    auto metadata = inode.metadata();
-    if (!metadata.isValid())
+    auto core_inode = inode.fs()->get_inode(inode);
+    if (!core_inode)
         return nullptr;
         return nullptr;
 
 
-    auto core_inode = inode.fs()->get_inode(inode);
-    if (core_inode)
-        core_inode->m_metadata = metadata;
+    auto& metadata = core_inode->metadata();
 
 
     InterruptDisabler disabler;
     InterruptDisabler disabler;
 
 
@@ -501,3 +499,8 @@ void VFS::for_each_mount(Function<void(const Mount&)> callback) const
         callback(*mount);
         callback(*mount);
     }
     }
 }
 }
+
+void VFS::sync()
+{
+    FS::sync();
+}

+ 2 - 0
VirtualFileSystem/VirtualFileSystem.h

@@ -123,6 +123,8 @@ public:
 
 
     InodeIdentifier root_inode_id() const;
     InodeIdentifier root_inode_id() const;
 
 
+    void sync();
+
 private:
 private:
     friend class FileDescriptor;
     friend class FileDescriptor;
     friend class Vnode;
     friend class Vnode;