Currently there is no easy way for a drm driver to safely check and allow drm_vma_offset_node for a drm file just once. Allow drm drivers to call non-refcounted version of drm_vma_node_allow() so that a driver doesn't need to keep track of each drm_vma_node_allow() to call subsequent drm_vma_node_revoke() to prevent memory leak. Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Cc: Maxime Ripard <mripard@kernel.org> Cc: Thomas Zimmermann <tzimmermann@suse.de> Cc: David Airlie <airlied@gmail.com> Cc: Daniel Vetter <daniel@ffwll.ch> Cc: Tvrtko Ursulin <tvrtko.ursulin@linux.intel.com> Cc: Andi Shyti <andi.shyti@linux.intel.com>
Unified · Split
| @@ -240,27 +240,8 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr, · 239 unmodified lines | ||
| 240 | 240 | } |
| 241 | 241 | EXPORT_SYMBOL(drm_vma_offset_remove); |
| 242 | 242 | |
| 243 | −/** | |
| 244 | − * drm_vma_node_allow - Add open-file to list of allowed users | |
| 245 | − * @node: Node to modify | |
| 246 | − * @tag: Tag of file to remove | |
| 247 | − * | |
| 248 | − * Add @tag to the list of allowed open-files for this node. If @tag is | |
| 249 | − * already on this list, the ref-count is incremented. | |
| 250 | − * | |
| 251 | − * The list of allowed-users is preserved across drm_vma_offset_add() and | |
| 252 | − * drm_vma_offset_remove() calls. You may even call it if the node is currently | |
| 253 | − * not added to any offset-manager. | |
| 254 | − * | |
| 255 | − * You must remove all open-files the same number of times as you added them | |
| 256 | − * before destroying the node. Otherwise, you will leak memory. | |
| 257 | − * | |
| 258 | − * This is locked against concurrent access internally. | |
| 259 | − * | |
| 260 | − * RETURNS: | |
| 261 | − * 0 on success, negative error code on internal failure (out-of-mem) | |
| 262 | − */ | |
| 263 | −int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag) | |
| 243 | +static int vma_node_allow(struct drm_vma_offset_node *node, | |
| 244 | + struct drm_file *tag, bool ref_counted) | |
| 264 | 245 | { |
| 265 | 246 | struct rb_node **iter; |
| 266 | 247 | struct rb_node *parent = NULL; |
| @@ -282,7 +263,8 @@ int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag) · 15 unmodified lines | ||
| 282 | 263 | entry = rb_entry(*iter, struct drm_vma_offset_file, vm_rb); |
| 283 | 264 | |
| 284 | 265 | if (tag == entry->vm_tag) { |
| 285 | − entry->vm_count++; | |
| 266 | + if (ref_counted) | |
| 267 | + entry->vm_count++; | |
| 286 | 268 | goto unlock; |
| 287 | 269 | } else if (tag > entry->vm_tag) { |
| 288 | 270 | iter = &(*iter)->rb_right; |
| @@ -307,8 +289,58 @@ unlock: · 18 unmodified lines | ||
| 307 | 289 | kfree(new); |
| 308 | 290 | return ret; |
| 309 | 291 | } |
| 292 | + | |
| 293 | +/** | |
| 294 | + * drm_vma_node_allow - Add open-file to list of allowed users | |
| 295 | + * @node: Node to modify | |
| 296 | + * @tag: Tag of file to remove | |
| 297 | + * | |
| 298 | + * Add @tag to the list of allowed open-files for this node. If @tag is | |
| 299 | + * already on this list, the ref-count is incremented. | |
| 300 | + * | |
| 301 | + * The list of allowed-users is preserved across drm_vma_offset_add() and | |
| 302 | + * drm_vma_offset_remove() calls. You may even call it if the node is currently | |
| 303 | + * not added to any offset-manager. | |
| 304 | + * | |
| 305 | + * You must remove all open-files the same number of times as you added them | |
| 306 | + * before destroying the node. Otherwise, you will leak memory. | |
| 307 | + * | |
| 308 | + * This is locked against concurrent access internally. | |
| 309 | + * | |
| 310 | + * RETURNS: | |
| 311 | + * 0 on success, negative error code on internal failure (out-of-mem) | |
| 312 | + */ | |
| 313 | +int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag) | |
| 314 | +{ | |
| 315 | + return vma_node_allow(node, tag, true); | |
| 316 | +} | |
| 310 | 317 | EXPORT_SYMBOL(drm_vma_node_allow); |
| 311 | 318 | |
| 319 | +/** | |
| 320 | + * drm_vma_node_allow_once - Add open-file to list of allowed users | |
| 321 | + * @node: Node to modify | |
| 322 | + * @tag: Tag of file to remove | |
| 323 | + * | |
| 324 | + * Add @tag to the list of allowed open-files for this node. | |
| 325 | + * | |
| 326 | + * The list of allowed-users is preserved across drm_vma_offset_add() and | |
| 327 | + * drm_vma_offset_remove() calls. You may even call it if the node is currently | |
| 328 | + * not added to any offset-manager. | |
| 329 | + * | |
| 330 | + * This is not ref-counted unlike drm_vma_node_allow() hence drm_vma_node_revoke() | |
| 331 | + * should only be called once after this. | |
| 332 | + * | |
| 333 | + * This is locked against concurrent access internally. | |
| 334 | + * | |
| 335 | + * RETURNS: | |
| 336 | + * 0 on success, negative error code on internal failure (out-of-mem) | |
| 337 | + */ | |
| 338 | +int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag) | |
| 339 | +{ | |
| 340 | + return vma_node_allow(node, tag, false); | |
| 341 | +} | |
| 342 | +EXPORT_SYMBOL(drm_vma_node_allow_once); | |
| 343 | + | |
| 312 | 344 | /** |
| 313 | 345 | * drm_vma_node_revoke - Remove open-file from list of allowed users |
| 314 | 346 | * @node: Node to modify |
| @@ -74,6 +74,7 @@ void drm_vma_offset_remove(struct drm_vma_offset_manager *mgr, · 73 unmodified lines | ||
| 74 | 74 | struct drm_vma_offset_node *node); |
| 75 | 75 | |
| 76 | 76 | int drm_vma_node_allow(struct drm_vma_offset_node *node, struct drm_file *tag); |
| 77 | +int drm_vma_node_allow_once(struct drm_vma_offset_node *node, struct drm_file *tag); | |
| 77 | 78 | void drm_vma_node_revoke(struct drm_vma_offset_node *node, |
| 78 | 79 | struct drm_file *tag); |
| 79 | 80 | bool drm_vma_node_is_allowed(struct drm_vma_offset_node *node, |