The branch stable/13 has been updated by kib:

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

commit 2eeb0e9fc1306f40ec684af1ea56a8871a9a3684
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2024-05-07 13:23:28 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2024-05-19 00:59:13 +0000

    cdev_pager_allocate(): ensure that the cdev_pager_ops ctr is called only 
once
    
    PR:     278826
    
    (cherry picked from commit e93404065177d6c909cd64bf7d74fe0d8df35edf)
---
 sys/vm/device_pager.c | 70 +++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 51 insertions(+), 19 deletions(-)

diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 2d8f003c6f92..cb3b0e522d9a 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -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);
 }
 

Reply via email to