From 2ec3aaf6395e2f6ab919df5a768226ee0967c6ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Wed, 20 Mar 2019 11:46:34 +0100 Subject: [PATCH] file_system_session: add modification time * add modification_time member * add WRITE_TIMESTAMP packet --- .../file_system_session/file_system_session.h | 65 ++++++++++++++++--- repos/os/src/server/ram_fs/directory.h | 1 + repos/os/src/server/ram_fs/file.h | 3 +- repos/os/src/server/ram_fs/main.cc | 12 ++++ repos/os/src/server/ram_fs/node.h | 14 +++- repos/os/src/server/ram_fs/symlink.h | 1 + 6 files changed, 84 insertions(+), 12 deletions(-) diff --git a/repos/os/include/file_system_session/file_system_session.h b/repos/os/include/file_system_session/file_system_session.h index 5c8ba3b08..55ace3dcd 100644 --- a/repos/os/include/file_system_session/file_system_session.h +++ b/repos/os/include/file_system_session/file_system_session.h @@ -71,6 +71,26 @@ namespace File_system { typedef Genode::uint64_t seek_off_t; typedef Genode::uint64_t file_size_t; + struct Timestamp + { + /* + * The INVALID value is used whenever the underlying file system + * session does not support modification timestamps. The value is + * chosen such that it is unlikely to occur, instead of simply '0', + * which would correspond to plausible time (see comment below). + * This allows for handling this case explicitly. In any case, an + * invalid timestamp should not be used for doing any calculations. + */ + static constexpr Genode::int64_t INVALID = 0x7fffffffffffffffLL; + + /* + * The 'value' member contains the modification timestamp in seconds. + * Value '0' is defined as 1970-01-01T00:00:00Z, where a positive value + * covers all seconds after this date and a negative one all before. + */ + Genode::int64_t value; + }; + typedef Genode::Out_of_ram Out_of_ram; typedef Genode::Out_of_caps Out_of_caps; @@ -127,6 +147,7 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor enum Opcode { READ, WRITE, + WRITE_TIMESTAMP, CONTENT_CHANGED, READ_READY, @@ -143,9 +164,16 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor Node_handle _handle { 0 }; /* node handle */ Opcode _op; /* requested operation */ - seek_off_t _position; /* file seek offset in bytes */ - size_t _length; /* transaction length in bytes */ bool _success; /* indicates success of operation */ + union + { + struct + { + seek_off_t _position; /* file seek offset in bytes */ + size_t _length; /* transaction length in bytes */ + }; + Timestamp _modification_time; /* seconds since the Unix epoch */ + }; public: @@ -156,7 +184,7 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor Genode::size_t buf_size = 0) : Genode::Packet_descriptor(buf_offset, buf_size), - _op(READ), _position(0), _length(0), _success(false) { } + _op(READ), _success(false), _position(0), _length(0) { } /** * Constructor @@ -172,8 +200,8 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor seek_off_t position = SEEK_TAIL) : Genode::Packet_descriptor(p.offset(), p.size()), - _handle(handle), _op(op), - _position(position), _length(length), _success(false) + _handle(handle), _op(op), _success(false), + _position(position), _length(length) { } /** @@ -185,16 +213,33 @@ class File_system::Packet_descriptor : public Genode::Packet_descriptor Packet_descriptor(Node_handle handle, Opcode op) : Genode::Packet_descriptor(0, 0), - _handle(handle), _op(op), - _position(0), _length(0), _success(true) + _handle(handle), _op(op), _success(true), + _position(0), _length(0) + { } + + /** + * Constructor + */ + Packet_descriptor(Packet_descriptor p, Node_handle handle, Opcode op, Timestamp const &mtime) + : + Genode::Packet_descriptor(p.offset(), p.size()), + _handle(handle), _op(op), _success(false), + _modification_time(mtime) { } Node_handle handle() const { return _handle; } Opcode operation() const { return _op; } - seek_off_t position() const { return _position; } - size_t length() const { return _length; } + seek_off_t position() const { return _op != Opcode::WRITE_TIMESTAMP ? _position : 0; } + size_t length() const { return _op != Opcode::WRITE_TIMESTAMP ? _length : 0; } bool succeeded() const { return _success; } + template + void with_timestamp(FN const &fn) const + { + if (_op == Opcode::WRITE_TIMESTAMP) + fn(_modification_time); + } + /* * Accessors called at the server side */ @@ -212,13 +257,13 @@ struct File_system::Status }; /* - * XXX add access time * XXX add executable bit */ file_size_t size; unsigned mode; unsigned long inode; + Timestamp modification_time; /** * Return true if node is a directory diff --git a/repos/os/src/server/ram_fs/directory.h b/repos/os/src/server/ram_fs/directory.h index 349d718d0..eca6f9513 100644 --- a/repos/os/src/server/ram_fs/directory.h +++ b/repos/os/src/server/ram_fs/directory.h @@ -228,6 +228,7 @@ class Ram_fs::Directory : public Node s.inode = inode(); s.size = _num_entries * sizeof(File_system::Directory_entry); s.mode = File_system::Status::MODE_DIRECTORY; + s.modification_time = modification_time(); return s; } }; diff --git a/repos/os/src/server/ram_fs/file.h b/repos/os/src/server/ram_fs/file.h index e7df3cd4c..0f339560c 100644 --- a/repos/os/src/server/ram_fs/file.h +++ b/repos/os/src/server/ram_fs/file.h @@ -112,10 +112,11 @@ class Ram_fs::File : public Node Status status() override { - Status s; + Status s { }; s.inode = inode(); s.size = _length; s.mode = File_system::Status::MODE_FILE; + s.modification_time = modification_time(); return s; } diff --git a/repos/os/src/server/ram_fs/main.cc b/repos/os/src/server/ram_fs/main.cc index e4dc1a8d2..f7e744d8b 100644 --- a/repos/os/src/server/ram_fs/main.cc +++ b/repos/os/src/server/ram_fs/main.cc @@ -108,6 +108,18 @@ class Ram_fs::Session_component : public File_system::Session_rpc_object open_node.mark_as_written(); break; + case Packet_descriptor::WRITE_TIMESTAMP: { + Locked_ptr node { open_node.node() }; + if (!node.valid()) + break; + + packet.with_timestamp([&] (File_system::Timestamp const time) { + node->update_modification_time(time); + succeeded = true; + }); + break; + } + case Packet_descriptor::CONTENT_CHANGED: Genode::error("CONTENT_CHANGED packets from clients have no effect"); return; diff --git a/repos/os/src/server/ram_fs/node.h b/repos/os/src/server/ram_fs/node.h index 6ccd1af32..e2905f270 100644 --- a/repos/os/src/server/ram_fs/node.h +++ b/repos/os/src/server/ram_fs/node.h @@ -23,6 +23,7 @@ namespace Ram_fs { using namespace Genode; using File_system::seek_off_t; using File_system::Status; + using File_system::Timestamp; class Node; class File; class Symlink; @@ -48,6 +49,7 @@ class Ram_fs::Node : public File_system::Node_base, int _ref_count; Name _name; unsigned long const _inode; + Timestamp _modification_time { }; /** * Generate unique inode number @@ -62,7 +64,10 @@ class Ram_fs::Node : public File_system::Node_base, Node() : _ref_count(0), _inode(_unique_inode()) - { _name[0] = 0; } + { + _name[0] = 0; + _modification_time.value = File_system::Timestamp::INVALID; + } virtual ~Node() { lock_for_destruction(); } @@ -74,6 +79,13 @@ class Ram_fs::Node : public File_system::Node_base, */ void name(char const *name) { strncpy(_name, name, sizeof(_name)); } + void update_modification_time(Timestamp const time) + { + _modification_time = time; + } + + Timestamp modification_time() const { return _modification_time; } + virtual size_t read(char *dst, size_t len, seek_off_t) = 0; virtual size_t write(char const *src, size_t len, seek_off_t) = 0; diff --git a/repos/os/src/server/ram_fs/symlink.h b/repos/os/src/server/ram_fs/symlink.h index ef3376238..0f830bc70 100644 --- a/repos/os/src/server/ram_fs/symlink.h +++ b/repos/os/src/server/ram_fs/symlink.h @@ -71,6 +71,7 @@ class Ram_fs::Symlink : public Node s.inode = inode(); s.size = _len; s.mode = File_system::Status::MODE_SYMLINK; + s.modification_time = modification_time(); return s; } };