git: 1de8fcf419fc - main - linuxkpi: Add Linux 6.7 `get_file_rcu()` variant
Date: Fri, 31 Jan 2025 16:03:21 UTC
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)
{