aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladimir Kondratyev <wulf@FreeBSD.org>2021-09-29 20:12:25 +0000
committerVladimir Kondratyev <wulf@FreeBSD.org>2021-09-29 20:12:25 +0000
commita81b36c6d35d74177891860b789dd02b9d1c5851 (patch)
treec43e6424f821fd29371ff4bf5d522d96343c361b
parentab4ed843a303ea3e585f8ed3f79873e46d3b3ae3 (diff)
downloadsrc-a81b36c6d35d74177891860b789dd02b9d1c5851.tar.gz
src-a81b36c6d35d74177891860b789dd02b9d1c5851.zip
LinuxKPI: Implement get_file_rcu()
get_file_rcu() grabs a file if the file->f_count is not zero. Required by drm-kmod 5.6 Reviewed by: hselasky, manu (previous version) MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D31672
-rw-r--r--sys/compat/linuxkpi/common/include/linux/fs.h9
-rw-r--r--sys/compat/linuxkpi/common/src/linux_compat.c4
2 files changed, 12 insertions, 1 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/fs.h b/sys/compat/linuxkpi/common/include/linux/fs.h
index 38911c276216..eaf806b6732c 100644
--- a/sys/compat/linuxkpi/common/include/linux/fs.h
+++ b/sys/compat/linuxkpi/common/include/linux/fs.h
@@ -108,6 +108,8 @@ struct linux_file {
/* pointer to associated character device, if any */
struct linux_cdev *f_cdev;
+
+ struct rcu_head rcu;
};
#define file linux_file
@@ -254,6 +256,13 @@ get_file(struct linux_file *f)
return (f);
}
+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));
+}
+
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 7ea33c9a0d8d..f15b9396525c 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -90,6 +90,7 @@ __FBSDID("$FreeBSD$");
#include <linux/poll.h>
#include <linux/smp.h>
#include <linux/wait_bit.h>
+#include <linux/rcupdate.h>
#if defined(__i386__) || defined(__amd64__)
#include <asm/smp.h>
@@ -472,7 +473,7 @@ linux_file_free(struct linux_file *filp)
if (filp->_file == NULL) {
if (filp->f_shmem != NULL)
vm_object_deallocate(filp->f_shmem);
- kfree(filp);
+ kfree_rcu(filp, rcu);
} else {
/*
* The close method of the character device or file
@@ -1538,6 +1539,7 @@ linux_file_close(struct file *file, struct thread *td)
ldev = filp->f_cdev;
if (ldev != NULL)
linux_cdev_deref(ldev);
+ linux_synchronize_rcu(RCU_TYPE_REGULAR);
kfree(filp);
return (error);