The branch main has been updated by dumbbell:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=1de8fcf419fce890474271215dce3b6e4876b60a

commit 1de8fcf419fce890474271215dce3b6e4876b60a
Author:     Jean-Sébastien Pédron <dumbb...@freebsd.org>
AuthorDate: 2025-01-01 13:11:14 +0000
Commit:     Jean-Sébastien Pédron <dumbb...@freebsd.org>
CommitDate: 2025-01-31 16:00:49 +0000

    linuxkpi: Add Linux 6.7 `get_file_rcu()` variant
    
    [Why]
    In Linux 6.7, the signature of `get_file_rcu()` changed significantly,
    going from:
    
        bool get_file_rcu(struct linux_file *f);
    
    ... to:
    
        struct linux_file * get_file_rcu(struct linux_file **f);
    
    I.e., both the argument and the return value changed in an incompatible
    way.
    
    This is used by the i915 DRM driver.
    
    [How]
    This patch introduces the variant and hide the new prototype behind
    `LINUXKPI_VERSION >= 60700`.
    
    Reviewed by:    manu
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D48756
---
 sys/compat/linuxkpi/common/include/linux/fs.h |  5 ++++
 sys/compat/linuxkpi/common/src/linux_compat.c | 39 +++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h 
b/sys/compat/linuxkpi/common/include/linux/fs.h
index d277b717423f..86b922ac9a1d 100644
--- a/sys/compat/linuxkpi/common/include/linux/fs.h
+++ b/sys/compat/linuxkpi/common/include/linux/fs.h
@@ -264,12 +264,17 @@ get_file(struct linux_file *f)
        return (f);
 }
 
+struct linux_file * linux67_get_file_rcu(struct linux_file **f);
+#if defined(LINUXKPI_VERSION) && LINUXKPI_VERSION >= 60700
+#define        get_file_rcu(f) linux67_get_file_rcu(f)
+#else
 static inline bool
 get_file_rcu(struct linux_file *f)
 {
        return (refcount_acquire_if_not_zero(
            f->_file == NULL ? &f->f_count : &f->_file->f_count));
 }
+#endif
 
 static inline struct inode *
 igrab(struct inode *inode)
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c 
b/sys/compat/linuxkpi/common/src/linux_compat.c
index ec3ccb16b47d..e5049a4b8f43 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -75,6 +75,7 @@
 #include <linux/moduleparam.h>
 #include <linux/cdev.h>
 #include <linux/file.h>
+#include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/mm.h>
 #include <linux/io.h>
@@ -1082,6 +1083,44 @@ linux_poll_wakeup(struct linux_file *filp)
        spin_unlock(&filp->f_kqlock);
 }
 
+static struct linux_file *
+__get_file_rcu(struct linux_file **f)
+{
+       struct linux_file *file1, *file2;
+
+       file1 = READ_ONCE(*f);
+       if (file1 == NULL)
+               return (NULL);
+
+       if (!refcount_acquire_if_not_zero(
+           file1->_file == NULL ? &file1->f_count : &file1->_file->f_count))
+               return (ERR_PTR(-EAGAIN));
+
+       file2 = READ_ONCE(*f);
+       if (file2 == file1)
+               return (file2);
+
+       fput(file1);
+       return (ERR_PTR(-EAGAIN));
+}
+
+struct linux_file *
+linux67_get_file_rcu(struct linux_file **f)
+{
+       struct linux_file *file1;
+
+       for (;;) {
+               file1 = __get_file_rcu(f);
+               if (file1 == NULL)
+                       return (NULL);
+
+               if (IS_ERR(file1))
+                       continue;
+
+               return (file1);
+       }
+}
+
 static void
 linux_file_kqfilter_detach(struct knote *kn)
 {

Reply via email to