[PATCH 2/7] sync_file: mark the fence pointer as rcu.

Dave Airlie airlied at gmail.com
Thu Apr 13 01:41:39 UTC 2017


From: Dave Airlie <airlied at redhat.com>

The current code never updates this pointer after init,
and it should always be initialised with a valid value.

However in the future we want to share some code with
semaphore files, and those will want to use rcu to update
this pointer. However none of the places sync_file access
the pointer from should correspond with semaphore files,
so this just wraps things with init and dereference wrappers.

Signed-off-by: Dave Airlie <airlied at redhat.com>
---
 drivers/dma-buf/sync_file.c | 32 +++++++++++++++++++-------------
 include/linux/sync_file.h   |  2 +-
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c
index dc89b1d..9b7ad7e 100644
--- a/drivers/dma-buf/sync_file.c
+++ b/drivers/dma-buf/sync_file.c
@@ -78,7 +78,7 @@ struct sync_file *sync_file_create(struct dma_fence *fence)
 	if (!sync_file)
 		return NULL;
 
-	sync_file->fence = dma_fence_get(fence);
+	RCU_INIT_POINTER(sync_file->fence, dma_fence_get(fence));
 
 	snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
 		 fence->ops->get_driver_name(fence),
@@ -122,7 +122,7 @@ struct dma_fence *sync_file_get_fence(int fd)
 	if (!sync_file)
 		return NULL;
 
-	fence = dma_fence_get(sync_file->fence);
+	fence = dma_fence_get(rcu_dereference_protected(sync_file->fence, 1));
 	fput(sync_file->file);
 
 	return fence;
@@ -141,7 +141,7 @@ static int sync_file_set_fence(struct sync_file *sync_file,
 	 * we own the reference of the dma_fence_array creation.
 	 */
 	if (num_fences == 1) {
-		sync_file->fence = fences[0];
+		RCU_INIT_POINTER(sync_file->fence, fences[0]);
 		kfree(fences);
 	} else {
 		array = dma_fence_array_create(num_fences, fences,
@@ -150,7 +150,7 @@ static int sync_file_set_fence(struct sync_file *sync_file,
 		if (!array)
 			return -ENOMEM;
 
-		sync_file->fence = &array->base;
+		RCU_INIT_POINTER(sync_file->fence, &array->base);
 	}
 
 	return 0;
@@ -159,8 +159,9 @@ static int sync_file_set_fence(struct sync_file *sync_file,
 static struct dma_fence **get_fences(struct sync_file *sync_file,
 				     int *num_fences)
 {
-	if (dma_fence_is_array(sync_file->fence)) {
-		struct dma_fence_array *array = to_dma_fence_array(sync_file->fence);
+	struct dma_fence *fence = rcu_dereference_protected(sync_file->fence, 1);
+	if (dma_fence_is_array(fence)) {
+		struct dma_fence_array *array = to_dma_fence_array(fence);
 
 		*num_fences = array->num_fences;
 		return array->fences;
@@ -278,10 +279,12 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
 static int sync_file_release(struct inode *inode, struct file *file)
 {
 	struct sync_file *sync_file = file->private_data;
+	struct dma_fence *fence;
 
-	if (test_bit(POLL_ENABLED, &sync_file->fence->flags))
-		dma_fence_remove_callback(sync_file->fence, &sync_file->cb);
-	dma_fence_put(sync_file->fence);
+	fence = rcu_dereference_protected(sync_file->fence, 1);
+	if (test_bit(POLL_ENABLED, &fence->flags))
+		dma_fence_remove_callback(fence, &sync_file->cb);
+	dma_fence_put(fence);
 	kfree(sync_file);
 
 	return 0;
@@ -290,16 +293,19 @@ static int sync_file_release(struct inode *inode, struct file *file)
 static unsigned int sync_file_poll(struct file *file, poll_table *wait)
 {
 	struct sync_file *sync_file = file->private_data;
+	struct dma_fence *fence;
+
+	fence = rcu_dereference_protected(sync_file->fence, 1);
 
 	poll_wait(file, &sync_file->wq, wait);
 
-	if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
-		if (dma_fence_add_callback(sync_file->fence, &sync_file->cb,
+	if (!test_and_set_bit(POLL_ENABLED, &fence->flags)) {
+		if (dma_fence_add_callback(fence, &sync_file->cb,
 					   fence_check_cb_func) < 0)
 			wake_up_all(&sync_file->wq);
 	}
 
-	return dma_fence_is_signaled(sync_file->fence) ? POLLIN : 0;
+	return dma_fence_is_signaled(fence) ? POLLIN : 0;
 }
 
 static long sync_file_ioctl_merge(struct sync_file *sync_file,
@@ -414,7 +420,7 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
 
 no_fences:
 	strlcpy(info.name, sync_file->name, sizeof(info.name));
-	info.status = dma_fence_is_signaled(sync_file->fence);
+	info.status = dma_fence_is_signaled(rcu_dereference_protected(sync_file->fence, 1));
 	info.num_fences = num_fences;
 
 	if (copy_to_user((void __user *)arg, &info, sizeof(info)))
diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h
index d37beef..adbc0b9 100644
--- a/include/linux/sync_file.h
+++ b/include/linux/sync_file.h
@@ -38,7 +38,7 @@ struct sync_file {
 
 	wait_queue_head_t	wq;
 
-	struct dma_fence	*fence;
+	struct dma_fence	__rcu *fence;
 	struct dma_fence_cb cb;
 };
 
-- 
2.9.3



More information about the dri-devel mailing list