mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-11 21:37:58 +03:00
Kernel: Update atime/ctime/mtime timestamps atomically
Instead of having three separate APIs (one for each timestamp), there's now only Inode::update_timestamps() and it takes 3x optional timestamps. The non-empty timestamps are updated while holding the inode mutex, and the outside world no longer has to look at intermediate timestamp states.
This commit is contained in:
parent
35b2e9c663
commit
280694bb46
Notes:
sideshowbarker
2024-07-17 08:03:52 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/280694bb46
@ -1537,34 +1537,23 @@ ErrorOr<NonnullLockRefPtr<Inode>> Ext2FSInode::lookup(StringView name)
|
||||
return fs().get_inode({ fsid(), inode_index });
|
||||
}
|
||||
|
||||
ErrorOr<void> Ext2FSInode::set_atime(time_t t)
|
||||
ErrorOr<void> Ext2FSInode::update_timestamps(Optional<time_t> atime, Optional<time_t> ctime, Optional<time_t> mtime)
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
if (fs().is_readonly())
|
||||
return EROFS;
|
||||
if (t > INT32_MAX)
|
||||
if (atime.value_or(0) > INT32_MAX)
|
||||
return EINVAL;
|
||||
m_raw_inode.i_atime = t;
|
||||
set_metadata_dirty(true);
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> Ext2FSInode::set_ctime(time_t t)
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
if (fs().is_readonly())
|
||||
return EROFS;
|
||||
m_raw_inode.i_ctime = t;
|
||||
set_metadata_dirty(true);
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> Ext2FSInode::set_mtime(time_t t)
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
if (fs().is_readonly())
|
||||
return EROFS;
|
||||
m_raw_inode.i_mtime = t;
|
||||
if (ctime.value_or(0) > INT32_MAX)
|
||||
return EINVAL;
|
||||
if (mtime.value_or(0) > INT32_MAX)
|
||||
return EINVAL;
|
||||
if (atime.has_value())
|
||||
m_raw_inode.i_atime = atime.value();
|
||||
if (ctime.has_value())
|
||||
m_raw_inode.i_ctime = ctime.value();
|
||||
if (mtime.has_value())
|
||||
m_raw_inode.i_mtime = mtime.value();
|
||||
set_metadata_dirty(true);
|
||||
return {};
|
||||
}
|
||||
|
@ -44,9 +44,7 @@ private:
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> create_child(StringView name, mode_t, dev_t, UserID, GroupID) override;
|
||||
virtual ErrorOr<void> add_child(Inode& child, StringView name, mode_t) override;
|
||||
virtual ErrorOr<void> remove_child(StringView name) override;
|
||||
virtual ErrorOr<void> set_atime(time_t) override;
|
||||
virtual ErrorOr<void> set_ctime(time_t) override;
|
||||
virtual ErrorOr<void> set_mtime(time_t) override;
|
||||
virtual ErrorOr<void> update_timestamps(Optional<time_t> atime, Optional<time_t> ctime, Optional<time_t> mtime) override;
|
||||
virtual ErrorOr<void> increment_link_count() override;
|
||||
virtual ErrorOr<void> decrement_link_count() override;
|
||||
virtual ErrorOr<void> chmod(mode_t) override;
|
||||
|
@ -528,17 +528,7 @@ ErrorOr<void> ISO9660Inode::truncate(u64)
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> ISO9660Inode::set_atime(time_t)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> ISO9660Inode::set_ctime(time_t)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
||||
ErrorOr<void> ISO9660Inode::set_mtime(time_t)
|
||||
ErrorOr<void> ISO9660Inode::update_timestamps(Optional<time_t>, Optional<time_t>, Optional<time_t>)
|
||||
{
|
||||
return EROFS;
|
||||
}
|
||||
|
@ -359,9 +359,7 @@ public:
|
||||
virtual ErrorOr<void> chmod(mode_t) override;
|
||||
virtual ErrorOr<void> chown(UserID, GroupID) override;
|
||||
virtual ErrorOr<void> truncate(u64) override;
|
||||
virtual ErrorOr<void> set_atime(time_t) override;
|
||||
virtual ErrorOr<void> set_ctime(time_t) override;
|
||||
virtual ErrorOr<void> set_mtime(time_t) override;
|
||||
virtual ErrorOr<void> update_timestamps(Optional<time_t> atime, Optional<time_t> ctime, Optional<time_t> mtime) override;
|
||||
|
||||
private:
|
||||
// HACK: The base ISO 9660 standard says the maximum filename length is 37
|
||||
|
@ -106,17 +106,7 @@ void Inode::will_be_destroyed()
|
||||
(void)flush_metadata();
|
||||
}
|
||||
|
||||
ErrorOr<void> Inode::set_atime(time_t)
|
||||
{
|
||||
return ENOTIMPL;
|
||||
}
|
||||
|
||||
ErrorOr<void> Inode::set_ctime(time_t)
|
||||
{
|
||||
return ENOTIMPL;
|
||||
}
|
||||
|
||||
ErrorOr<void> Inode::set_mtime(time_t)
|
||||
ErrorOr<void> Inode::update_timestamps([[maybe_unused]] Optional<time_t> atime, [[maybe_unused]] Optional<time_t> ctime, [[maybe_unused]] Optional<time_t> mtime)
|
||||
{
|
||||
return ENOTIMPL;
|
||||
}
|
||||
@ -236,8 +226,7 @@ void Inode::did_modify_contents()
|
||||
// FIXME: What happens if this fails?
|
||||
// ENOTIMPL would be a meaningless error to return here
|
||||
auto time = kgettimeofday().to_truncated_seconds();
|
||||
(void)set_mtime(time);
|
||||
(void)set_ctime(time);
|
||||
(void)update_timestamps({}, time, time);
|
||||
|
||||
m_watchers.for_each([&](auto& watcher) {
|
||||
watcher->notify_inode_event({}, identifier(), InodeWatcherEvent::Type::ContentModified);
|
||||
|
@ -80,9 +80,7 @@ public:
|
||||
|
||||
bool is_metadata_dirty() const { return m_metadata_dirty; }
|
||||
|
||||
virtual ErrorOr<void> set_atime(time_t);
|
||||
virtual ErrorOr<void> set_ctime(time_t);
|
||||
virtual ErrorOr<void> set_mtime(time_t);
|
||||
virtual ErrorOr<void> update_timestamps(Optional<time_t> atime, Optional<time_t> ctime, Optional<time_t> mtime);
|
||||
virtual ErrorOr<void> increment_link_count();
|
||||
virtual ErrorOr<void> decrement_link_count();
|
||||
|
||||
|
@ -49,7 +49,7 @@ ErrorOr<size_t> InodeFile::write(OpenFileDescription& description, u64 offset, U
|
||||
nwritten = TRY(m_inode->write_bytes(offset, count, data, &description));
|
||||
}
|
||||
if (nwritten > 0) {
|
||||
auto mtime_result = m_inode->set_mtime(kgettimeofday().to_truncated_seconds());
|
||||
auto mtime_result = m_inode->update_timestamps({}, {}, kgettimeofday().to_truncated_seconds());
|
||||
Thread::current()->did_file_write(nwritten);
|
||||
evaluate_block_conditions();
|
||||
if (mtime_result.is_error())
|
||||
@ -106,7 +106,7 @@ ErrorOr<NonnullOwnPtr<KString>> InodeFile::pseudo_path(OpenFileDescription const
|
||||
ErrorOr<void> InodeFile::truncate(u64 size)
|
||||
{
|
||||
TRY(m_inode->truncate(size));
|
||||
TRY(m_inode->set_mtime(kgettimeofday().to_truncated_seconds()));
|
||||
TRY(m_inode->update_timestamps({}, {}, kgettimeofday().to_truncated_seconds()));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -145,11 +145,6 @@ ErrorOr<void> ProcFSGlobalInode::truncate(u64 size)
|
||||
return m_associated_component->truncate(size);
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSGlobalInode::set_mtime(time_t time)
|
||||
{
|
||||
return m_associated_component->set_mtime(time);
|
||||
}
|
||||
|
||||
InodeMetadata ProcFSGlobalInode::metadata() const
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
|
@ -84,7 +84,6 @@ protected:
|
||||
virtual ErrorOr<void> traverse_as_directory(Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)>) const override;
|
||||
virtual ErrorOr<NonnullLockRefPtr<Inode>> lookup(StringView) override;
|
||||
virtual ErrorOr<void> truncate(u64) override final;
|
||||
virtual ErrorOr<void> set_mtime(time_t) override final;
|
||||
|
||||
NonnullLockRefPtr<ProcFSExposedComponent> m_associated_component;
|
||||
};
|
||||
|
@ -121,11 +121,6 @@ ErrorOr<void> SysFSInode::chown(UserID, GroupID)
|
||||
return EPERM;
|
||||
}
|
||||
|
||||
ErrorOr<void> SysFSInode::set_mtime(time_t time)
|
||||
{
|
||||
return m_associated_component->set_mtime(time);
|
||||
}
|
||||
|
||||
ErrorOr<void> SysFSInode::truncate(u64 size)
|
||||
{
|
||||
return m_associated_component->truncate(size);
|
||||
|
@ -54,7 +54,6 @@ protected:
|
||||
virtual ErrorOr<void> chmod(mode_t) override;
|
||||
virtual ErrorOr<void> chown(UserID, GroupID) override;
|
||||
virtual ErrorOr<void> truncate(u64) override;
|
||||
virtual ErrorOr<void> set_mtime(time_t) override;
|
||||
|
||||
virtual ErrorOr<void> attach(OpenFileDescription& description) override final;
|
||||
virtual void did_seek(OpenFileDescription&, off_t) override final;
|
||||
|
@ -35,7 +35,6 @@ public:
|
||||
virtual mode_t permissions() const;
|
||||
virtual ErrorOr<void> truncate(u64) { return EPERM; }
|
||||
virtual size_t size() const { return 0; }
|
||||
virtual ErrorOr<void> set_mtime(time_t) { return ENOTIMPL; }
|
||||
virtual ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) { return EROFS; }
|
||||
virtual ErrorOr<void> refresh_data(OpenFileDescription&) const { return {}; }
|
||||
|
||||
|
@ -27,7 +27,6 @@ public:
|
||||
virtual mode_t permissions() const override;
|
||||
virtual ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) override;
|
||||
virtual ErrorOr<void> truncate(u64) override;
|
||||
virtual ErrorOr<void> set_mtime(time_t) override { return {}; }
|
||||
|
||||
private:
|
||||
PowerStateSwitchNode(FirmwareSysFSDirectory&);
|
||||
|
@ -301,29 +301,16 @@ ErrorOr<void> TmpFSInode::truncate(u64 size)
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> TmpFSInode::set_atime(time_t time)
|
||||
ErrorOr<void> TmpFSInode::update_timestamps(Optional<time_t> atime, Optional<time_t> ctime, Optional<time_t> mtime)
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
|
||||
m_metadata.atime = time;
|
||||
set_metadata_dirty(true);
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> TmpFSInode::set_ctime(time_t time)
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
|
||||
m_metadata.ctime = time;
|
||||
set_metadata_dirty(true);
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> TmpFSInode::set_mtime(time_t t)
|
||||
{
|
||||
MutexLocker locker(m_inode_lock);
|
||||
|
||||
m_metadata.mtime = t;
|
||||
if (atime.has_value())
|
||||
m_metadata.atime = atime.value();
|
||||
if (ctime.has_value())
|
||||
m_metadata.ctime = ctime.value();
|
||||
if (mtime.has_value())
|
||||
m_metadata.ctime = mtime.value();
|
||||
set_metadata_dirty(true);
|
||||
return {};
|
||||
}
|
||||
|
@ -59,9 +59,7 @@ public:
|
||||
virtual ErrorOr<void> chmod(mode_t) override;
|
||||
virtual ErrorOr<void> chown(UserID, GroupID) override;
|
||||
virtual ErrorOr<void> truncate(u64) override;
|
||||
virtual ErrorOr<void> set_atime(time_t) override;
|
||||
virtual ErrorOr<void> set_ctime(time_t) override;
|
||||
virtual ErrorOr<void> set_mtime(time_t) override;
|
||||
virtual ErrorOr<void> update_timestamps(Optional<time_t> atime, Optional<time_t> ctime, Optional<time_t> mtime) override;
|
||||
|
||||
private:
|
||||
TmpFSInode(TmpFS& fs, InodeMetadata const& metadata, LockWeakPtr<TmpFSInode> parent);
|
||||
|
@ -213,8 +213,7 @@ ErrorOr<void> VirtualFileSystem::utime(Credentials const& credentials, StringVie
|
||||
if (custody->is_readonly())
|
||||
return EROFS;
|
||||
|
||||
TRY(inode.set_atime(atime));
|
||||
TRY(inode.set_mtime(mtime));
|
||||
TRY(inode.update_timestamps(atime, {}, mtime));
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -228,10 +227,10 @@ ErrorOr<void> VirtualFileSystem::utimensat(Credentials const& credentials, Strin
|
||||
return EROFS;
|
||||
|
||||
// NOTE: A standard ext2 inode cannot store nanosecond timestamps.
|
||||
if (atime.tv_nsec != UTIME_OMIT)
|
||||
TRY(inode.set_atime(atime.tv_sec));
|
||||
if (mtime.tv_nsec != UTIME_OMIT)
|
||||
TRY(inode.set_mtime(mtime.tv_sec));
|
||||
TRY(inode.update_timestamps(
|
||||
(atime.tv_nsec != UTIME_OMIT) ? atime.tv_nsec : Optional<time_t> {},
|
||||
{},
|
||||
(mtime.tv_nsec != UTIME_OMIT) ? mtime.tv_nsec : Optional<time_t> {}));
|
||||
|
||||
return {};
|
||||
}
|
||||
@ -321,7 +320,7 @@ ErrorOr<NonnullLockRefPtr<OpenFileDescription>> VirtualFileSystem::open(Credenti
|
||||
|
||||
if (should_truncate_file) {
|
||||
TRY(inode.truncate(0));
|
||||
TRY(inode.set_mtime(kgettimeofday().to_truncated_seconds()));
|
||||
TRY(inode.update_timestamps({}, {}, kgettimeofday().to_truncated_seconds()));
|
||||
}
|
||||
auto description = TRY(OpenFileDescription::try_create(custody));
|
||||
description->set_rw_mode(options);
|
||||
|
@ -184,11 +184,6 @@ ErrorOr<void> ProcFSSystemBoolean::truncate(u64 size)
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<void> ProcFSSystemBoolean::set_mtime(time_t)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
ErrorOr<size_t> ProcFSExposedLink::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, OpenFileDescription*) const
|
||||
{
|
||||
VERIFY(offset == 0);
|
||||
|
@ -74,7 +74,6 @@ public:
|
||||
virtual ErrorOr<NonnullLockRefPtr<ProcFSExposedComponent>> lookup(StringView) { VERIFY_NOT_REACHED(); };
|
||||
virtual ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) { return EROFS; }
|
||||
virtual ErrorOr<void> truncate(u64) { return EPERM; }
|
||||
virtual ErrorOr<void> set_mtime(time_t) { return ENOTIMPL; }
|
||||
|
||||
virtual mode_t required_mode() const { return 0444; }
|
||||
virtual UserID owner_user() const { return 0; }
|
||||
@ -201,7 +200,6 @@ private:
|
||||
virtual ErrorOr<size_t> write_bytes(off_t, size_t, UserOrKernelBuffer const&, OpenFileDescription*) override final;
|
||||
virtual mode_t required_mode() const override final { return 0644; }
|
||||
virtual ErrorOr<void> truncate(u64) override final;
|
||||
virtual ErrorOr<void> set_mtime(time_t) override final;
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user