Commit Graph

43 Commits

Author SHA1 Message Date
implicitfield
54bfc3d294 Kernel/Ext2FS: Cache blocks less aggressively
With this patch, we now only cache at most 2^14 blocks, which greatly
relieves memory pressure when working with large files.
2024-11-05 20:14:21 +01:00
implicitfield
54b8fe1fa4 Kernel/Ext2FS: Add a helper to free every block an inode holds 2024-11-05 20:14:21 +01:00
implicitfield
a32b9c903b Kernel/Ext2FS: Make block allocation properly fallible
For some context, write_bytes_locked used to simply bail out before
writing any data if there weren't enough blocks to cover the entire size
of an inode before 1bf7f99a.

We're not actually restoring that behavior here, since computing the
amount of blocks to be allocated would get exceedingly complex,
considering that there could always be holes in between already
allocated blocks.

Instead, this simply makes allocate_blocks() bail out properly if there
aren't any free blocks left.

Fixes #24980
2024-11-05 20:14:21 +01:00
brody-qq
44a2157e2e Kernel/Ext2FS: Reduce allocations in compute_block_list_impl()
In Ext2FSInode::compute_block_list_impl(), each call to
process_block_array() creates a new ByteBuffer, which leads to a
kmalloc() call. The ByteBuffer is then discarded when
process_block_array() exits, leading to a kfree() call.

This leads to repeated kmalloc() and kfree() calls as ByteBuffers are
created and destroyed each time process_block_array() is called.

This commit makes it so that only 1 ByteBuffer is created for each level
of inode indirect block (so only 3 ByteBuffers are created at most).
These ByteBuffers are re-used on each call to process_block_array().

This reduces the number of kmalloc() and kfree() calls during
compute_block_list_impl(), especially for larger files.
2024-08-30 22:22:13 +02:00
Liav A.
cb10f70394 Kernel: Change internal handling of filesystem-specific options
Instead of using a raw `KBuffer` and letting each implementation to
populating the specific flags on its own, we change things so we only
let each FileSystem implementation to validate the flag and its value
but then store it in a HashMap which its key is the flag name and
the value is a special new class called `FileSystemSpecificOption`
which wraps around `AK::Variant<...>`.

This approach has multiple advantages over the previous:
- It allows runtime inspection of what the user has set on a `MountFile`
  description for a specific filesystem.
- It ensures accidental overriding of filesystem specific option that
  was already set is not possible
- It removes ugly casting of a `KBuffer` contents to a strongly-typed
  values. Instead, a strongly-typed `AK::Variant` is used which ensures
  we always get a value without doing any casting.

Please note that we have removed support for ASCII string-oriented flags
as there were no actual use cases, and supporting such type would make
`FileSystemSpecificOption` more complicated unnecessarily for now.
2024-08-03 20:35:06 +02:00
brody-qq
f3f681ae45 Kernel/Ext2FS: Replace hardcoded offset with a constexpr
The superblock of an ext2 filesystem is always found on the storage
device at offset 1024. This 1024 number was hardcoded in the Ext2FS
code.

This commit:
* adds a constexpr to replace the hardcoded 1024 values
* removes a comment about one of the the hardcoded 1024 values which is
  now umnecessary
2024-07-27 07:50:07 -04:00
implicitfield
1bf7f99a7b Kernel/Ext2FS: Support writing holes
With this change, we no longer preallocate blocks when an inode's size
is updated, and instead only allocate the minimum amount of blocks when
the inode is actually written to.
2024-06-29 19:16:08 +02:00
implicitfield
180f3f29ab Kernel/Ext2FS: Refactor computing and flushing blocks
This is a large commit, since this is essentially a complete rewrite of
the key low-level functions that handle reading/writing blocks. This is,
however, a necessary prerequisite of being able to write holes.

The previous version of `flush_block_list()` (along with its numerous
helper functions) was entirely reliant on all blocks being sequential.
In contrast to the previous implementation, the new version
of `flush_block_list()` simply writes out the difference between the old
block list and the new block list by calculating the correct indirect
block(s) to update based on the relevant block's logical index.

`compute_block_list()` has also been rewritten, since the estimated
amount of meta blocks was incorrectly calculated for files with holes as
a result of the estimated amount of blocks being a function of the file
size. Since it isn't possible to accurately compute the shape of the
block list without traversing it, we no longer try to perform such a
computation, and instead simply search through all of the allocated
indirect blocks.

`compute_block_list_with_meta_blocks()` has also been removed in favor
of the new `compute_meta_blocks()`, since meta blocks are fundamentally
distinct from data blocks due to there being no mapping between any
logical block index and the physical block index.
2024-06-29 19:16:08 +02:00
implicitfield
06d4672564 Kernel/Ext2FS: Store the block list as a HashMap rather than a Vector
Since we now only store blocks that are actually allocated, it is
entirely valid for the block list to be empty, so this commit lifts the
restrictions on accessing inodes with an empty block list.
2024-06-29 19:16:08 +02:00
implicitfield
ba96a0e4f8 Kernel/Ext2FS: Simplify read/write loops
This removes removes the need to know the last block in advance, and
makes the loops slightly easier to reason about by depending on fewer
conditions.
2024-06-29 19:16:08 +02:00
Liav A
5dcf03ad9a Kernel/Devices: Introduce the LoopDevice device
This device is a block device that allows a user to effectively treat an
Inode as a block device.

The static construction method is given an OpenFileDescription reference
but validates that:
- The description has a valid custody (so it's not some arbitrary file).
  Failing this requirement will yield EINVAL.
- The description custody points to an Inode which is a regular file, as
  we only support (seekable) regular files. Failing this requirement
  will yield ENOTSUP.

LoopDevice can be used to mount a regular file on the filesystem like
other supported types of (physical) block devices.
2024-03-13 15:33:47 -06:00
Liav A
fff49ab6d3 Kernel/FileSystem: Avoid double locking m_inode_lock in the Ext2 driver 2024-02-24 16:45:26 -07:00
Liav A
b63a1dda63 Kernel/FileSystem: Enforce locking of m_inode_lock when truncating Inode
Such operation is almost equivalent to writing on an Inode, so lock the
Inode m_inode_lock exclusively.
All FileSystem Inode implementations then override a new method called
truncate_locked which should implement the actual truncating.
2024-02-24 16:45:26 -07:00
Fabian Dellwing
5180e41918 Kernel: Call did_modify_contents() after truncate()
Truncating a file should absolutly mark it as modified. With this
change our `tail` implementation can correctly handle it.
2024-02-24 15:48:36 -07:00
implicitfield
48e848a9fd Kernel/Ext2: Only handle extended attributes when they are supported 2024-01-05 04:00:11 +03:30
implicitfield
280d5feac9 Kernel/Ext2: Allow checking for the presence of extended attributes 2024-01-05 04:00:11 +03:30
Blake Smith
e346331424 Kernel/FS: Fix check-then-act concurrency bug in FileSystem/Inode
When the FileSystem does a sync, it gathers up all the inodes with
dirty metadata into a vector. The inode mutex is not held while
checking the inode dirty bit, which can lead to a kernel panic
due to concurrent inode modifications.

Fixes: #21796
2023-11-20 09:44:29 +01:00
Tim Ledbetter
db929e0fcf Kernel/Ext2: Avoid overflow when updating UID and GID values
Previously, attempting to update an ext2 inode with a UID or GID
larger than 65535 would overflow. We now write the high bits of UIDs
and GIDs to the same place that Linux does within the `osd2` struct.
2023-10-24 07:21:11 +02:00
Zak-K-Abdi
abcf05801a Kernel: Allow Ext2FS::flush_writes() to return ErrorOr<void> 2023-08-25 11:36:57 +01:00
Liav A
dbab4d34d7 Kernel/FileSystem: Remove disk cache only after ext2 superblock flush
We first must flush the superblock through the BlockBasedFileSystem
methods properly and only then clear the DiskCache pointer, to prevent a
possible kernel panic due to nullptr dereference.
2023-08-20 13:04:42 -06:00
kleines Filmröllchen
c8d7bcede6 Kernel/FileSystem: Rename block_size -> logical_block_size
Since this is the block size that file system drivers *should* set,
let's name it the logical block size, just like most file systems such
as ext2 already do anyways.
2023-07-28 14:51:07 +02:00
kleines Filmröllchen
d1e6e6110d Kernel/FileSystem: Rename logical_block_size -> device_block_size
This never was a logical block size, it always was a device specific
block size. Ideally the block size would change in accordance to
whatever the driver wants to use, but that is a change for the future.
For now, let's get rid of this confusing naming.
2023-07-28 14:51:07 +02:00
kleines Filmröllchen
bf1610d378 Kernel/Ext2: Don't rely on block size 512 for superblock offset 2023-07-28 14:51:07 +02:00
kleines Filmröllchen
10ba54a009 Kernel/Ext2: Write BGDT backups
Same as for the superblock, let's back up the block group descriptor
table.
2023-07-28 14:51:07 +02:00
kleines Filmröllchen
a0705202ea Kernel/Ext2: Write superblock backups
We don't ever read them out, but this should make fsck a lot less mad.
2023-07-28 14:51:07 +02:00
kleines Filmröllchen
cc1cb72fb5 Kernel/Ext2: Extract common calculations to functions
This also makes it easier to understand and reference where these
(sometimes rather arbitrary) calculations come from.

This also fixes a bug where group_index_from_block_index assumed 1KiB
blocks.
2023-07-28 14:51:07 +02:00
kleines Filmröllchen
251b17085b Kernel/Ext2: Check and set file system state
This is supposed to detect whether a file system was unmounted
cleanly or not.
2023-07-15 00:12:01 +02:00
kleines Filmröllchen
8fb126bec6 Kernel/FileSystem: Pass last mount point guest inode to unmount prepare
This will be important later on when we check file system busyness.
2023-07-15 00:12:01 +02:00
Liav A
23a7ccf607 Kernel+LibCore+LibC: Split the mount syscall into multiple syscalls
This is a preparation before we can create a usable mechanism to use
filesystem-specific mount flags.
To keep some compatibility with userland code, LibC and LibCore mount
functions are kept being usable, but now instead of doing an "atomic"
syscall, they do multiple syscalls to perform the complete procedure of
mounting a filesystem.

The FileBackedFileSystem IntrusiveList in the VFS code is now changed to
be protected by a Mutex, because when we mount a new filesystem, we need
to check if a filesystem is already created for a given source_fd so we
do a scan for that OpenFileDescription in that list. If we fail to find
an already-created filesystem we create a new one and register it in the
list if we successfully mounted it. We use a Mutex because we might need
to initiate disk access during the filesystem creation, which will take
other mutexes in other parts of the kernel, therefore making it not
possible to take a spinlock while doing this.
2023-07-02 01:04:51 +02:00
Liav A
7c0540a229 Everywhere: Move global Kernel pattern code to Kernel/Library directory
This has KString, KBuffer, DoubleBuffer, KBufferBuilder, IOWindow,
UserOrKernelBuffer and ScopedCritical classes being moved to the
Kernel/Library subdirectory.

Also, move the panic and assertions handling code to that directory.
2023-06-04 21:32:34 +02:00
Liav A
1b04726c85 Kernel: Move all tasks-related code to the Tasks subdirectory 2023-06-04 21:32:34 +02:00
Liav A
2ab657d3b5 Kernel: Make Ext2FSInode::traverse_as_directory to take m_inode_lock
The contents of the directory inode could change if we are not taking so
we must take the m_inode_lock to prevent corruption when reading the
directory contents.
2023-05-27 10:58:58 +02:00
kleines Filmröllchen
939600d2d4 Kernel: Use UnixDateTime wherever applicable
"Wherever applicable" = most places, actually :^), especially for
networking and filesystem timestamps.

This includes changes to unzip, which uses DOSPackedTime, since that is
changed for the FAT file systems.
2023-05-24 23:18:07 +02:00
kleines Filmröllchen
213025f210 AK: Rename Time to Duration
That's what this class really is; in fact that's what the first line of
the comment says it is.

This commit does not rename the main files, since those will contain
other time-related classes in a little bit.
2023-05-24 23:18:07 +02:00
Andreas Kling
673592dea8 Kernel: Stop using *LockRefPtr for FileSystem pointers
There was only one permanent storage location for these: as a member
in the Mount class.

That member is never modified after Mount initialization, so we don't
need to worry about races there.
2023-04-04 10:33:42 +02:00
Tim Schumacher
ecd1862859 AK: Rename Stream::write_entire_buffer to Stream::write_until_depleted
No functional changes.
2023-03-13 15:16:20 +00:00
Andreas Kling
e6fc7b3ff7 Kernel: Switch LockRefPtr<Inode> to RefPtr<Inode>
The main place where this is a little iffy is in RAMFS where inodes
have a LockWeakPtr to their parent inode. I've left that as a
LockWeakPtr for now.
2023-03-09 21:54:59 +01:00
Tim Schumacher
81863eaf57 Kernel: Use AK::Stream to write packed binary data 2023-02-08 18:50:31 +00:00
Tim Schumacher
ae64b68717 AK: Deprecate the old AK::Stream
This also removes a few cases where the respective header wasn't
actually required to be included.
2023-01-29 19:16:44 -07:00
Andrew Kaster
7ab37ee22c Everywhere: Remove string.h include from AK/Traits.h and resolve fallout
A lot of places were relying on AK/Traits.h to give it strnlen, memcmp,
memcpy and other related declarations.

In the quest to remove inclusion of LibC headers from Kernel files, deal
with all the fallout of this included-everywhere header including less
things.
2023-01-21 10:43:59 -07:00
sin-ack
3b03077abb Kernel: Update the ".." inode for directories after a rename
Because the ".." entry in a directory is a separate inode, if a
directory is renamed to a new location, then we should update this entry
the point to the new parent directory as well.

Co-authored-by: Liav A <liavalb@gmail.com>
2022-11-25 17:33:05 +01:00
Andreas Kling
10fa72d451 Kernel: Use AK::Time for InodeMetadata timestamps instead of time_t
Before this change, we were truncating the nanosecond part of file
timestamps in many different places.
2022-11-24 16:56:27 +01:00
Liav A
3cc0d60141 Kernel: Split the Ext2FileSystem.{cpp,h} files into smaller components 2022-11-08 02:54:48 -07:00