Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Jan 2025 16:03:21 GMT
From:      =?utf-8?Q?Jean-S=C3=A9bastien?= =?utf-8?Q?P=C3=A9dron?= <dumbbell@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 1de8fcf419fc - main - linuxkpi: Add Linux 6.7 `get_file_rcu()` variant
Message-ID:  <202501311603.50VG3LPI038815@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <dumbbell@FreeBSD.org>
AuthorDate: 2025-01-01 13:11:14 +0000
Commit:     Jean-Sébastien Pédron <dumbbell@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)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202501311603.50VG3LPI038815>