Add some helpers to correctly allocate/free reservation_object_lists.

Otherwise we might forget to drop dma_fence references on list destruction.

Signed-off-by: Christian König <christian.koe...@amd.com>
---
 drivers/dma-buf/reservation.c | 65 +++++++++++++++++++++++++----------
 1 file changed, 46 insertions(+), 19 deletions(-)

diff --git a/drivers/dma-buf/reservation.c b/drivers/dma-buf/reservation.c
index d59207ca72d2..c0ba05936ab6 100644
--- a/drivers/dma-buf/reservation.c
+++ b/drivers/dma-buf/reservation.c
@@ -55,6 +55,47 @@ EXPORT_SYMBOL(reservation_seqcount_class);
 const char reservation_seqcount_string[] = "reservation_seqcount";
 EXPORT_SYMBOL(reservation_seqcount_string);
 
+/**
+ * reservation_object_list_alloc - allocate fence list
+ * @shared_max: number of fences we need space for
+ *
+ * Allocate a new reservation_object_list and make sure to correctly initialize
+ * shared_max.
+ */
+static struct reservation_object_list *
+reservation_object_list_alloc(unsigned int shared_max)
+{
+       struct reservation_object_list *list;
+
+       list = kmalloc(offsetof(typeof(*list), shared[shared_max]), GFP_KERNEL);
+       if (!list)
+               return NULL;
+
+       list->shared_max = (ksize(list) - offsetof(typeof(*list), shared)) /
+               sizeof(*list->shared);
+
+       return list;
+}
+
+/**
+ * reservation_object_list_free - free fence list
+ * @list: list to free
+ *
+ * Free a reservation_object_list and make sure to drop all references.
+ */
+static void reservation_object_list_free(struct reservation_object_list *list)
+{
+       unsigned int i;
+
+       if (!list)
+               return;
+
+       for (i = 0; i < list->shared_count; ++i)
+               dma_fence_put(rcu_dereference_protected(list->shared[i], true));
+
+       kfree_rcu(list, rcu);
+}
+
 /**
  * reservation_object_init - initialize a reservation object
  * @obj: the reservation object
@@ -76,7 +117,6 @@ EXPORT_SYMBOL(reservation_object_init);
  */
 void reservation_object_fini(struct reservation_object *obj)
 {
-       int i;
        struct reservation_object_list *fobj;
        struct dma_fence *excl;
 
@@ -89,13 +129,7 @@ void reservation_object_fini(struct reservation_object *obj)
                dma_fence_put(excl);
 
        fobj = rcu_dereference_protected(obj->fence, 1);
-       if (fobj) {
-               for (i = 0; i < fobj->shared_count; ++i)
-                       
dma_fence_put(rcu_dereference_protected(fobj->shared[i], 1));
-
-               kfree(fobj);
-       }
-
+       reservation_object_list_free(fobj);
        ww_mutex_destroy(&obj->lock);
 }
 EXPORT_SYMBOL(reservation_object_fini);
@@ -132,7 +166,7 @@ int reservation_object_reserve_shared(struct 
reservation_object *obj,
                max = 4;
        }
 
-       new = kmalloc(offsetof(typeof(*new), shared[max]), GFP_KERNEL);
+       new = reservation_object_list_alloc(max);
        if (!new)
                return -ENOMEM;
 
@@ -153,9 +187,6 @@ int reservation_object_reserve_shared(struct 
reservation_object *obj,
                        RCU_INIT_POINTER(new->shared[j++], fence);
        }
        new->shared_count = j;
-       new->shared_max =
-               (ksize(new) - offsetof(typeof(*new), shared)) /
-               sizeof(*new->shared);
 
        /*
         * We are not changing the effective set of fences here so can
@@ -286,7 +317,6 @@ int reservation_object_copy_fences(struct 
reservation_object *dst,
 {
        struct reservation_object_list *src_list, *dst_list;
        struct dma_fence *old, *new;
-       size_t size;
        unsigned i;
 
        reservation_object_assert_held(dst);
@@ -298,10 +328,9 @@ int reservation_object_copy_fences(struct 
reservation_object *dst,
        if (src_list) {
                unsigned shared_count = src_list->shared_count;
 
-               size = offsetof(typeof(*src_list), shared[shared_count]);
                rcu_read_unlock();
 
-               dst_list = kmalloc(size, GFP_KERNEL);
+               dst_list = reservation_object_list_alloc(shared_count);
                if (!dst_list)
                        return -ENOMEM;
 
@@ -313,7 +342,6 @@ int reservation_object_copy_fences(struct 
reservation_object *dst,
                }
 
                dst_list->shared_count = 0;
-               dst_list->shared_max = shared_count;
                for (i = 0; i < src_list->shared_count; ++i) {
                        struct dma_fence *fence;
 
@@ -323,7 +351,7 @@ int reservation_object_copy_fences(struct 
reservation_object *dst,
                                continue;
 
                        if (!dma_fence_get_rcu(fence)) {
-                               kfree(dst_list);
+                               reservation_object_list_free(dst_list);
                                src_list = rcu_dereference(src->fence);
                                goto retry;
                        }
@@ -353,8 +381,7 @@ int reservation_object_copy_fences(struct 
reservation_object *dst,
        write_seqcount_end(&dst->seq);
        preempt_enable();
 
-       if (src_list)
-               kfree_rcu(src_list, rcu);
+       reservation_object_list_free(src_list);
        dma_fence_put(old);
 
        return 0;
-- 
2.17.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to