mirror of
https://github.com/opnsense/src.git
synced 2026-02-18 18:20:26 -05:00
cdev_pager_allocate(): ensure that the cdev_pager_ops ctr is called only once
PR: 278826 (cherry picked from commit e93404065177d6c909cd64bf7d74fe0d8df35edf)
This commit is contained in:
parent
a19d42b08a
commit
4018bcdea8
1 changed files with 51 additions and 19 deletions
|
|
@ -118,8 +118,15 @@ cdev_pager_lookup(void *handle)
|
|||
{
|
||||
vm_object_t object;
|
||||
|
||||
again:
|
||||
mtx_lock(&dev_pager_mtx);
|
||||
object = vm_pager_object_lookup(&dev_pager_object_list, handle);
|
||||
if (object != NULL && object->un_pager.devp.dev == NULL) {
|
||||
msleep(&object->un_pager.devp.dev, &dev_pager_mtx,
|
||||
PVM | PDROP, "cdplkp", 0);
|
||||
vm_object_deallocate(object);
|
||||
goto again;
|
||||
}
|
||||
mtx_unlock(&dev_pager_mtx);
|
||||
return (object);
|
||||
}
|
||||
|
|
@ -129,9 +136,8 @@ cdev_pager_allocate(void *handle, enum obj_type tp,
|
|||
const struct cdev_pager_ops *ops, vm_ooffset_t size, vm_prot_t prot,
|
||||
vm_ooffset_t foff, struct ucred *cred)
|
||||
{
|
||||
vm_object_t object, object1;
|
||||
vm_object_t object;
|
||||
vm_pindex_t pindex;
|
||||
u_short color;
|
||||
|
||||
if (tp != OBJT_DEVICE && tp != OBJT_MGTDEVICE)
|
||||
return (NULL);
|
||||
|
|
@ -157,16 +163,16 @@ cdev_pager_allocate(void *handle, enum obj_type tp,
|
|||
pindex < OFF_TO_IDX(size))
|
||||
return (NULL);
|
||||
|
||||
if (ops->cdev_pg_ctor(handle, size, prot, foff, cred, &color) != 0)
|
||||
return (NULL);
|
||||
again:
|
||||
mtx_lock(&dev_pager_mtx);
|
||||
|
||||
/*
|
||||
* Look up pager, creating as necessary.
|
||||
*/
|
||||
object1 = NULL;
|
||||
object = vm_pager_object_lookup(&dev_pager_object_list, handle);
|
||||
if (object == NULL) {
|
||||
vm_object_t object1;
|
||||
|
||||
/*
|
||||
* Allocate object and associate it with the pager. Initialize
|
||||
* the object's pg_color based upon the physical address of the
|
||||
|
|
@ -174,15 +180,19 @@ cdev_pager_allocate(void *handle, enum obj_type tp,
|
|||
*/
|
||||
mtx_unlock(&dev_pager_mtx);
|
||||
object1 = vm_object_allocate(tp, pindex);
|
||||
object1->flags |= OBJ_COLORED;
|
||||
object1->pg_color = color;
|
||||
object1->handle = handle;
|
||||
object1->un_pager.devp.ops = ops;
|
||||
object1->un_pager.devp.dev = handle;
|
||||
TAILQ_INIT(&object1->un_pager.devp.devp_pglist);
|
||||
mtx_lock(&dev_pager_mtx);
|
||||
object = vm_pager_object_lookup(&dev_pager_object_list, handle);
|
||||
if (object != NULL) {
|
||||
object1->type = OBJT_DEAD;
|
||||
vm_object_deallocate(object1);
|
||||
object1 = NULL;
|
||||
if (object->un_pager.devp.dev == NULL) {
|
||||
msleep(&object->un_pager.devp.dev,
|
||||
&dev_pager_mtx, PVM | PDROP, "cdplkp", 0);
|
||||
vm_object_deallocate(object);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/*
|
||||
* We raced with other thread while allocating object.
|
||||
*/
|
||||
|
|
@ -194,29 +204,51 @@ cdev_pager_allocate(void *handle, enum obj_type tp,
|
|||
KASSERT(object->un_pager.devp.ops == ops,
|
||||
("Inconsistent devops %p %p", object, ops));
|
||||
} else {
|
||||
u_short color;
|
||||
|
||||
object = object1;
|
||||
object1 = NULL;
|
||||
object->handle = handle;
|
||||
object->un_pager.devp.ops = ops;
|
||||
TAILQ_INIT(&object->un_pager.devp.devp_pglist);
|
||||
TAILQ_INSERT_TAIL(&dev_pager_object_list, object,
|
||||
pager_object_list);
|
||||
mtx_unlock(&dev_pager_mtx);
|
||||
if (ops->cdev_pg_populate != NULL)
|
||||
vm_object_set_flag(object, OBJ_POPULATE);
|
||||
if (ops->cdev_pg_ctor(handle, size, prot, foff,
|
||||
cred, &color) != 0) {
|
||||
mtx_lock(&dev_pager_mtx);
|
||||
TAILQ_REMOVE(&dev_pager_object_list, object,
|
||||
pager_object_list);
|
||||
wakeup(&object->un_pager.devp.dev);
|
||||
mtx_unlock(&dev_pager_mtx);
|
||||
object->type = OBJT_DEAD;
|
||||
vm_object_deallocate(object);
|
||||
object = NULL;
|
||||
mtx_lock(&dev_pager_mtx);
|
||||
} else {
|
||||
mtx_lock(&dev_pager_mtx);
|
||||
object->flags |= OBJ_COLORED;
|
||||
object->pg_color = color;
|
||||
object->un_pager.devp.dev = handle;
|
||||
wakeup(&object->un_pager.devp.dev);
|
||||
}
|
||||
}
|
||||
MPASS(object1 == NULL);
|
||||
} else {
|
||||
if (object->un_pager.devp.dev == NULL) {
|
||||
msleep(&object->un_pager.devp.dev,
|
||||
&dev_pager_mtx, PVM | PDROP, "cdplkp", 0);
|
||||
vm_object_deallocate(object);
|
||||
goto again;
|
||||
}
|
||||
if (pindex > object->size)
|
||||
object->size = pindex;
|
||||
KASSERT(object->type == tp,
|
||||
("Inconsistent device pager type %p %d", object, tp));
|
||||
}
|
||||
mtx_unlock(&dev_pager_mtx);
|
||||
if (object1 != NULL) {
|
||||
object1->handle = object1;
|
||||
mtx_lock(&dev_pager_mtx);
|
||||
TAILQ_INSERT_TAIL(&dev_pager_object_list, object1,
|
||||
pager_object_list);
|
||||
mtx_unlock(&dev_pager_mtx);
|
||||
vm_object_deallocate(object1);
|
||||
}
|
||||
return (object);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue