linux-apfs / linux-apfs-rw

APFS module for linux, with experimental write support
GNU General Public License v2.0
510 stars 34 forks source link

Does not compile on Linux 5.14.1 #19

Closed Luflosi closed 3 years ago

Luflosi commented 3 years ago

The latest commit from the develop branch does not compile on Linux 5.14.1. Here is the relevant build log:

/build/source/inode.c: In function 'apfs_do_ioc_setflags':
/build/source/inode.c:1807:8: error: implicit declaration of function 'vfs_ioc_setflags_prepare' [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wimplicit-function-declaration-Werror=implicit-function-declaration8;;]
 1807 |  err = vfs_ioc_setflags_prepare(inode, oldflags, newflags);
      |        ^~~~~~~~~~~~~~~~~~~~~~~~
/build/source/inode.c: In function 'apfs_ioc_setflags':
/build/source/inode.c:1844:30: error: passing argument 1 of 'inode_owner_or_capable' from incompatible pointer type [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wincompatible-pointer-types-Werror=incompatible-pointer-types8;;]
 1844 |  if (!inode_owner_or_capable(inode))
      |                              ^~~~~
      |                              |
      |                              struct inode *
In file included from /nix/store/iswyx074r0h6k9dlbf53mhwddwjb1ri8-linux-5.14.1-dev/lib/modules/5.14.1/source/include/linux/buffer_head.h:12,
                 from /build/source/inode.c:7:
/nix/store/iswyx074r0h6k9dlbf53mhwddwjb1ri8-linux-5.14.1-dev/lib/modules/5.14.1/source/include/linux/fs.h:1888:52: note: expected 'struct user_namespace *' but argument is of type 'struct inode *'
 1888 | bool inode_owner_or_capable(struct user_namespace *mnt_userns,
      |                             ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
/build/source/inode.c:1844:7: error: too few arguments to function 'inode_owner_or_capable'
 1844 |  if (!inode_owner_or_capable(inode))
      |       ^~~~~~~~~~~~~~~~~~~~~~
In file included from /nix/store/iswyx074r0h6k9dlbf53mhwddwjb1ri8-linux-5.14.1-dev/lib/modules/5.14.1/source/include/linux/buffer_head.h:12,
                 from /build/source/inode.c:7:
/nix/store/iswyx074r0h6k9dlbf53mhwddwjb1ri8-linux-5.14.1-dev/lib/modules/5.14.1/source/include/linux/fs.h:1888:6: note: declared here
 1888 | bool inode_owner_or_capable(struct user_namespace *mnt_userns,
      |      ^~~~~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors

Let me know if I can provide any additional information.

Luflosi commented 3 years ago

I overlooked that it also doesn't compile for Linux 5.13.9 with the same error message and maybe some other versions I didn't test yet. I think a recent commit broke compilation.

eafer commented 3 years ago

Thanks! I just pushed a patch, I think it should be fine because I build-tested it myself this time.

Luflosi commented 3 years ago

Thanks. Indeed, it does compile for Linux 5.4, 5.13 and 5.14 but 4.9, 4.14 and 1.19 don't: 4.9.282:

/build/source/file.c:8:8: error: unknown type name 'vm_fault_t'
    8 | static vm_fault_t apfs_page_mkwrite(struct vm_fault *vmf)
      |        ^~~~~~~~~~
/build/source/file.c: In function 'apfs_page_mkwrite':
/build/source/file.c:10:34: error: 'struct vm_fault' has no member named 'vma'
   10 |  struct vm_area_struct *vma = vmf->vma;
      |                                  ^~
/build/source/file.c:12:38: error: 'struct vm_fault' has no member named 'vma'
   12 |  struct inode *inode = file_inode(vmf->vma->vm_file);
      |                                      ^~
/build/source/file.c:15:2: error: unknown type name 'vm_fault_t'
   15 |  vm_fault_t ret = VM_FAULT_LOCKED;
      |  ^~~~~~~~~~
/build/source/file.c:23:22: error: 'struct vm_fault' has no member named 'vma'
   23 |  file_update_time(vmf->vma->vm_file);
      |                      ^~
/build/source/file.c: At top level:
/build/source/file.c:93:18: error: initialization of 'int (*)(struct vm_area_struct *, struct vm_fault *)' from incompatible pointer type 'int (*)(struct vm_fault *)' [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wincompatible-pointer-types^G-Werror=incompatible-pointer-types8;;^G]
   93 |  .page_mkwrite = apfs_page_mkwrite,
      |                  ^~~~~~~~~~~~~~~~~
/build/source/file.c:93:18: note: (near initialization for 'apfs_file_vm_ops.page_mkwrite')

4.14.246:

/build/source/file.c:8:8: error: unknown type name 'vm_fault_t'
    8 | static vm_fault_t apfs_page_mkwrite(struct vm_fault *vmf)
      |        ^~~~~~~~~~
/build/source/file.c: In function 'apfs_page_mkwrite':
/build/source/file.c:15:2: error: unknown type name 'vm_fault_t'
   15 |  vm_fault_t ret = VM_FAULT_LOCKED;
      |  ^~~~~~~~~~

4.19.206:

/build/source/inode.c: In function 'apfs_do_ioc_setflags':
/build/source/inode.c:1828:8: error: implicit declaration of function 'vfs_ioc_setflags_prepare' [8;;https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Wimplicit-function-declaration^G-Werror=implicit-function-declaration8;;^G]
 1828 |  err = vfs_ioc_setflags_prepare(inode, oldflags, newflags);
      |        ^~~~~~~~~~~~~~~~~~~~~~~~
eafer commented 3 years ago

This should cover it, but I didn't run a build myself this time.

Luflosi commented 3 years ago

Unfortunately it still fails to compile for 4.9 and 4.14. 4.9.282:

/build/source/file.c: In function 'apfs_page_mkwrite':
/build/source/file.c:21:38: error: 'struct vm_fault' has no member named 'vma'
   21 |  struct inode *inode = file_inode(vmf->vma->vm_file);
      |                                      ^~
/build/source/file.c:32:22: error: 'struct vm_fault' has no member named 'vma'
   32 |  file_update_time(vmf->vma->vm_file);
      |                      ^~

4.14.246:

/build/source/inode.c:513:20: error: 'noop_invalidatepage' undeclared here (not in a function); did you mean 'do_invalidatepage'?
  513 |  .invalidatepage = noop_invalidatepage,
      |                    ^~~~~~~~~~~~~~~~~~~
      |                    do_invalidatepage

Would you like me to show you how I test compilation using Nix?

eafer commented 3 years ago

Would you like me to show you how I test compilation using Nix?

Thanks, but that's okay. The problem I have is that after checking out a different kernel version to use its headers, I have to rebuild 5.3, which is the one I use. It's a bit annoying, but I need to stop being lazy and just do it. I'll push patches for this (tested this time) in a minute.

eafer commented 3 years ago

Ok, this time it should be fine.

Luflosi commented 3 years ago

Yep, everything compiles fine now. Thanks!

Since your current workflow seems to cost you so much time, I thought, I would show you anyways. Install Nix from https://nixos.org/download.html#nix-quick-install. Create a new file shell.nix in the root of linux-apfs-rw with the following contents:

{ kernel ? "linux_latest", pkgs ? import <nixpkgs> { } }:
with pkgs;

mkShell rec {
  kernel' = pkgs."${kernel}".dev;

  nativeBuildInputs = kernel'.moduleBuildDependencies;

  shellHook = ''
    export KERNELRELEASE=${kernel'.modDirVersion}
    export KERNEL_DIR=${kernel'.dev}/lib/modules/${kernel'.modDirVersion}/build
  '';
}

Then execute nix-shell --argstr kernel linux_4_9, which will "install" the kernel headers in a newly spawned temporary shell. Then simply execute make as normal. Nixpkgs currently contains the Linux versions 4.4, 4.9, 4.14, 4.19, 5.4, 5.10, 5.13, 5.14 and some other kernels like hardened variants and the libre kernels. Once a kernel version is cached, entering the environment with nix-shell is fairly fast. I'm sure there is some way to automatically build and even test the kernel module for all kernel versions, even in CI but I didn't try that yet.