The branch stable/13 has been updated by kib:

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

commit e49760d9efda09a390476d64e6328fdd17aa3117
Author:     Konstantin Belousov <k...@freebsd.org>
AuthorDate: 2021-03-30 08:45:24 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2021-04-23 11:14:06 +0000

    linuxkpi: avoid counting per-thread use for the embedded linux cdevs
    
    (cherry picked from commit f6b108837e7df7d7bfb35ec447f7cb62afa79441)
---
 sys/compat/linuxkpi/common/src/linux_compat.c      | 31 ++++++++++++++--------
 sys/compat/linuxkpi/common/src/linux_compat.c.orig | 13 ++++++---
 2 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c 
b/sys/compat/linuxkpi/common/src/linux_compat.c
index 1d75644105dd..f8b939a5ec16 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -710,15 +710,19 @@ linux_get_fop(struct linux_file *filp, const struct 
file_operations **fop,
        ldev = filp->f_cdev;
        *fop = filp->f_op;
        if (ldev != NULL) {
-               for (siref = ldev->siref;;) {
-                       if ((siref & LDEV_SI_DTR) != 0) {
-                               ldev = &dummy_ldev;
-                               siref = ldev->siref;
-                               *fop = ldev->ops;
-                               MPASS((ldev->siref & LDEV_SI_DTR) == 0);
-                       } else if (atomic_fcmpset_int(&ldev->siref, &siref,
-                           siref + LDEV_SI_REF)) {
-                               break;
+               if (ldev->kobj.ktype == &linux_cdev_static_ktype) {
+                       refcount_acquire(&ldev->refs);
+               } else {
+                       for (siref = ldev->siref;;) {
+                               if ((siref & LDEV_SI_DTR) != 0) {
+                                       ldev = &dummy_ldev;
+                                       *fop = ldev->ops;
+                                       siref = ldev->siref;
+                                       MPASS((ldev->siref & LDEV_SI_DTR) == 0);
+                               } else if (atomic_fcmpset_int(&ldev->siref,
+                                   &siref, siref + LDEV_SI_REF)) {
+                                       break;
+                               }
                        }
                }
        }
@@ -731,8 +735,13 @@ linux_drop_fop(struct linux_cdev *ldev)
 
        if (ldev == NULL)
                return;
-       MPASS((ldev->siref & ~LDEV_SI_DTR) != 0);
-       atomic_subtract_int(&ldev->siref, LDEV_SI_REF);
+       if (ldev->kobj.ktype == &linux_cdev_static_ktype) {
+               linux_cdev_deref(ldev);
+       } else {
+               MPASS(ldev->kobj.ktype == &linux_cdev_ktype);
+               MPASS((ldev->siref & ~LDEV_SI_DTR) != 0);
+               atomic_subtract_int(&ldev->siref, LDEV_SI_REF);
+       }
 }
 
 #define        OPW(fp,td,code) ({                      \
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c.orig 
b/sys/compat/linuxkpi/common/src/linux_compat.c.orig
index 0731859e7a53..71ea7e0844dc 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c.orig
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c.orig
@@ -2199,8 +2199,8 @@ linux_completion_done(struct completion *c)
 static void
 linux_cdev_deref(struct linux_cdev *ldev)
 {
-
-       if (refcount_release(&ldev->refs))
+       if (refcount_release(&ldev->refs) &&
+           ldev->kobj.ktype == &linux_cdev_ktype)
                kfree(ldev);
 }
 
@@ -2220,12 +2220,17 @@ linux_cdev_release(struct kobject *kobj)
 static void
 linux_cdev_static_release(struct kobject *kobj)
 {
+       struct cdev *cdev;
        struct linux_cdev *ldev;
        struct kobject *parent;
 
        ldev = container_of(kobj, struct linux_cdev, kobj);
        parent = kobj->parent;
-       linux_destroy_dev(ldev);
+       cdev = ldev->cdev;
+       if (cdev != NULL) {
+               destroy_dev(cdev);
+               ldev->cdev = NULL;
+       }
        kobject_put(parent);
 }
 
@@ -2237,6 +2242,8 @@ linux_destroy_dev(struct linux_cdev *ldev)
                return;
 
        MPASS((ldev->siref & LDEV_SI_DTR) == 0);
+       MPASS(ldev->kobj.ktype == &linux_cdev_ktype);
+
        atomic_set_int(&ldev->siref, LDEV_SI_DTR);
        while ((atomic_load_int(&ldev->siref) & ~LDEV_SI_DTR) != 0)
                pause("ldevdtr", hz / 4);
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to