10 Commits
Author SHA1 Message Date
Ernesto A. Fernández 1db8a6d92a 0.3.18
This release adds support for the upcoming 6.19 kernel version.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2026-01-30 18:44:25 -03:00
Ernesto A. Fernández a3bca211bd Don't access inode state directly in 6.19
The build is broken for the 6.19 release candidate:

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

The problem is that the inode i_state field can no longer be accessed
directly. Switch to the new helpers, using a wrapper to keep the code
consistent for all kernel versions.

Note that I always use the *_raw version of the helpers to avoid a lockdep
check that will not pass. I can't tell for sure if this is a bug.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-12-30 20:51:14 -03:00
Ernesto A. Fernández de721cd995 0.3.17
This release adds support for the upcoming 6.18 kernel version.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-11-26 18:28:54 -03:00
Ernesto A. Fernández 0daf28cef7 Always treat ->d_name as const
The build is broken for the 6.18 release candidate:

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

The problem is that ->d_name has become const, and that qualifier gets
dropped when we pass it around in the driver. Just treat is as const for
all kernel versions.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-10-27 22:30:27 -03:00
Ernesto A. Fernández c76aecff25 0.3.16
This release adds support for the upcoming 6.17 kernel version.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-09-27 13:17:31 -03:00
Ernesto A. Fernández 714202fefa Set dentry operations in the new way
Once more, the build is still broken for the 6.17 release candidate.
This time the problem is that we are no longer allowed to set s_d_op
directly. Use the new helper instead.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-09-16 14:02:10 -03:00
Ernesto A. Fernández 44db9dc02e Fix the apfs_write_begin/end() type for 6.17
The build is still broken for the 6.17 release candidate. The problem is
that ->write_begin() and ->write_end() now take a kiocb struct as the
first argument instead of a file. Add the proper version checks. The
driver does nothing with this argument but pass it along, so continue to
call it "file" to keep the patch simple.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-09-16 13:43:22 -03:00
Ernesto A. Fernández aefae5433f Rename "struct fileattr" to "struct file_kattr"
The build is broken for the 6.17 release candidate:

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

Upstream has renamed the fileattr struct to file_kattr, so that needs to
happen here as well. To avoid excessive nesting of version checks, don't
change the actual code and just rewrite it on build time with a macro. I
hope this doesn't cause any trouble in the future...

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-09-15 20:15:01 -03:00
Ernesto A. Fernández de4083a506 0.3.15
This release adds support for the upcoming 6.16 kernel version.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-07-25 19:27:24 -03:00
Ernesto A. Fernández a3c23dffc3 Don't reference page index in 6.16
The build is broken for the 6.16 release candidate:

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

The problem is that the page struct no longer has a member called
"index". Use folios for this instead.

Signed-off-by: Ernesto A. Fernández <ernesto@corellium.com>
2025-07-01 20:45:23 -03:00
8 changed files with 77 additions and 12 deletions

No files matched your search

+36
View File
@@ -1021,8 +1021,13 @@ extern struct inode *apfs_new_inode(struct inode *dir, umode_t mode,
extern int apfs_create_inode_rec(struct super_block *sb, struct inode *inode,
struct dentry *dentry);
extern int apfs_inode_create_exclusive_dstream(struct inode *inode);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
extern int __apfs_write_begin(const struct kiocb *iocb, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct page **pagep, void **fsdata);
extern int __apfs_write_end(const struct kiocb *iocb, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int copied, struct page *page, void *fsdata);
#else
extern int __apfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct page **pagep, void **fsdata);
extern int __apfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int copied, struct page *page, void *fsdata);
#endif
extern int apfs_dstream_adj_refcnt(struct apfs_dstream_info *dstream, u32 delta);
#if LINUX_VERSION_CODE < KERNEL_VERSION(5, 12, 0)
@@ -1061,6 +1066,10 @@ extern int apfs_getattr(struct mnt_idmap *idmap,
extern int apfs_crypto_adj_refcnt(struct super_block *sb, u64 crypto_id, int delta);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
#define fileattr file_kattr
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 3, 0) || RHEL_VERSION_GE(9, 6)
extern int apfs_fileattr_get(struct dentry *dentry, struct fileattr *fa);
extern int apfs_fileattr_set(struct mnt_idmap *idmap, struct dentry *dentry, struct fileattr *fa);
@@ -1207,6 +1216,33 @@ static inline void apfs_assert_query_is_valid(const struct apfs_query *query)
#define page_has_buffers(page) folio_buffers(page_folio(page))
#endif
static inline int apfs_inode_state_read_once(struct inode *inode)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 19, 0)
return inode_state_read_once(inode);
#else
return inode->i_state;
#endif
}
static inline void apfs_inode_state_set_raw(struct inode *inode, int flags)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 19, 0)
inode_state_set_raw(inode, flags);
#else
inode->i_state |= flags;
#endif
}
static inline void apfs_inode_state_clear_raw(struct inode *inode, int flags)
{
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 19, 0)
inode_state_clear_raw(inode, flags);
#else
inode->i_state &= ~flags;
#endif
}
/*
* TODO: the following are modified variants of buffer head functions that will
* work with the shared block device for the container. The correct approach
+4
View File
@@ -422,7 +422,11 @@ static int apfs_compress_readpage(struct file *filp, struct page *page)
loff_t off;
/* Mostly copied from ext4_read_inline_page() */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0)
off = page_folio(page)->index << PAGE_SHIFT;
#else
off = page->index << PAGE_SHIFT;
#endif
addr = kmap(page);
ret = apfs_compress_file_read_page(filp, addr, off);
flush_dcache_page(page);
+7 -6
View File
@@ -261,7 +261,7 @@ const struct file_operations apfs_dir_operations = {
*
* Returns the length of the key, or a negative error code in case of failure.
*/
static int apfs_build_dentry_unhashed_key(struct qstr *qname, u64 parent_id,
static int apfs_build_dentry_unhashed_key(const struct qstr *qname, u64 parent_id,
struct apfs_drec_key **key_p)
{
struct apfs_drec_key *key;
@@ -290,7 +290,7 @@ static int apfs_build_dentry_unhashed_key(struct qstr *qname, u64 parent_id,
*
* Returns the length of the key, or a negative error code in case of failure.
*/
static int apfs_build_dentry_hashed_key(struct qstr *qname, u64 hash, u64 parent_id,
static int apfs_build_dentry_hashed_key(const struct qstr *qname, u64 hash, u64 parent_id,
struct apfs_drec_hashed_key **key_p)
{
struct apfs_drec_hashed_key *key;
@@ -363,7 +363,7 @@ static int apfs_build_dentry_val(struct inode *inode, u64 sibling_id,
*
* Returns 0 on success or a negative error code in case of failure.
*/
static int apfs_create_dentry_rec(struct inode *inode, struct qstr *qname,
static int apfs_create_dentry_rec(struct inode *inode, const struct qstr *qname,
u64 parent_id, u64 sibling_id)
{
struct super_block *sb = inode->i_sb;
@@ -426,7 +426,7 @@ static int apfs_build_sibling_val(struct dentry *dentry,
struct apfs_sibling_val **val_p)
{
struct apfs_sibling_val *val;
struct qstr *qname = &dentry->d_name;
const struct qstr *qname = &dentry->d_name;
u16 namelen = qname->len + 1; /* We count the null-termination */
struct inode *parent = d_inode(dentry->d_parent);
int val_len;
@@ -1255,9 +1255,10 @@ static void __apfs_undo_unlink(struct dentry *dentry)
{
struct inode *inode = d_inode(dentry);
inode->i_state |= I_LINKABLE; /* Silence warning about nlink 0->1 */
/* Silence warning about nlink 0->1 */
apfs_inode_state_set_raw(inode, I_LINKABLE);
inc_nlink(inode);
inode->i_state &= ~I_LINKABLE;
apfs_inode_state_clear_raw(inode, I_LINKABLE);
apfs_undo_delete_dentry(dentry);
}
+1 -1
View File
@@ -1,5 +1,5 @@
PACKAGE_NAME="linux-apfs-rw"
PACKAGE_VERSION="0.3.14"
PACKAGE_VERSION="0.3.18"
BUILT_MODULE_NAME[0]="apfs"
DEST_MODULE_LOCATION[0]="/extra"
+4
View File
@@ -72,7 +72,11 @@ static vm_fault_t apfs_page_mkwrite(struct vm_fault *vmf)
}
size = i_size_read(inode);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 16, 0)
if (page_folio(page)->index == size >> PAGE_SHIFT)
#else
if (page->index == size >> PAGE_SHIFT)
#endif
len = size & ~PAGE_MASK;
else
len = PAGE_SIZE;
+20 -4
View File
@@ -470,7 +470,11 @@ out:
return ret;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
int __apfs_write_begin(const struct kiocb *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct page **pagep, void **fsdata)
#else
int __apfs_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int flags, struct page **pagep, void **fsdata)
#endif
{
struct inode *inode = mapping->host;
struct apfs_dstream_info *dstream = &APFS_I(inode)->i_dstream;
@@ -584,7 +588,11 @@ out_put_page:
return err;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
static int apfs_write_begin(const struct kiocb *file, struct address_space *mapping,
loff_t pos, unsigned int len,
struct folio **foliop, void **fsdata)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
static int apfs_write_begin(struct file *file, struct address_space *mapping,
loff_t pos, unsigned int len,
struct folio **foliop, void **fsdata)
@@ -629,7 +637,11 @@ fail:
return err;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
int __apfs_write_end(const struct kiocb *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int copied, struct page *page, void *fsdata)
#else
int __apfs_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned int len, unsigned int copied, struct page *page, void *fsdata)
#endif
{
struct inode *inode = mapping->host;
struct apfs_dstream_info *dstream = &APFS_I(inode)->i_dstream;
@@ -652,7 +664,11 @@ int __apfs_write_end(struct file *file, struct address_space *mapping, loff_t po
return ret;
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
static int apfs_write_end(const struct kiocb *file, struct address_space *mapping,
loff_t pos, unsigned int len, unsigned int copied,
struct folio *folio, void *fsdata)
#elif LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0)
static int apfs_write_end(struct file *file, struct address_space *mapping,
loff_t pos, unsigned int len, unsigned int copied,
struct folio *folio, void *fsdata)
@@ -1021,7 +1037,7 @@ struct inode *apfs_iget(struct super_block *sb, u64 cnid)
inode = apfs_iget_locked(sb, cnid);
if (!inode)
return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW))
if (!(apfs_inode_state_read_once(inode) & I_NEW))
return inode;
down_read(&nxi->nx_big_sem);
@@ -1133,7 +1149,7 @@ int apfs_getattr(struct mnt_idmap *idmap,
*
* Returns the length of the value, or a negative error code in case of failure.
*/
static int apfs_build_inode_val(struct inode *inode, struct qstr *qname,
static int apfs_build_inode_val(struct inode *inode, const struct qstr *qname,
struct apfs_inode_val **val_p)
{
struct apfs_inode_val *val;
+4
View File
@@ -1585,7 +1585,11 @@ static int apfs_fill_super(struct super_block *sb, void *data, int silent)
goto failed_cat;
sb->s_op = &apfs_sops;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 17, 0)
set_default_d_op(sb, &apfs_dentry_operations);
#else
sb->s_d_op = &apfs_dentry_operations;
#endif
sb->s_xattr = apfs_xattr_handlers;
sb->s_maxbytes = MAX_LFS_FILESIZE;
sb->s_time_gran = 1; /* Nanosecond granularity */
+1 -1
View File
@@ -468,7 +468,7 @@ int apfs_transaction_flush_all_inodes(struct super_block *sb)
curr_err = apfs_update_inode(inode, NULL /* new_name */);
if (curr_err)
err = curr_err;
inode->i_state &= ~I_DIRTY_ALL;
apfs_inode_state_clear_raw(inode, I_DIRTY_ALL);
/*
* The same inode may get dirtied again as soon as we release