mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-16 07:27:35 +00:00
os: increase mtime resolution to milliseconds
This patch changes the 'Timestamp' type of the VFS and file-system session to an unsigned 64-bit value holding the number of milliseconds since the UNIX epoch (beginning of 1970). The special case of an invalid timestamp has been removed as it was never consistently handled anyway. In contrast to the POSIX timespec, which represents tv_sec and tv_nsec both as signed values, this patch uses an unsigned value because the interpretation of negative tv_sec and tv_nsec values is muddy. Hypothetical modification times older that 1970 are capped at 1970. Fixes #3511
This commit is contained in:
parent
5cfe44ab72
commit
05d69a0bb3
@ -171,8 +171,13 @@ class Vfs::Rump_file_system : public File_system
|
||||
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 }
|
||||
{
|
||||
.tv_sec = 0,
|
||||
.tv_nsec = 0
|
||||
}, {
|
||||
.tv_sec = time_t( time.ms_since_1970 / 1000),
|
||||
.tv_nsec = time_t((time.ms_since_1970 % 1000)*1000*1000)
|
||||
}
|
||||
};
|
||||
|
||||
/* silently igore error */
|
||||
@ -726,7 +731,9 @@ class Vfs::Rump_file_system : public File_system
|
||||
.inode = sb.st_ino,
|
||||
.device = sb.st_dev,
|
||||
|
||||
.modification_time = { sb.st_mtim.tv_sec }
|
||||
.modification_time = {
|
||||
.ms_since_1970 = uint64_t(sb.st_mtim.tv_sec*1000 +
|
||||
sb.st_mtim.tv_nsec/1000000) }
|
||||
};
|
||||
|
||||
return STAT_OK;
|
||||
|
@ -118,6 +118,10 @@ static void vfs_stat_to_libc_stat_struct(Vfs::Directory_service::Stat const &src
|
||||
|
||||
*dst = { };
|
||||
|
||||
timespec const mtime {
|
||||
.tv_sec = time_t( src.modification_time.ms_since_1970 / 1000),
|
||||
.tv_nsec = time_t((src.modification_time.ms_since_1970 % 1000)*1000*1000) };
|
||||
|
||||
dst->st_uid = 0;
|
||||
dst->st_gid = 0;
|
||||
dst->st_mode = (src.rwx.readable ? readable_bits : 0)
|
||||
@ -129,8 +133,7 @@ static void vfs_stat_to_libc_stat_struct(Vfs::Directory_service::Stat const &src
|
||||
dst->st_blocks = (dst->st_size + FS_BLOCK_SIZE - 1) / FS_BLOCK_SIZE;
|
||||
dst->st_ino = src.inode;
|
||||
dst->st_dev = src.device;
|
||||
long long mtime = src.modification_time.value;
|
||||
dst->st_mtime = mtime != Vfs::Timestamp::INVALID ? mtime : 0;
|
||||
dst->st_mtim = mtime;
|
||||
dst->st_nlink = 1;
|
||||
}
|
||||
|
||||
@ -546,7 +549,7 @@ struct Sync
|
||||
enum { INITIAL, TIMESTAMP_UPDATED, QUEUED, COMPLETE } state { INITIAL };
|
||||
|
||||
Vfs::Vfs_handle &vfs_handle;
|
||||
Vfs::Timestamp mtime { Vfs::Timestamp::INVALID };
|
||||
Vfs::Timestamp mtime { };
|
||||
|
||||
Sync(Vfs::Vfs_handle &vfs_handle, Libc::Vfs_plugin::Update_mtime update_mtime,
|
||||
Libc::Current_real_time ¤t_real_time)
|
||||
@ -561,7 +564,9 @@ struct Sync
|
||||
} else {
|
||||
timespec const ts = current_real_time.current_real_time();
|
||||
|
||||
mtime = { .value = (long long)ts.tv_sec };
|
||||
mtime.ms_since_1970 = ts.tv_sec >= 0
|
||||
? ts.tv_sec*1000ull + ts.tv_nsec/1000000ull
|
||||
: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,25 +86,7 @@ namespace File_system {
|
||||
using seek_off_t = Genode::uint64_t;
|
||||
using file_size_t = Genode::uint64_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;
|
||||
};
|
||||
struct Timestamp { Genode::uint64_t ms_since_1970; };
|
||||
|
||||
using Out_of_ram = Genode::Out_of_ram;
|
||||
using Out_of_caps = Genode::Out_of_caps;
|
||||
|
@ -451,7 +451,7 @@ class Vfs::Dir_file_system : public File_system
|
||||
.rwx = Node_rwx::rwx(),
|
||||
.inode = 1,
|
||||
.device = (Genode::addr_t)this,
|
||||
.modification_time = { Vfs::Timestamp::INVALID },
|
||||
.modification_time = { },
|
||||
};
|
||||
return STAT_OK;
|
||||
}
|
||||
|
@ -50,11 +50,7 @@ namespace Vfs {
|
||||
using Genode::Byte_range_ptr;
|
||||
using Genode::Const_byte_range_ptr;
|
||||
|
||||
struct Timestamp
|
||||
{
|
||||
static constexpr Genode::int64_t INVALID = 0x7fffffffffffffffLL;
|
||||
Genode::int64_t value;
|
||||
};
|
||||
struct Timestamp { Genode::uint64_t ms_since_1970; };
|
||||
|
||||
enum class Node_type {
|
||||
DIRECTORY,
|
||||
|
@ -300,7 +300,8 @@ class Vfs::Fs_file_system : public File_system, private Remote_io
|
||||
Packet_descriptor p(source.alloc_packet(0),
|
||||
file_handle(),
|
||||
Packet_descriptor::WRITE_TIMESTAMP,
|
||||
::File_system::Timestamp { .value = time.value });
|
||||
::File_system::Timestamp {
|
||||
.ms_since_1970 = time.ms_since_1970 });
|
||||
|
||||
_vfs_fs._submit_packet(p);
|
||||
} catch (::File_system::Session::Tx::Source::Packet_alloc_failed) {
|
||||
@ -617,7 +618,8 @@ class Vfs::Fs_file_system : public File_system, private Remote_io
|
||||
out.rwx = _node_rwx(status.rwx);
|
||||
out.inode = status.inode;
|
||||
out.device = (Genode::addr_t)this;
|
||||
out.modification_time.value = status.modification_time.value;
|
||||
out.modification_time = {
|
||||
.ms_since_1970 = status.modification_time.ms_since_1970 };
|
||||
|
||||
return STAT_OK;
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ class Vfs_ram::Node : private Genode::Avl_node<Node>
|
||||
return ++inode_count;
|
||||
}
|
||||
|
||||
Vfs::Timestamp _modification_time { Vfs::Timestamp::INVALID };
|
||||
Vfs::Timestamp _modification_time { };
|
||||
|
||||
bool _marked_as_unlinked = false;
|
||||
|
||||
|
@ -626,6 +626,11 @@ class Vfs::Tar_file_system : public File_system
|
||||
return Node_type::DIRECTORY;
|
||||
};
|
||||
|
||||
auto timestamp_from_mtime = [] (auto mtime) -> Timestamp
|
||||
{
|
||||
return { .ms_since_1970 = mtime >= 0 ? Genode::uint64_t(mtime*1000) : 0 };
|
||||
};
|
||||
|
||||
out = {
|
||||
.size = record.size(),
|
||||
.type = node_type(),
|
||||
@ -634,7 +639,7 @@ class Vfs::Tar_file_system : public File_system
|
||||
.executable = record.rwx().executable },
|
||||
.inode = (Genode::addr_t)node_ptr,
|
||||
.device = (Genode::addr_t)this,
|
||||
.modification_time = { record.mtime() }
|
||||
.modification_time = timestamp_from_mtime(record.mtime())
|
||||
};
|
||||
|
||||
return STAT_OK;
|
||||
|
@ -116,10 +116,7 @@ class Lx_fs::Directory : public Node
|
||||
|
||||
void update_modification_time(Timestamp const time) override
|
||||
{
|
||||
struct timespec ts[2] = {
|
||||
{ .tv_sec = (time_t)0, .tv_nsec = 0 },
|
||||
{ .tv_sec = (time_t)time.value, .tv_nsec = 0 }
|
||||
};
|
||||
struct timespec ts[2] = { { }, timespec_from_timestamp(time) };
|
||||
|
||||
/* silently ignore errors */
|
||||
futimens(dirfd(_fd), (const timespec*)&ts);
|
||||
@ -258,7 +255,7 @@ class Lx_fs::Directory : public Node
|
||||
.writeable = (st.st_mode & S_IWUSR) != 0,
|
||||
.executable = (st.st_mode & S_IXUSR) != 0},
|
||||
.inode = (unsigned long)inode(),
|
||||
.modification_time = { st.st_mtime }
|
||||
.modification_time = timestamp_from_timespec(st.st_mtim)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -114,10 +114,7 @@ class Lx_fs::File : public Node
|
||||
|
||||
void update_modification_time(Timestamp const time) override
|
||||
{
|
||||
struct timespec ts[2] = {
|
||||
{ .tv_sec = (time_t)0, .tv_nsec = 0 },
|
||||
{ .tv_sec = (time_t)time.value, .tv_nsec = 0 }
|
||||
};
|
||||
struct timespec ts[2] = { { }, timespec_from_timestamp(time) };
|
||||
|
||||
/* silently ignore errors */
|
||||
futimens(_fd, (const timespec*)&ts);
|
||||
@ -167,7 +164,7 @@ class Lx_fs::File : public Node
|
||||
.writeable = (st.st_mode & S_IWUSR) != 0,
|
||||
.executable = (st.st_mode & S_IXUSR) != 0},
|
||||
.inode = (unsigned long)inode(),
|
||||
.modification_time = { st.st_mtime }
|
||||
.modification_time = timestamp_from_timespec(st.st_mtim)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,17 @@ namespace Lx_fs {
|
||||
*
|
||||
*/
|
||||
Path_string absolute_root_dir(char const *root_path);
|
||||
|
||||
static inline timespec timespec_from_timestamp(File_system::Timestamp t)
|
||||
{
|
||||
return { .tv_sec = time_t (t.ms_since_1970 * 1000),
|
||||
.tv_nsec = time_t((t.ms_since_1970 % 1000)*1000*1000) };
|
||||
}
|
||||
|
||||
static inline File_system::Timestamp timestamp_from_timespec(timespec ts)
|
||||
{
|
||||
return { .ms_since_1970 = Genode::uint64_t(ts.tv_sec*1000 + ts.tv_nsec/1000000) };
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _LX_UTIL_H_ */
|
||||
|
@ -684,7 +684,8 @@ class Vfs_server::Session_component : private Session_resources,
|
||||
.executable = vfs_stat.rwx.executable },
|
||||
|
||||
.inode = vfs_stat.inode,
|
||||
.modification_time = { vfs_stat.modification_time.value }
|
||||
.modification_time = {
|
||||
.ms_since_1970 = vfs_stat.modification_time.ms_since_1970 }
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -447,7 +447,7 @@ class Vfs_server::Io_node : public Vfs_server::Node,
|
||||
void _execute_write_timestamp()
|
||||
{
|
||||
_packet.with_timestamp([&] (::File_system::Timestamp const time) {
|
||||
Vfs::Timestamp ts { .value = time.value };
|
||||
Vfs::Timestamp ts { .ms_since_1970 = time.ms_since_1970 };
|
||||
_handle.fs().update_modification_timestamp(&_handle, ts);
|
||||
});
|
||||
_acknowledge_as_success(0);
|
||||
|
Loading…
x
Reference in New Issue
Block a user