--- a/sys/dev/drm/drm_gem.c +++ b/sys/dev/drm/drm_gem.c @@ -582,8 +585,20 @@ } obj->on_map = true; - return drm_vma_offset_add(dev->vma_offset_manager, &obj->vma_node, - size / PAGE_SIZE); + ret = drm_vma_offset_add(dev->vma_offset_manager, &obj->vma_node, + size / PAGE_SIZE); + if (ret != 0) { + /* + * Undo the hash/unr publication so obj state stays + * consistent (on_map false again) and a later retry + * starts clean instead of returning "success" with no + * vma offset allocated and a leaked idx. + */ + drm_ht_remove_item(&mm->offset_hash, &obj->map_list); + free_unr(mm->idxunr, obj->map_list.key); + obj->on_map = false; + } + return (ret); } EXPORT_SYMBOL(drm_gem_create_mmap_offset_size);