The official documentation defined APFS_DREC_HASH_MASK incorrectly, and
this bug was later copied into the module. The macro has been unused so
far but the next commit will change that, so get it fixed.
Fixes: 5ba903dba3 ("apfs: fix directory entry structures")
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
The official documentation defines a couple of macros for working with
the name_len_and_hash field of a dentry key. They were introduced in
the module by commit 5ba903dba3 ("apfs: fix directory entry
structures"), but I forgot about them and they remain unused.
So, replace the magic numbers in the dentry code with these macros. In
apfs_init_drec_hashed_key(), remove the redundant mask before the shift.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Object maps may have more than one record for each object id; I believe
this is caused by snapshots. Queries are currently returning any of
them at random, so the mounted volume may seem inconsistent or outdated.
They should always return the latest.
To this end, use the transaction id from the container superblock and
perform a nonexact search. We could just use the maximum possible xid
instead, but this is cleaner and will be easier to extend to support
reading old snapshots.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Mention the existence of the apfsprogs project in the documentation for
the module.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
By mistake, the macro guard of object.h was given a name that is prone
to collision. Rename it to specify the module.
Fixes: 303360577a ("apfs: move object code to separate files")
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Get rid of all unnecessary include directives in header files. Also add
a couple of missing structure declarations, which haven't been a problem
so far because they appear in other headers.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
A multiple query that reaches an empty node simply assumes that all of
its records were already read, and continues with the next one. A
crafted filesystem with a large number of empty nodes could keep this
spinning for a while.
I don't think there is any legitimate reason for empty nodes to exist on
disk, so just declare them corrupted in apfs_node_is_valid().
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
There is no reason to set the individual fields of stat->btime
explicitly; just copy the whole ai->i_crtime structure.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Give credit to Gabriel and Arnaud for their contributions, and also add
a link to the official specification for the filesystem.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
The superblock in block zero is only certain to be the latest if the
filesystem was unmounted cleanly. Otherwise, there may be a more recent
valid superblock among the checkpoint descriptors, so work with that one
instead.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Currently, the superblock read by apfs_map_main_super() is not the
latest, but the copy made on the last clean unmount. Before we fix
this, move the code into a new apfs_read_super_copy() to keep the
function simple.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Verify the checksums for not only the container superblock, but also the
volume superblock and the object maps.
As for the b-tree nodes, checking them has a big impact in performance,
probably because too many are being read repeatedly. This will
hopefully improve in the future, but for now provide a mount option to
let the user decide what to do.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Create the object.c and object.h files. The intention is to be able to
verify the checksum of objects other than the superblock.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Following ext4 and xfs, define the EFSBADCRC error code as an alias for
EBADMSG, and use it to signal failure to verify the checksum for a
filesystem object.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
For the sake of consistency, make explicit the extern declarations of
apfs_node_get() and apfs_node_put() in node.h. Also add an extra line
break before the end.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Since apfs_node_locate_key() and apfs_node_locate_data() are now only
used in the context of node queries, make them static functions and
remove their declarations from the header.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Currently, apfs_count_used_blocks() assumes that the object map for the
container only has one level. I'm not sure if that can be wrong, but
rework the function anyway, using apfs_omap_lookup_block().
This change requires several lookups, as opposed to just reading all
the records one by one, so it may have an impact in the performance of
statfs when the filesystem has many volumes. I don't expect anyone will
mind.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Before doing anything else, apfs_map_volume_super() must check that the
volume number specified by the user is not so large as to force an
out-of-bounds read. The specification only allows 100 volumes, which
will always fit in a single block. So, just check that the volume
number is below 100.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
The flags variable in apfs_node_locate_data() and apfs_node_locate_key()
has been unused since commit d060b68813 ("apfs: fix apfs_table_is_*
functions"). Get rid of it.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
The original paper I followed used 'table' instead of 'node', and 'node'
instead of 'object'. Follow the terminology from the specification
instead, and fix a number of related confusions in the comments.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Check that the file type of a directory record is valid before emitting
it. If that's not the case respond like the other modules: don't return
an error, but emit the type as DT_UNKNOWN.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>
Since it doesn't really belong in btree.c, move the logic of
apfs_cat_resolve() directly into apfs_inode_by_name(), which was a
strange unnecessary wrapper for it.
Signed-off-by: Ernesto A. Fernández <ernesto.mnd.fernandez@gmail.com>