Commit graph

268 commits

Author SHA1 Message Date
Andreas Kling
c09921b9be Ext2FS: Don't hog FS lock while reading/writing inodes
There are two locks in the Ext2FS implementation:

* The FS lock (Ext2FS::m_lock)
  This governs access to the superblock, block group descriptors,
  and the block & inode bitmap blocks. It's held while allocating
  or freeing blocks/inodes.

* The inode lock (Ext2FSInode::m_lock)
  This governs access to the inode metadata, including the block
  list, and to the content data as well. It's held while doing
  basically anything with the inode.

Once an on-disk block/inode is allocated, it logically belongs
to the in-memory Inode object, so there's no need for the FS lock
to be taken while manipulating them, the inode lock is all you need.

This dramatically reduces the impact of disk I/O on path resolution
and various other things that look at individual inodes.
2021-02-26 17:57:38 +01:00
Andreas Kling
c7c63727bf Ext2FS: Remove unnecessary locking in find_block_containing_inode()
This is just a bunch of index math based on immutable values in the
super block and block group descriptor. No need to lock here!
2021-02-26 17:24:39 +01:00
Andreas Kling
81e3ea29c3 Ext2FS: Remove unnecessary lock in Ext2FS::write_ext2_node()
Now that writing to the underlying storage is serialized, we don't
need to take the FS lock when writing out an inode struct.
2021-02-26 17:23:46 +01:00
Andreas Kling
65e083ed36 Revert "Ext2FS: Don't reload already-cached block list when freeing inode"
This reverts commit 1e737a5c50.

The cached block list does not include meta-blocks, so we'd end up
leaking those. There's definitely a nice way to avoid work here, but it
turns out it wasn't quite this trivial. Reverting for now.
2021-02-26 14:57:00 +01:00
Andreas Kling
1e737a5c50 Ext2FS: Don't reload already-cached block list when freeing inode
If we already have a cached copy of the inode's block list, we can use
that to free the blocks. No need to reload the list.
2021-02-26 14:05:18 +01:00
Andreas Kling
1f9409a658 Ext2FS: Inode allocation improvements
This patch combines inode the scan for an available inode with the
updating of the bit in the inode bitmap into a single operation.

We also exit the scan immediately when we find an inode, instead of
continuing until we've scanned all the eligible groups(!)

Finally, we stop holding the filesystem lock throughout the entire
operation, and instead only take it while actually necessary
(during inode allocation, flush, and inode cache update.)
2021-02-26 14:05:18 +01:00
Andreas Kling
19083fd760 Ext2FS: Propagate errors from more places
Improve a bunch of situations where we'd previously panic the kernel
on failure. We now propagate whatever error we had instead. Usually
that'll be EIO.
2021-02-26 14:05:18 +01:00
Andreas Kling
6352b4fd74 Ext2FS: Share some bitmap code between inode and block allocation
Both inode and block allocation operate on bitmap blocks and update
counters in the superblock and group descriptor.

Since we're here, also add some error propagation around this code.
2021-02-26 14:05:18 +01:00
Andreas Kling
5d180d1f99 Everywhere: Rename ASSERT => VERIFY
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED)

Since all of these checks are done in release builds as well,
let's rename them to VERIFY to prevent confusion, as everyone is
used to assertions being compiled out in release.

We can introduce a new ASSERT macro that is specifically for debug
checks, but I'm doing this wholesale conversion first since we've
accumulated thousands of these already, and it's not immediately
obvious which ones are suitable for ASSERT.
2021-02-23 20:56:54 +01:00
Brian Gianforcaro
cbd8f78cce Kernel: Use uniform initialization instead of memset for a few stack buffer.
Raw memset is relatively easy to mess up, avoid it when there are
better alternatives provided by the compiler in modern C++.
2021-02-21 11:52:47 +01:00
Brian Gianforcaro
7c950c2d01 Kernel: Use ByteBuffer::zero_fill() instead of raw memset in Ext2
There was a typo in one of the memsets, use the type safe wrapper instead.

Fix EXt
2021-02-21 11:52:47 +01:00
Jean-Baptiste Boric
9ce0639383 Kernel: Use divide_rounded_up inside write_block_list_for_inode 2021-02-13 19:56:49 +01:00
Jean-Baptiste Boric
869b33d6dd Kernel: Support triply indirect blocks for BlockListShape computation 2021-02-13 19:56:49 +01:00
Andreas Kling
c62c00e7db Ext2FS: Make Ext2FS::GroupIndex a distinct integer type 2021-02-12 13:33:58 +01:00
Andreas Kling
489317e573 Kernel: Make BlockBasedFS::BlockIndex a distinct integer type 2021-02-12 11:59:27 +01:00
Andreas Kling
e44c1792a7 Kernel: Add distinct InodeIndex type
Use the DistinctNumeric mechanism to make InodeIndex a strongly typed
integer type.
2021-02-12 10:26:29 +01:00
Andreas Kling
95064f8b58 Ext2FS: Convert #if EXT2_DEBUG => dbgln_if() and constexpr-if 2021-02-11 23:05:16 +01:00
Andreas Kling
a280cdf9ba Ext2FS: Shrink Ext2FSDirectoryEntry from 16 to 12 bytes
The way we read/write directories is very inefficient, and this doesn't
solve any of that. It does however reduce memory usage of directory
entry vectors by 25% which has nice immediate benefits.
2021-02-11 22:45:50 +01:00
Andreas Kling
4c0707e56c Kernel: Don't create a zero-length VLA in Ext2FS block list walk
Found by KUBSAN :^)
2021-02-05 21:23:11 +01:00
Andreas Kling
d4f40241f1 Ext2FS: Avoid unnecessary parent inode lookup during inode creation
Creation of new inodes is always driven by the parent inode, so we can
just refer directly to it instead of looking up the parent by ID.
2021-02-02 18:58:26 +01:00
Andreas Kling
9e4dd834ab Ext2FS: Simplify inode creation by always starting empty
We had two ways of creating a new Ext2FS inode. Either they were empty,
or they started with some pre-allocated size.

In practice, the pre-sizing code path was only used for new directories
and it didn't actually improve anything as far as I can tell.

This patch simplifies inode creation by simply always allocating empty
inodes. Block allocation and block list generation now always happens
on the same code path.
2021-02-02 18:58:26 +01:00
Andreas Kling
dbb668ddd3 Ext2FS: Propagate error codes from write_directory() 2021-02-02 18:58:26 +01:00
Peter Elliott
c0e88b9710 Kernel: Add FIBMAP ioctl to Ext2FileSystem
FIBMAP is a linux ioctl that gives the location on disk of a specific
block of a file
2021-01-30 22:54:51 +01:00
asynts
7cf0c7cc0d Meta: Split debug defines into multiple headers.
The following script was used to make these changes:

    #!/bin/bash
    set -e

    tmp=$(mktemp -d)

    echo "tmp=$tmp"

    find Kernel \( -name '*.cpp' -o -name '*.h' \) | sort > $tmp/Kernel.files
    find . \( -path ./Toolchain -prune -o -path ./Build -prune -o -path ./Kernel -prune \) -o \( -name '*.cpp' -o -name '*.h' \) -print | sort > $tmp/EverythingExceptKernel.files

    cat $tmp/Kernel.files | xargs grep -Eho '[A-Z0-9_]+_DEBUG' | sort | uniq > $tmp/Kernel.macros
    cat $tmp/EverythingExceptKernel.files | xargs grep -Eho '[A-Z0-9_]+_DEBUG' | sort | uniq > $tmp/EverythingExceptKernel.macros

    comm -23 $tmp/Kernel.macros $tmp/EverythingExceptKernel.macros > $tmp/Kernel.unique
    comm -1 $tmp/Kernel.macros $tmp/EverythingExceptKernel.macros > $tmp/EverythingExceptKernel.unique

    cat $tmp/Kernel.unique | awk '{ print "#cmakedefine01 "$1 }' > $tmp/Kernel.header
    cat $tmp/EverythingExceptKernel.unique | awk '{ print "#cmakedefine01 "$1 }' > $tmp/EverythingExceptKernel.header

    for macro in $(cat $tmp/Kernel.unique)
    do
        cat $tmp/Kernel.files | xargs grep -l $macro >> $tmp/Kernel.new-includes ||:
    done
    cat $tmp/Kernel.new-includes | sort > $tmp/Kernel.new-includes.sorted

    for macro in $(cat $tmp/EverythingExceptKernel.unique)
    do
        cat $tmp/Kernel.files | xargs grep -l $macro >> $tmp/Kernel.old-includes ||:
    done
    cat $tmp/Kernel.old-includes | sort > $tmp/Kernel.old-includes.sorted

    comm -23 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.new
    comm -13 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.old
    comm -12 $tmp/Kernel.new-includes.sorted $tmp/Kernel.old-includes.sorted > $tmp/Kernel.includes.mixed

    for file in $(cat $tmp/Kernel.includes.new)
    do
        sed -i -E 's/#include <AK\/Debug\.h>/#include <Kernel\/Debug\.h>/' $file
    done

    for file in $(cat $tmp/Kernel.includes.mixed)
    do
        echo "mixed include in $file, requires manual editing."
    done
2021-01-26 21:20:00 +01:00
asynts
eea72b9b5c Everywhere: Hook up remaining debug macros to Debug.h. 2021-01-25 09:47:36 +01:00
asynts
acdcf59a33 Everywhere: Remove unnecessary debug comments.
It would be tempting to uncomment these statements, but that won't work
with the new changes.

This was done with the following commands:

    find . \( -name '*.cpp' -o -name '*.h' -o -name '*.in' \) -not -path './Toolchain/*' -not -path './Build/*' -exec awk -i inplace '$0 !~ /\/\/#define/ { if (!toggle) { print; } else { toggle = !toggle } } ; $0 ~/\/\/#define/ { toggle = 1 }' {} \;

    find . \( -name '*.cpp' -o -name '*.h' -o -name '*.in' \) -not -path './Toolchain/*' -not -path './Build/*' -exec awk -i inplace '$0 !~ /\/\/ #define/ { if (!toggle) { print; } else { toggle = !toggle } } ; $0 ~/\/\/ #define/ { toggle = 1 }' {} \;
2021-01-25 09:47:36 +01:00
Andreas Kling
bfb254ed14 Ext2FS: Assert that create_directory() is called with valid mode 2021-01-23 16:45:05 +01:00
Andreas Kling
f2ea6c3d4c Ext2FS: Don't create a directory when asked to create a socket file
(mode & S_IFDIR) is not enough to check if "mode" is a directory,
we have to check all the bits in the S_IFMT mask.

Use the is_directory() helper to fix this bug.
2021-01-23 16:45:05 +01:00
Andreas Kling
1f53dd0943 Ext2FS: Propagate I/O errors from Ext2FSInode::write_bytes() 2021-01-21 00:14:56 +01:00
Andreas Kling
19d3f8cab7 Kernel+LibC: Turn errno codes into a strongly typed enum
..and allow implicit creation of KResult and KResultOr from ErrnoCode.
This means that kernel functions that return those types can finally
do "return EINVAL;" and it will just work.

There's a handful of functions that still deal with signed integers
that should be converted to return KResults.
2021-01-20 23:20:02 +01:00
Andreas Kling
e279b45aed Kernel: Make BlockBasedFS read/write functions return a KResult
This way, if something goes wrong, we get to keep the actual error.
Also, KResults are nodiscard, so we have to deal with that in Ext2FS
instead of just silently ignoring I/O errors(!)
2021-01-20 22:57:36 +01:00
Andreas Kling
6613cef2f8 Ext2FS: Update block group directory count after directory removal
When freeing an inode, we were checking if it's a directory *after*
wiping the inode metadata. This caused us to forget updating the block
group descriptor with the new directory count.
2021-01-17 16:56:07 +01:00
Andreas Kling
77656aed8e Ext2FS: Zero out new space when growing an inode
Before this change, truncating an Ext2FS inode to a larger size than it
was before would give you uninitialized on-disk data.

Fix this by zeroing out all the new space when doing an inode resize.

This is pretty naively implemented via Inode::write_bytes() and there's
lots of room for cleverness here in the future.
2021-01-09 22:08:53 +01:00
Andreas Kling
f0093e5d59 Ext2FS: Convert dbg() to dbgln()
Also remove some dbg()'s that were printing incorrect information.
2021-01-09 21:54:27 +01:00
asynts
938e5c7719 Everywhere: Replace a bundle of dbg with dbgln.
These changes are arbitrarily divided into multiple commits to make it
easier to find potentially introduced bugs with git bisect.Everything:

The modifications in this commit were automatically made using the
following command:

    find . -name '*.cpp' -exec sed -i -E 's/dbg\(\) << ("[^"{]*");/dbgln\(\1\);/' {} \;
2021-01-09 21:11:09 +01:00
Tom
ae956edf6e Kernel: Improve some low-memory situations with ext2 2021-01-01 23:43:44 +01:00
Andreas Kling
43d9fe15f9 Revert "Kernel: Convert read_block method to get a reference instead of pointer"
This reverts commit 092a13211a.

Fixes #4611.
2020-12-29 00:06:52 +01:00
Liav A
092a13211a Kernel: Convert read_block method to get a reference instead of pointer
BlockBasedFileSystem::read_block method should get a reference of
a UserOrKernelBuffer.

If we need to force caching a block, we will call other method to do so.
2020-12-27 23:07:44 +01:00
Nathan Lanza
d1891f67ac
AK: Use direct-list-initialization for Vector::empend() (#4564)
clang trunk with -std=c++20 doesn't seem to properly look for an
aggregate initializer here when the type being constructed is a simple
aggregate (e.g. `struct Thing { int a; int b; };`). This template fails
to compile in a usage added 12/16/2020 in `AK/Trie.h`.

Both forms of initialization are supposed to call the
aggregate-initializers but direct-list-initialization delegating to
aggregate initializers is a new addition in c++20 that might not be
implemented yet.
2020-12-27 23:06:37 +01:00
Andreas Kling
8e79bde2b7 Kernel: Move KBufferBuilder to the fallible KBuffer API
KBufferBuilder::build() now returns an OwnPtr<KBuffer> and can fail.
Clients of the API have been updated to handle that situation.
2020-12-18 19:22:26 +01:00
Andreas Kling
47da86d136 Ext2FS: Fail the mount if BGD table cache allocation fails
Instead of asserting if we can't allocate enough memory for a BGD table
cache, just fail the mount instead.
2020-12-18 19:22:26 +01:00
Andreas Kling
76308c2e1f Kernel: Reduce ByteBuffer thrashing in inode block list generation
Instead of creating and destroying a new ByteBuffer for every block we
process during block list generation, just use stack memory instead.
2020-11-24 21:29:08 +01:00
Andreas Kling
3e3a72f2a2 Ext2FS: Oops, fix forgotten assignment in Ext2FSInode::resize()
If the inode's block list cache is empty, we forgot to assign the
result of computing the block list. The fact that this worked anyway
makes me wonder when we actually don't have a cache..

Thanks to szyszkienty for spotting this! :^)
2020-11-24 16:16:09 +01:00
Andreas Kling
20205708b9 Ext2FS: Use cached inode block list in resize() if available
If we have already cached the block list of an Ext2FSInode, we can save
a lot of time by not regenerating it.
2020-11-24 13:40:45 +01:00
Andreas Kling
bb9c705fc2 Ext2FS: Move some EXT2_DEBUG logging behind EXT2_VERY_DEBUG
This makes the build actually somewhat usable with EXT2_DEBUG. :^)
2020-11-23 16:08:42 +01:00
Andreas Kling
df758a5a51 Ext2FS: Clear out the direct block list when an inode is resized to 0
e2fsck was complaining about blocks being allocated in an inode's list
of direct blocks while at the same time being free in the block bitmap.

It was easy to reproduce by creating a file with non-zero length and
then truncating it. This fixes the issue by clearing out the direct
block list when resizing a file to 0.
2020-11-23 14:08:50 +01:00
Andreas Kling
1da828b8bf Ext2FS: Zero out inode metadata when deleting them
This isn't strictly necessary but it seems like a reasonable thing
to be doing. Note that we still populate the dtime field with the
time of deletion.
2020-11-07 17:48:22 +01:00
Andreas Kling
bab24ce34c Ext2FS: Deallocate block list meta blocks when freeing an inode
When computing the list of blocks to deallocate when freeing an inode,
we would stop collecting blocks after reaching the inode's block count.
Since we're getting rid of the inode, we need to also include the meta
blocks used by the on-disk block list itself.
2020-11-07 16:45:03 +01:00
Andreas Kling
eeffd5be07 Ext2FS: Fix block allocation ignoring the very last block group
The block group indices are 1-based for some reason. Because of that,
we were forgetting to check in the very last block group when doing
block allocation. This caused block allocation to fail even when the
superblock indicated that we had free blocks.

Fixes #3674.
2020-10-07 13:42:17 +02:00
Luke
d79194d87f Kernel: Return early in create_inode if name is too long 2020-09-28 21:52:31 +02:00
Andreas Kling
2cb32f8356 Kernel: Let InodeWatcher track child inode numbers instead of names
First of all, this fixes a dumb info leak where we'd write kernel heap
addresses (StringImpl*) into userspace memory when reading a watcher.

Instead of trying to pass names to userspace, we now simply pass the
child inode index. Nothing in userspace makes use of this yet anyway,
so it's not like we're breaking anything. We'll see how this evolves.
2020-09-19 16:39:52 +02:00
asynts
206dcd84a6 FileSystem: Use OutputMemoryStream instead of BufferStream. 2020-09-15 20:36:45 +02:00
Tom
c8d9f1b9c9 Kernel: Make copy_to/from_user safe and remove unnecessary checks
Since the CPU already does almost all necessary validation steps
for us, we don't really need to attempt to do this. Doing it
ourselves doesn't really work very reliably, because we'd have to
account for other processors modifying virtual memory, and we'd
have to account for e.g. pages not being able to be allocated
due to insufficient resources.

So change the copy_to/from_user (and associated helper functions)
to use the new safe_memcpy, which will return whether it succeeded
or not. The only manual validation step needed (which the CPU
can't perform for us) is making sure the pointers provided by user
mode aren't pointing to kernel mappings.

To make it easier to read/write from/to either kernel or user mode
data add the UserOrKernelBuffer helper class, which will internally
either use copy_from/to_user or directly memcpy, or pass the data
through directly using a temporary buffer on the stack.

Last but not least we need to keep syscall params trivial as we
need to copy them from/to user mode using copy_from/to_user.
2020-09-13 21:19:15 +02:00
Ben Wiederhake
737c9f0a14 Kernel: Explain correctness of reference to local lambda 2020-08-30 10:31:04 +02:00
Itamar
33138900de FileSystem: Convert file types to DT_* types at a later stage
A change introduced in 5e01234 made it the resposibility of each
filesystem to have the file types returned from
'traverse_as_directory' match up with the DT_* types.
However, this caused corruption of the Ext2FS file format because
the Ext2FS uses 'traverse_as_directory' internally when manipulating
 the file system. The result was a mixture between EXT2_FT_* and DT_*
file types in the internal Ext2FS structures.

Starting with this commit, the conversion from internal filesystem file
types to the user facing DT_* types happens at a later stage,
in the 'FileDescription::get_dir_entries' function which is directly
used by sys$get_dir_entries.
2020-08-29 20:54:06 +02:00
Itamar
b6c34c0521 Ext2FS: Make reported file_type values match up with those in dirent
This fixes an issue we had in the git port where git would not
recognize untracked files (for example in 'git status').
When git used readdir, the 'd_type' field in the dirent struct contained
bad values (Specifically, it contained the values defiend in
Kernel/FileSystem/ext2_fs.h instead of the ones in LibC/dirent.h).

After this fix, we can create a new git repository with 'git init', and
then stage and commit files as usual.
2020-08-28 16:06:55 +02:00
Andreas Kling
31d3eac651 Ext2FS: Fix build with EXT2_DEBUG 2020-08-23 01:25:29 +02:00
Andreas Kling
607e085823 Ext2FS: Fix inode link leak on all new inodes
The initial inode link count was wrong in Ext2FS, as the act of adding
new inodes to their new parent bumps the count.

This regressed in df66c28479.
2020-08-19 21:17:02 +02:00
Andreas Kling
6ad2d31952 Ext2FS: Stop using FS::DirectoryEntry
We were only using this as a temporary helper object while constructing
directories. Create a simpler Ext2FSDirectoryEntry instead for this.
2020-08-18 18:26:54 +02:00
Andreas Kling
eeaba41d13 Kernel: Add DirectoryEntryView for VFS directory traversal
Unlike DirectoryEntry (which is used when constructing directories),
DirectoryEntryView does not manage storage for file names. Names are
just StringViews.

This is much more suited to the directory traversal API and makes
it easier to implement this in file system classes since they no
longer need to create temporary name copies while traversing.
2020-08-18 18:26:54 +02:00
Brian Gianforcaro
946c96dd56 Kernel: Suppress remaining unobserved KResult return codes
These are all cases where there is no clear and easy fix,
I've left FIXME bread crumbs so that these can hopefully
be fixed over time.
2020-08-05 14:36:48 +02:00
Brian Gianforcaro
d67069d922 Kernel: Propagate a few KResults properly in FileSystem subsystems
Propagating un-obsevered KResults up the stack.
2020-08-05 14:36:48 +02:00
Brian Gianforcaro
e8c9b5e870 Kernel: Make Inode::directory_entry_count errors observable.
Certain implementations of Inode::directory_entry_count were calling
functions which returned errors, but had no way of surfacing them.
Switch the return type to KResultOr<size_t> and start observing these
error paths.
2020-08-05 10:26:29 +02:00
Tom
bc107d0b33 Kernel: Add SMP IPI support
We can now properly initialize all processors without
crashing by sending SMP IPI messages to synchronize memory
between processors.

We now initialize the APs once we have the scheduler running.
This is so that we can process IPI messages from the other
cores.

Also rework interrupt handling a bit so that it's more of a
1:1 mapping. We need to allocate non-sharable interrupts for
IPIs.

This also fixes the occasional hang/crash because all
CPUs now synchronize memory with each other.
2020-07-06 17:07:44 +02:00
Sergey Bugaev
187b785a05 Kernel: Split BlockBasedFileSystem off FileBackedFileSystem
FileBackedFileSystem is one that's backed by (mounted from) a file, in other
words one that has a "source" of the mount; that doesn't mean it deals in
blocks. The hierarchy now becomes:

* FS
  * ProcFS
  * DevPtsFS
  * TmpFS
  * FileBackedFS
    * (future) Plan9FS
    * BlockBasedFS
      * Ext2FS
2020-07-05 12:26:27 +02:00
Andreas Kling
0d577ab781 Kernel: Add "child added" and "child removed" InodeWatcher events
The child name is not yet accessible to userspace, but will be in a
future patch.
2020-07-04 13:37:51 +02:00
Sergey Bugaev
df66c28479 Kernel: Deemphasize inode identifiers
These APIs were clearly modeled after Ext2FS internals, and make perfect sense
in Ext2FS context. The new APIs are more generic, and map better to the
semantics exported to the userspace, where inode identifiers only appear in
stat() and readdir() output, but never in any input.

This will also hopefully reduce the potential for races (see commit c44b4d61f3).

Lastly, this makes it way more viable to implement a filesystem that only
synthesizes its inodes lazily when queried, and destroys them when they are no
longer in use. With inode identifiers being used to reference inodes, the only
choice for such a filesystem is to persist any inode it has given out the
identifier for, because it might be queried at any later time. With direct
references to inodes, the filesystem will know when the last reference is
dropped and the inode can be safely destroyed.
2020-06-25 15:49:04 +02:00
Brian Gianforcaro
6a74af8063 Kernel: Plumb KResult through FileDescription::read_entire_file() implementation.
Allow file system implementation to return meaningful error codes to
callers of the FileDescription::read_entire_file(). This allows both
Process::sys$readlink() and Process::sys$module_load() to return more
detailed errors to the user.
2020-05-26 10:15:40 +02:00
Andreas Kling
d63b6287f5 Kernel: Add missing casts when calling AK::min() 2020-05-23 15:25:43 +02:00
Yonatan Goldschmidt
3a90a01dd4 Ext2FS: Fix indirect-blocks iteration
For singly-indirect blocks, "callback" is just "add_block".
For doubly-indirect blocks, "callback" is the lambda function
iterating on singly-indirect blocks: so instead of adding itself to the
list, the doubly-indirect block will add all its childs, but they add
themselves again when they run the callback of singly-indirect blocks.
And nothing adds the doubly-indirect block itself :(

This leads to a double free of all child blocks of the doubly-indirect
block, which is the failed assert described in #1549.

Closes: #1549.
2020-05-22 10:50:41 +02:00
Sergey Bugaev
88e23113ae Kernel: Tweak FileBackedFS API to avoid intermediary copies
read_block() and write_block() now accept the count (how many bytes to read
or write) and offset (where in the block to start; defaults to 0). Using these
new APIs, we can avoid doing copies between intermediary buffers in a lot more
cases. Hopefully this improves performance or something.
2020-05-19 11:07:35 +02:00
Liav A
65dd9d5ad3 Kernel: Ensure we flush the entire ext2 superblock 2020-04-06 17:18:36 +02:00
Liav A
ecee76b741 Kernel: Change Ext2FS to be backed by a file instead of a block device
In contrast to the previous patchset that was reverted, this time we use
a "special" method to access a file with block size of 512 bytes (like
a harddrive essentially).
2020-04-06 15:36:36 +02:00
Liav A
a7d708e47d Kernel: Don't enumerate blocks of ext2 symlinks by default
Also, we assert if we encounter a block that is bigger than blocks
count in the superblock.

Fixes #1608.
2020-04-05 15:27:31 +02:00
Andreas Kling
53d0ca2ad8 Kernel: Strip SUID+SGID bits from file when written to or chowned
Fixes #1624.
2020-04-04 19:46:55 +02:00
Andreas Kling
c2a8bbcb59 Revert "Kernel: Change Ext2FS to be backed by a file instead of a block device"
This reverts commit 6b59311d4b.

Reverting these changes since they broke things.
Fixes #1608.
2020-04-03 21:29:03 +02:00
Liav A
6b59311d4b Kernel: Change Ext2FS to be backed by a file instead of a block device
This ensures that we can mount image files as virtual disks without the
need of implementing gross hacks like loopback devices :)
2020-04-02 12:03:08 +02:00
Andreas Kling
7d862dd5fc AK: Reduce header dependency graph of String.h
String.h no longer pulls in StringView.h. We do this by moving a bunch
of String functions out-of-line.
2020-03-23 13:48:44 +01:00
marprok
3cbc2f4381 Ext2FS: Reset the found_a_group flag 2020-03-12 12:35:00 +01:00
Andreas Kling
75a6b27f73 Ext2FS: Remove unused allocate_block()
We only use allocate_blocks() now. If you want a single block, you can
just call allocate_blocks() with a count of 1.
2020-03-06 11:22:23 +01:00
Andreas Kling
8bb361889c AK: Remove Optional::operator bool()
This was causing some obvious-in-hindsight but hard to spot bugs where
we'd implicitly convert the bool to an integer type and carry on with
the number 1 instead of the actual value().
2020-03-06 10:32:58 +01:00
Liav A
0fc60e41dd Kernel: Use klog() instead of kprintf()
Also, duplicate data in dbg() and klog() calls were removed.
In addition, leakage of virtual address to kernel log is prevented.
This is done by replacing kprintf() calls to dbg() calls with the
leaked data instead.
Also, other kprintf() calls were replaced with klog().
2020-03-02 22:23:39 +01:00
Andreas Kling
7cd1bdfd81 Kernel: Simplify some dbg() logging
We don't have to log the process name/PID/TID, dbg() automatically adds
that as a prefix to every line.

Also we don't have to do .characters() on Strings passed to dbg() :^)
2020-02-29 13:39:06 +01:00
Liav A
b0d40e9495 Ext2Filesystem: Use dbg() instead of dbgprintf() 2020-02-27 13:05:12 +01:00
Andreas Kling
ceec1a7d38 AK: Make Vector use size_t for its size and capacity 2020-02-25 14:52:35 +01:00
Andreas Kling
0763f67043 AK: Make Bitmap use size_t for its size
Also rework its API's to return Optional<size_t> instead of int with -1
as the error value.
2020-02-24 09:56:07 +01:00
Andreas Kling
b6887bd9cd Ext2FS: The max current block count of a file is size/block_size
Turns out that i_blocks does not take block list holes into account.
2020-02-21 19:07:23 +01:00
Andreas Kling
59c052a72a Ext2FS: Allow holes in block lists
Linux creates holes in block lists for all-zero content. This is very
reasonable and we can now handle that situation as well.

Note that we're not smart enough to generate these holes ourselves yet,
but now we can at least read from such files.
2020-02-21 17:50:51 +01:00
Andreas Kling
88b9fcb976 AK: Use size_t for ByteBuffer sizes
This matches what we already do for string types.
2020-02-20 13:20:34 +01:00
Andreas Kling
e28809a996 Kernel: Add forward declaration header 2020-02-16 01:50:32 +01:00
Andreas Kling
a356e48150 Kernel: Move all code into the Kernel namespace 2020-02-16 01:27:42 +01:00
Andreas Kling
7291370478 Kernel: Make File::truncate() take a u64
No point in taking a signed type here. We validate at the syscall layer
and then pass around a u64 from then on.
2020-02-08 12:07:04 +01:00
Andreas Kling
42d41fdf94 Kernel: Simplify FS::create_inode() a little bit
Return a KResultOr<NonnullRefPtr<Inode>> instead of returning errors in
an out-parameter.
2020-02-08 11:58:28 +01:00
Andreas Kling
8731682d0e Kernel: Simplify FS::create_directory() a little bit
None of the clients of this function actually used the returned Inode,
so it can simply return a KResult instead.
2020-02-08 02:34:22 +01:00
Andreas Kling
cb97ef5589 Ext2FS: Fail with EMFILE if we would overflow i_links_count 2020-02-08 02:26:33 +01:00
Andreas Kling
88ea152b24 Kernel: Merge unnecessary DiskDevice class into BlockDevice 2020-02-08 02:20:03 +01:00
Andreas Kling
c44b4d61f3 Kernel: Make Inode::lookup() return a RefPtr<Inode>
Previously this API would return an InodeIdentifier, which meant that
there was a race in path resolution where an inode could be unlinked
in between finding the InodeIdentifier for a path component, and
actually resolving that to an Inode object.

Attaching a test that would quickly trip an assertion before.

Test: Kernel/path-resolution-race.cpp
2020-02-01 10:56:17 +01:00
Andreas Kling
1d506a935c Ext2FS: Give names to some KBuffers
The more we give names to KBuffers, the easier it gets to understand
what's what in a kernel region dump. :^)
2020-01-26 10:18:18 +01:00
Marios Prokopakis
da296f5865 Ext2FS: allocate_blocks allocates contiguous blocks (#1095)
This implementation uses the new helper method of Bitmap called
find_longest_range_of_unset_bits. This method looks for the biggest 
range of contiguous bits unset in the bitmap and returns the start of
the range back to the caller.
2020-01-26 09:48:24 +01:00
Andreas Kling
f309381d4e Ext2FS: Use more dbg() in Ext2FS code
We should use dbg() instead of dbgprintf() as much as possible to
protect ourselves against format string bugs. Here's a bunch of
conversions in Ext2FS.
2020-01-25 14:30:53 +01:00
Andreas Kling
94ca55cefd Meta: Add license header to source files
As suggested by Joshua, this commit adds the 2-clause BSD license as a
comment block to the top of every source file.

For the first pass, I've just added myself for simplicity. I encourage
everyone to add themselves as copyright holders of any file they've
added or modified in some significant way. If I've added myself in
error somewhere, feel free to replace it with the appropriate copyright
holder instead.

Going forward, all new source files should include a license header.
2020-01-18 09:45:54 +01:00
Andreas Kling
e91f03cb39 Ext2FS: Assert that inline symlink read/write always uses offset=0 2020-01-15 22:11:44 +01:00
Andreas Kling
9e54c7c17f Ext2FS: Don't allow creating new files in removed directories
Also don't uncache inodes when they reach i_links_count==0 unless they
also have no ref counts other than the +1 from the inode cache.
This prevents the FS from deleting the on-disk inode too soon.
2020-01-15 22:11:44 +01:00
Andreas Kling
4abbedb6e4 Kernel: Allow passing initial UID and GID when creating new inodes
If we're creating something that should have a different owner than the
current process's UID/GID, we need to plumb that all the way through
VFS down to the FS functions.
2020-01-03 20:13:21 +01:00
Andreas Kling
82760998a9 Ext2FS: Take the inode lock in Ext2FSInode::metadata()
Remove an unnecessary InterruptDisabler to make this not assert. :^)
2020-01-03 17:48:02 +01:00
Drew Stratford
ee0eed26f4 Ext2FileSystem: set_metadata_dirty(true) during write_directory().
This adds a call to set_metadata_dirty(true) to
Ext2FS::write_directory(). This fixes a bug wherein InodeWatchers
weren't alerted on directory updates.
2019-11-21 13:04:38 +01:00
Andreas Kling
8ccbd7002b Ext2FS: Rename allocate_inode() => find_a_free_inode()
Since this function doesn't actually mark the inode as allocated,
let's tone down the name a little bit.
2019-11-17 19:19:02 +01:00
Andreas Kling
a712d4ac0c Ext2FS: Writing to a slow symlink should not treat it like a fast one
We would misinterpret short writes to the first 60 bytes of a slow
symlink as writes to a fast symlink.
2019-11-17 19:19:00 +01:00
Andreas Kling
5d08665d9a Ext2FS: Remove unnecessary extra cache lookup in get_inode() 2019-11-17 19:11:19 +01:00
Andreas Kling
ba997c0a72 Ext2FS: Add some FIXME's while browsing this code 2019-11-17 18:59:14 +01:00
Andreas Kling
8d4d63d9b6 Ext2FS: Minor cleanup, remove an unused function 2019-11-16 17:29:09 +01:00
Andreas Kling
59ed235c85 Kernel: Implement O_DIRECT open() flag to bypass disk caches
Files opened with O_DIRECT will now bypass the disk cache in read/write
operations (though metadata operations will still hit the disk cache.)

This will allow us to test actual disk performance instead of testing
disk *cache* performance, if that's what we want. :^)

There's room for improvment here, we're very aggressively flushing any
dirty cache entries for the specific block before reading/writing that
block. This is done by walking the entire cache, which may be slow.
2019-11-05 19:35:12 +01:00
Andreas Kling
721585473b Ext2FS: Don't uncache inodes while they are being watched
If an inode is observed by watch_file(), we won't uncache it.
This allows a program to watch a file without keeping it open.
2019-11-04 17:25:44 +01:00
Andreas Kling
c538648465 Ext2FS: Uncache unused Inodes after flushing contents to disk
Don't keep Inodes around in memory forever after we've interacted with
them once. This is a slight performance pessimization when accessing
the same file repeatedly, but closing it for a while in between.

Longer term we should find a way to keep a limited number of unused
Inodes cached, whichever ones we think are likely to be used again.
2019-11-04 12:23:19 +01:00
Andreas Kling
7e56cf1800 Ext2FS: Lock the filesystem during initialization and during sync
If we get preempted during initialization, we really don't want to try
doing a sync on a partially-initialized filesystem.
2019-11-03 13:56:55 +01:00
Andreas Kling
c1d3ac7108 Ext2FS: Fix unpopulated block list cache after mkdir()
When creating a new directory, we set the initial size to 1 block.
This meant that we were allocating a block up front, but the Inode's
internal block list cache was not populated with this block.

This broke write_bytes() on a new directory, since it assumed that
the block list cache would be up to date if the call to write_bytes()
would not change the directory's size.

This patch fixes the issue in two ways: First, we cache the initial
block list created for new directories.
Second, we now repopulate the block list cache in write_bytes() if it
is empty when we get there. This is basically just a safety fallback
to avoid having this kind of bug in the future.
2019-11-03 10:22:09 +01:00
Andreas Kling
1e36d899f1 Ext2FS: Use KBuffers for the cached bitmap blocks
Also cache the block group descriptor table in a KBuffer on file system
initialization, instead of on first access.

This reduces pressure on the kmalloc heap somewhat.
2019-11-03 00:10:24 +01:00
Andreas Kling
94a6b248ca Ext2FS: Resizing an Inode to its current size should do nothing
We were writing out the full block list whenever Ext2FSInode::resize()
was called, even if the old and new sizes were identical.

This patch makes it a no-op, which drastically improves "cp" speed
since we now take full advantage of the up-front call to ftruncate().
2019-11-02 16:22:29 +01:00
Andreas Kling
5835569527 Ext2FS: Inode resizing should fail with ENOSPC if we lack blocks
If there are not enough free blocks in the filesystem to accomodate
growing an Inode, we should fail with ENOSPC before even starting to
allocate blocks.
2019-11-02 12:53:31 +01:00
Andreas Kling
2ad2210eb4 Ext2FS: Use the bitmap block caching for Inode bitmaps as well
Nothing really shows up on disk_benchmark for this change, but it is
obviously sensible to use the same mechanism here.
2019-11-02 12:34:18 +01:00
Andreas Kling
e52b7eeccc Ext2FS: Rename get_block_bitmap() => get_bitmap_block()
This can be used for Inode bitmaps as well, so let's rename it.
2019-11-02 12:26:20 +01:00
Andreas Kling
1ae9d85de9 Ext2FS: Cache block bitmaps instead of always reading/writing disk
Add a simple cache to Ext2FS where we keep block bitmaps along with a
dirty bit. This allows us to coalesce bitmap flushes, giving us a nice
~3x improvement in disk_benchmark write speeds.
2019-11-02 12:18:43 +01:00
Andreas Kling
3a8b5b405c Ext2FS: Tidy up code related to the Ext2 super block a bit
Store the cached super block as an ext2_super_block member instead of
caching it in a ByteBuffer and using a casting helper everywhere.

This patch also combines reading/writing of the super block into a
single disk device operation (instead of two.)
2019-11-02 11:49:11 +01:00
Andreas Kling
e4b7786b66 Ext2FS: Flush the super block and block group descriptors lazily
Keep dirty bits for these and override flush_writes() so that we can
coalesce writes. Looks like a ~5x write performance bump on the
disk_benchmark.
2019-11-02 11:36:56 +01:00
Andreas Kling
5ab044beae Ext2FS: Make Ext2FSInode::is_directory() fast
This patch overloads Inode::is_directory() with a faster version that
doesn't require instantiating the whole InodeMetadata.

If you have an Ext2FSInode&, calling is_directory() should be instant
since we can just look directly at the raw inode bits.
2019-10-02 13:47:44 +02:00
Andreas Kling
922fd703c9 Kernel: Convert the DiskBackedFS write API to take "const u8*"
This way clients are not required to have instantiated ByteBuffers
and can choose whatever memory scheme works best for them.

Also converted some of the Ext2FS code to use stack buffers instead.
2019-09-30 11:23:36 +02:00
Andreas Kling
1fc2612667 Kernel: Make DiskBackedFS::read_block() write to client-provided memory
Instead of having DiskBackedFS allocate a ByteBuffer, leave it to each
client to provide buffer space.

This is significantly faster in many cases where we can use a stack
buffer and avoid heap allocation entirely.
2019-09-30 11:04:30 +02:00
Andreas Kling
8f45a259fc ByteBuffer: Remove pointer() in favor of data()
We had two ways to get the data inside a ByteBuffer. That was silly.
2019-09-30 08:57:01 +02:00
Conrad Pankoff
062218b4cf Kernel: Support writing doubly-indirect ext2 blocks 2019-09-28 09:29:10 +02:00
Andreas Kling
e364846622 Ext2FS: Don't allocate blocks until we're committed to a new inode
Otherwise we would leak the blocks in case we returned earlier than
expected. :^)
2019-09-22 18:50:24 +02:00
Andreas Kling
bd7c38e7b6 Ext2FS: Oops, fix wrong ENOSPC in create_inode() 2019-09-22 18:44:05 +02:00
Andreas Kling
bff59eff4b Ext2FS: Fix two bugs in block allocation:
1) Off-by-one in block allocation when block size != 1 KB

Due to a quirk in the on-disk layout of ext2, file systems with a block
size of 1 KB have block #1 as their first block, while all others start
on block #0.

2) We had no fallback mechanism when the preferred group was full

We now allocate blocks from the preferred block group as long as it's
possible, and fall back to a simple scan through all groups when the
preferred one is full.
2019-09-22 18:37:17 +02:00
Andreas Kling
b9be6b7bb4 Ext2FS: Trying to create a too-long directory entry should ENAMETOOLONG
Also added some assertions to DirectoryEntry in case someone tries to
instantiate them with names that would overflow the name buffer.

DirectoryEntry is a crappy data structure, and the name buffer is also
crappy. Added a FIXME about replacing it with something nicer.

Before this patch, the DirectoryEntry::name buffer would overflow if
you did "touch extremely-long-file-name". Duh.

Fixes #538.
2019-09-10 21:04:27 +02:00
Andreas Kling
ac7a559d96 Ext2FS: Avoid a String allocation in lookup()
By using find() with a custom finder, we can avoid creating a temporary
key value that's only used for the hash lookup.
2019-08-25 06:45:37 +02:00
Andreas Kling
da7ae52eee Ext2FS: Clean up prepare_to_unmount() a little bit 2019-08-17 13:49:37 +02:00
Jesse Buhagiar
bc22456f89 Kernel: Added unmount ability to VFS
It is now possible to unmount file systems from the VFS via `umount`.
It works via looking up the `fsid` of the filesystem from the `Inode`'s
metatdata so I'm not sure how fragile it is. It seems to work for now
though as something to get us going.
2019-08-17 09:29:54 +02:00
Andreas Kling
4afafeae50 Ext2FS: Make some use of Vector::empend(). 2019-08-01 16:31:05 +02:00
Andreas Kling
ecb1b93d53 Ext2FS: Fix fetching of the major/minor device numbers for st_rdev.
This is how it seems to work:

- If ext2_inode.i_blocks[0] is non-zero, it contains the major/minor.
- Otherwise, it's in ext2_inode.i_blocks[1].
2019-07-31 17:24:54 +02:00
Andreas Kling
3b588b7dc0 Ext2FS: Put most debug logging behind EXT2_DEBUG.
The debug output was basically dominated by Ext2FS spam.
2019-07-21 18:38:14 +02:00
Andreas Kling
5254a320d8 Kernel: Remove use of copy_ref() in favor of regular RefPtr copies.
This is obviously more readable. If we ever run into a situation where
ref count churn is actually causing trouble in the future, we can deal with
it then. For now, let's keep it simple. :^)
2019-07-11 15:40:04 +02:00
Andreas Kling
0e75aba7c3 StringView: Rename characters() to characters_without_null_termination().
This should make you think twice before trying to use the const char* from
a StringView as if it's a null-terminated string.
2019-07-08 15:38:44 +02:00
Andreas Kling
27f699ef0c AK: Rename the common integer typedefs to make it obvious what they are.
These types can be picked up by including <AK/Types.h>:

* u8, u16, u32, u64 (unsigned)
* i8, i16, i32, i64 (signed)
2019-07-03 21:20:13 +02:00
Andreas Kling
90b1354688 AK: Rename RetainPtr => RefPtr and Retained => NonnullRefPtr. 2019-06-21 18:37:47 +02:00
Andreas Kling
77b9fa89dd AK: Rename Retainable => RefCounted.
(And various related renames that go along with it.)
2019-06-21 15:30:03 +02:00
Sergey Bugaev
75df45d709 Kernel: Fix comparing StringViews with strcmp().
StringView character buffer is not guaranteed to be null-terminated;
in particular it will not be null-terminated when making a substring.
This means that the buffer can not be used with C functions that expect
a null-terminated string. Instead, StringView provides a convinient
operator == for comparing it with Strings and C stirngs, so use that.

This fixes /proc/self/... resolution failures in ProcFS, since the name
("self") passed to ProcFSInode::lookup() would not be null-terminated.
2019-06-12 16:14:29 +02:00
Andreas Kling
51d70996ba Ext2FS: The block numbers returned by allocate_blocks() should be 1-based.
e2fsck complained about two inodes sharing the same block, and this was why.
2019-06-09 14:59:46 +02:00
Andreas Kling
7562c0b7bf Ext2FS: Fix wrong file mode being passed from create_inode() to add_child(). 2019-06-09 12:48:34 +02:00
Andreas Kling
6873e7d016 Ext2FS: Move directory writing logic into Ext2FSInode. 2019-06-09 12:46:23 +02:00
Andreas Kling
8258b699db Kernel: Use StringView more in Inode and subclasses. 2019-06-09 10:25:19 +02:00
Andreas Kling
891d4c4834 Kernel: Qualify a bunch of #include statements. 2019-06-07 19:29:34 +02:00