From 9a82bbb54d0b35d1f533f74bfdb32ad80b7eb4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Wed, 20 Mar 2019 15:01:34 +0100 Subject: [PATCH] vfs: add modification time member to directory_service Issue #1784. --- repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc | 19 ++++++++ repos/os/include/vfs/dir_file_system.h | 1 + repos/os/include/vfs/directory_service.h | 1 + repos/os/include/vfs/file_io_service.h | 14 ++++++ repos/os/include/vfs/types.h | 6 +++ repos/os/src/lib/vfs/fs_file_system.h | 48 +++++++++++++++++++++ repos/os/src/lib/vfs/ram_file_system.h | 29 ++++++++++++- 7 files changed, 117 insertions(+), 1 deletion(-) diff --git a/repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc b/repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc index 997e37118..d18b529c9 100644 --- a/repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc +++ b/repos/dde_rump/src/lib/vfs/rump/vfs_rump.cc @@ -91,6 +91,8 @@ class Vfs::Rump_file_system : public File_system Genode::error("Rump_vfs_handle::write() called"); return WRITE_ERR_INVALID; } + + virtual void update_modification_timestamp(Vfs::Timestamp) { } }; class Rump_vfs_file_handle : @@ -163,6 +165,17 @@ class Vfs::Rump_file_system : public File_system out_count = n; return WRITE_OK; } + + void update_modification_timestamp(Vfs::Timestamp time) override + { + struct timespec ts[2] = { + { .tv_sec = 0, .tv_nsec = 0 }, + { .tv_sec = time.value, .tv_nsec = 0 } + }; + + /* silently igore error */ + rump_sys_futimens(_fd, (const timespec*)&ts); + } }; class Rump_vfs_dir_handle : public Rump_vfs_handle @@ -806,6 +819,12 @@ class Vfs::Rump_file_system : public File_system _notify_files(); return SYNC_OK; } + + bool update_modification_timestamp(Vfs_handle *vfs_handle, + Vfs::Timestamp ts) + { + return true; + } }; diff --git a/repos/os/include/vfs/dir_file_system.h b/repos/os/include/vfs/dir_file_system.h index 4da5fd47a..d99e94c21 100644 --- a/repos/os/include/vfs/dir_file_system.h +++ b/repos/os/include/vfs/dir_file_system.h @@ -462,6 +462,7 @@ class Vfs::Dir_file_system : public File_system out.gid = 0; out.inode = 1; out.device = (Genode::addr_t)this; + out.modification_time = { Vfs::Timestamp::INVALID }; return STAT_OK; } diff --git a/repos/os/include/vfs/directory_service.h b/repos/os/include/vfs/directory_service.h index b678f4259..155413e57 100644 --- a/repos/os/include/vfs/directory_service.h +++ b/repos/os/include/vfs/directory_service.h @@ -160,6 +160,7 @@ struct Vfs::Directory_service : Interface unsigned gid = 0; unsigned long inode = 0; unsigned long device = 0; + Timestamp modification_time { Timestamp::INVALID }; }; enum Stat_result { STAT_ERR_NO_ENTRY = NUM_GENERAL_ERRORS, diff --git a/repos/os/include/vfs/file_io_service.h b/repos/os/include/vfs/file_io_service.h index 178a74b90..8ff8a5530 100644 --- a/repos/os/include/vfs/file_io_service.h +++ b/repos/os/include/vfs/file_io_service.h @@ -172,6 +172,20 @@ struct Vfs::File_io_service : Interface virtual bool queue_sync(Vfs_handle *) { return true; } virtual Sync_result complete_sync(Vfs_handle *) { return SYNC_OK; } + + /*********************** + ** Modification time ** + ***********************/ + + /** + * Update the modification time of a file + * + * \return true if update attempt was successful + */ + virtual bool update_modification_timestamp(Vfs_handle *, Vfs::Timestamp) + { + return true; + } }; #endif /* _INCLUDE__VFS__FILE_IO_SERVICE_H_ */ diff --git a/repos/os/include/vfs/types.h b/repos/os/include/vfs/types.h index f4f555e89..2dac626c4 100644 --- a/repos/os/include/vfs/types.h +++ b/repos/os/include/vfs/types.h @@ -49,6 +49,12 @@ namespace Vfs { using Genode::Interface; using Genode::String; + struct Timestamp + { + static constexpr long long INVALID = (1LL << 63) + 1; + long long value; + }; + typedef Genode::Path Absolute_path; } diff --git a/repos/os/src/lib/vfs/fs_file_system.h b/repos/os/src/lib/vfs/fs_file_system.h index 8e38b8b92..d0051528c 100644 --- a/repos/os/src/lib/vfs/fs_file_system.h +++ b/repos/os/src/lib/vfs/fs_file_system.h @@ -225,6 +225,35 @@ class Vfs::Fs_file_system : public File_system return result; } + + bool update_modification_timestamp(Vfs::Timestamp time) + { + ::File_system::Session::Tx::Source &source = *_fs.tx(); + using ::File_system::Packet_descriptor; + + if (!source.ready_to_submit()) { + Genode::error(__func__, ":", __LINE__, " Insufficient_buffer"); + return false; + } + + try { + Packet_descriptor p(source.alloc_packet(0), + file_handle(), + Packet_descriptor::WRITE_TIMESTAMP, + ::File_system::Timestamp { .value = time.value }); + + /* pass packet to server side */ + source.submit_packet(p); + } catch (::File_system::Session::Tx::Source::Packet_alloc_failed) { + Genode::error(__func__, ":", __LINE__, " Insufficient_buffer"); + return false; + } catch (...) { + Genode::error("unhandled exception"); + return false; + } + + return true; + } }; struct Fs_vfs_file_handle : Fs_vfs_handle @@ -517,6 +546,10 @@ class Vfs::Fs_file_system : public File_system case Packet_descriptor::CONTENT_CHANGED: /* previously handled */ break; + + case Packet_descriptor::WRITE_TIMESTAMP: + /* previously handled */ + break; } }; @@ -535,6 +568,11 @@ class Vfs::Fs_file_system : public File_system Lock::Guard guard(_lock); source.release_packet(packet); } + + if (packet.operation() == Packet_descriptor::WRITE_TIMESTAMP) { + Lock::Guard guard(_lock); + source.release_packet(packet); + } } } @@ -621,6 +659,7 @@ class Vfs::Fs_file_system : public File_system out.gid = 0; out.inode = status.inode; out.device = (Genode::addr_t)this; + out.modification_time.value = status.modification_time.value; return STAT_OK; } @@ -1011,6 +1050,15 @@ class Vfs::Fs_file_system : public File_system return handle->complete_sync(); } + + bool update_modification_timestamp(Vfs_handle *vfs_handle, Vfs::Timestamp time) override + { + Lock::Guard guard(_lock); + + Fs_vfs_handle *handle = static_cast(vfs_handle); + + return handle->update_modification_timestamp(time); + } }; #endif /* _INCLUDE__VFS__FS_FILE_SYSTEM_H_ */ diff --git a/repos/os/src/lib/vfs/ram_file_system.h b/repos/os/src/lib/vfs/ram_file_system.h index 67260238d..1f6719394 100644 --- a/repos/os/src/lib/vfs/ram_file_system.h +++ b/repos/os/src/lib/vfs/ram_file_system.h @@ -119,6 +119,8 @@ class Vfs_ram::Node : private Genode::Avl_node, private Genode::Lock return ++inode_count; } + Vfs::Timestamp _modification_time { Vfs::Timestamp::INVALID }; + public: using Lock::lock; @@ -127,7 +129,10 @@ class Vfs_ram::Node : private Genode::Avl_node, private Genode::Lock unsigned inode; Node(char const *node_name) - : inode(_unique_inode()) { name(node_name); } + : inode(_unique_inode()) + { + name(node_name); + } virtual ~Node() { } @@ -156,6 +161,14 @@ class Vfs_ram::Node : private Genode::Avl_node, private Genode::Lock void unlink() { inode = 0; } bool unlinked() const { return inode == 0; } + bool update_modification_timestamp(Vfs::Timestamp time) + { + _modification_time = time; + return true; + } + + Vfs::Timestamp modification_time() const { return _modification_time; } + virtual size_t read(char*, size_t, file_size) { Genode::error("Vfs_ram::Node::read() called"); @@ -774,6 +787,7 @@ class Vfs::Ram_file_system : public Vfs::File_system stat.size = node->length(); stat.inode = node->inode; stat.device = (Genode::addr_t)this; + stat.modification_time = node->modification_time(); File *file = dynamic_cast(node); if (file) { @@ -1004,6 +1018,19 @@ class Vfs::Ram_file_system : public Vfs::File_system return SYNC_OK; } + bool update_modification_timestamp(Vfs_handle *vfs_handle, Vfs::Timestamp time) override + { + if ((vfs_handle->status_flags() & OPEN_MODE_ACCMODE) == OPEN_MODE_RDONLY) + return false; + + Vfs_ram::Io_handle *handle = + static_cast(vfs_handle); + handle->modifying = true; + + Vfs_ram::Node::Guard guard(&handle->node); + return handle->node.update_modification_timestamp(time); + } + /*************************** ** File_system interface ** ***************************/