mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
linuxkpi: avoid counting per-thread use for the embedded linux cdevs
The counter is not used to control destroy. Reviewed by: hselasky Sponsored by: Mellanox Technologies/NVidia Networking MFC after: 1 week
This commit is contained in:
parent
7f9867f8c6
commit
f6b108837e
2 changed files with 30 additions and 14 deletions
|
|
@ -717,15 +717,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -738,8 +742,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) ({ \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue