4 Commits
Author SHA1 Message Date
Ernesto A. Fernández d4799475db 0.3.3
This release fixes builds for kernels below 5.3, which have all been
broken for a while. So far development has only been focused on Linux
5.3, and I've relied on reporters to find out about issues on other
versions. From now on I will at least run builds for a range of kernels
before each release, so hopefully this won't happen again.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2023-05-24 23:05:25 -03:00
Ernesto A. Fernández c54e3a7423 Silence b_blocknr width warnings on old kernels
While fixing the build for old kernels, I noticed that in some of them
you get a warning when you prink a buffer head's b_blocknr as 0x%llx.
I haven't checked but I'm guessing that, at some point, sector_t on
64-bit archs went from being 'unsigned long' to 'unsigned long long',
so these warnings went away. Anyway, just cast b_blocknr before printing
it in all kernels.

At some point I do need to attempt a 32-bit build though. It's been a
long time, and I'm sure there will be much worse problems than this one.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2023-05-19 18:49:38 -03:00
Ernesto A. Fernández b185ce13bd Fix builds before generic_copy_file_range()
Even with the previous patch, builds are still broken for all kernels
before 5.2. The problem is that generic_copy_file_range() wasn't
introduced until Linux 5.3. The good news is that we don't actually need
it for older kernels: as I explained in the commit message for the patch
that broke this, we can just returning an error code from
apfs_remap_file_range().

Fixes: 396650b056 ("Don't let copy_file_range() use clones")
Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2023-05-19 18:31:51 -03:00
Ernesto A. Fernández 42d70a8997 Fix build for kernels with separate clone/dedupe
Luflosi reports that the build is broken once again for Linux 4.14 and
4.19:

  https://github.com/linux-apfs/linux-apfs-rw/issues/43

The problem here is that the clone and dedupe operations used to be
implemented with separate methods. Since Linux 4.20, they both use the
same ->remap_file_range(), with some flags passed to tell them apart.
So when I implemented clones I used this new version and broke the build
for the old ones. Fix it now.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2023-05-19 18:31:51 -03:00
6 changed files with 22 additions and 4 deletions

No files matched your search

+4
View File
@@ -885,7 +885,11 @@ extern int apfs_get_new_block(struct inode *inode, sector_t iblock,
struct buffer_head *bh_result, int create);
extern int APFS_GET_NEW_BLOCK_MAXOPS(void);
extern int apfs_truncate(struct apfs_dstream_info *dstream, loff_t new_size);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
extern loff_t apfs_remap_file_range(struct file *src_file, loff_t off, struct file *dst_file, loff_t destoff, loff_t len, unsigned int remap_flags);
#else
extern int apfs_clone_file_range(struct file *src_file, loff_t off, struct file *dst_file, loff_t destoff, u64 len);
#endif
extern int apfs_clone_extents(struct apfs_dstream_info *dstream, u64 new_id);
/* file.c */
+1 -1
View File
@@ -1,5 +1,5 @@
PACKAGE_NAME="linux-apfs-rw"
PACKAGE_VERSION="0.3.2"
PACKAGE_VERSION="0.3.3"
BUILT_MODULE_NAME[0]="apfs"
DEST_MODULE_LOCATION[0]="/extra"
+6
View File
@@ -1636,7 +1636,11 @@ int apfs_truncate(struct apfs_dstream_info *dstream, loff_t new_size)
return apfs_create_hole(dstream, old_blks, new_blks);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
loff_t apfs_remap_file_range(struct file *src_file, loff_t off, struct file *dst_file, loff_t destoff, loff_t len, unsigned int remap_flags)
#else
int apfs_clone_file_range(struct file *src_file, loff_t off, struct file *dst_file, loff_t destoff, u64 len)
#endif
{
struct inode *src_inode = file_inode(src_file);
struct inode *dst_inode = file_inode(dst_file);
@@ -1651,8 +1655,10 @@ loff_t apfs_remap_file_range(struct file *src_file, loff_t off, struct file *dst
const u64 xfield_flags = APFS_INODE_MAINTAIN_DIR_STATS | APFS_INODE_IS_SPARSE | APFS_INODE_HAS_PURGEABLE_FLAGS;
int err;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
if (remap_flags & ~(REMAP_FILE_ADVISORY))
return -EINVAL;
#endif
if (src_inode == dst_inode)
return -EINVAL;
+8
View File
@@ -145,8 +145,16 @@ const struct file_operations apfs_file_operations = {
.open = generic_file_open,
.fsync = apfs_fsync,
.unlocked_ioctl = apfs_file_ioctl,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0)
.copy_file_range = generic_copy_file_range,
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
.remap_file_range = apfs_remap_file_range,
#else
.clone_file_range = apfs_clone_file_range,
#endif
};
#if LINUX_VERSION_CODE == KERNEL_VERSION(5, 3, 0)
+2 -2
View File
@@ -138,12 +138,12 @@ struct apfs_node *apfs_read_node(struct super_block *sb, u64 oid, u32 storage,
if (nxi->nx_flags & APFS_CHECK_NODES && !apfs_obj_verify_csum(sb, bh)) {
/* TODO: don't check this twice for virtual/physical objects */
apfs_err(sb, "bad checksum for node in block 0x%llx", bh->b_blocknr);
apfs_err(sb, "bad checksum for node in block 0x%llx", (unsigned long long)bh->b_blocknr);
apfs_node_free(node);
return ERR_PTR(-EFSBADCRC);
}
if (!apfs_node_is_valid(sb, node)) {
apfs_err(sb, "bad node in block 0x%llx", bh->b_blocknr);
apfs_err(sb, "bad node in block 0x%llx", (unsigned long long)bh->b_blocknr);
apfs_node_free(node);
return ERR_PTR(-EFSCORRUPTED);
}
+1 -1
View File
@@ -383,7 +383,7 @@ struct buffer_head *apfs_read_object_block(struct super_block *sb, u64 bno, bool
if (!preserve) {
err = apfs_free_queue_insert(sb, bh->b_blocknr, 1);
if (err)
apfs_err(sb, "free queue insertion failed for 0x%llx", bh->b_blocknr);
apfs_err(sb, "free queue insertion failed for 0x%llx", (unsigned long long)bh->b_blocknr);
} else if ((type & APFS_OBJECT_TYPE_MASK) != APFS_OBJECT_TYPE_FS) {
vsb_raw = APFS_SB(sb)->s_vsb_raw;
apfs_assert_in_transaction(sb, &vsb_raw->apfs_o);