• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/dma-buf/sync_file.c
3  *
4  * Copyright (C) 2012 Google, Inc.
5  *
6  * This software is licensed under the terms of the GNU General Public
7  * License version 2, as published by the Free Software Foundation, and
8  * may be copied, distributed, and modified under those terms.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  */
16 
17 #include <linux/export.h>
18 #include <linux/file.h>
19 #include <linux/fs.h>
20 #include <linux/kernel.h>
21 #include <linux/poll.h>
22 #include <linux/sched.h>
23 #include <linux/slab.h>
24 #include <linux/uaccess.h>
25 #include <linux/anon_inodes.h>
26 #include <linux/sync_file.h>
27 #include <uapi/linux/sync_file.h>
28 
29 static const struct file_operations sync_file_fops;
30 
sync_file_alloc(void)31 static struct sync_file *sync_file_alloc(void)
32 {
33 	struct sync_file *sync_file;
34 
35 	sync_file = kzalloc(sizeof(*sync_file), GFP_KERNEL);
36 	if (!sync_file)
37 		return NULL;
38 
39 	sync_file->file = anon_inode_getfile("sync_file", &sync_file_fops,
40 					     sync_file, 0);
41 	if (IS_ERR(sync_file->file))
42 		goto err;
43 
44 	kref_init(&sync_file->kref);
45 
46 	init_waitqueue_head(&sync_file->wq);
47 
48 	INIT_LIST_HEAD(&sync_file->cb.node);
49 
50 	return sync_file;
51 
52 err:
53 	kfree(sync_file);
54 	return NULL;
55 }
56 
fence_check_cb_func(struct fence * f,struct fence_cb * cb)57 static void fence_check_cb_func(struct fence *f, struct fence_cb *cb)
58 {
59 	struct sync_file *sync_file;
60 
61 	sync_file = container_of(cb, struct sync_file, cb);
62 
63 	wake_up_all(&sync_file->wq);
64 }
65 
66 /**
67  * sync_file_create() - creates a sync file
68  * @fence:	fence to add to the sync_fence
69  *
70  * Creates a sync_file containg @fence. This function acquires and additional
71  * reference of @fence for the newly-created &sync_file, if it succeeds. The
72  * sync_file can be released with fput(sync_file->file). Returns the
73  * sync_file or NULL in case of error.
74  */
sync_file_create(struct fence * fence)75 struct sync_file *sync_file_create(struct fence *fence)
76 {
77 	struct sync_file *sync_file;
78 
79 	sync_file = sync_file_alloc();
80 	if (!sync_file)
81 		return NULL;
82 
83 	sync_file->fence = fence_get(fence);
84 
85 	snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d",
86 		 fence->ops->get_driver_name(fence),
87 		 fence->ops->get_timeline_name(fence), fence->context,
88 		 fence->seqno);
89 
90 	return sync_file;
91 }
92 EXPORT_SYMBOL(sync_file_create);
93 
sync_file_fdget(int fd)94 static struct sync_file *sync_file_fdget(int fd)
95 {
96 	struct file *file = fget(fd);
97 
98 	if (!file)
99 		return NULL;
100 
101 	if (file->f_op != &sync_file_fops)
102 		goto err;
103 
104 	return file->private_data;
105 
106 err:
107 	fput(file);
108 	return NULL;
109 }
110 
111 /**
112  * sync_file_get_fence - get the fence related to the sync_file fd
113  * @fd:		sync_file fd to get the fence from
114  *
115  * Ensures @fd references a valid sync_file and returns a fence that
116  * represents all fence in the sync_file. On error NULL is returned.
117  */
sync_file_get_fence(int fd)118 struct fence *sync_file_get_fence(int fd)
119 {
120 	struct sync_file *sync_file;
121 	struct fence *fence;
122 
123 	sync_file = sync_file_fdget(fd);
124 	if (!sync_file)
125 		return NULL;
126 
127 	fence = fence_get(sync_file->fence);
128 	fput(sync_file->file);
129 
130 	return fence;
131 }
132 EXPORT_SYMBOL(sync_file_get_fence);
133 
sync_file_set_fence(struct sync_file * sync_file,struct fence ** fences,int num_fences)134 static int sync_file_set_fence(struct sync_file *sync_file,
135 			       struct fence **fences, int num_fences)
136 {
137 	struct fence_array *array;
138 
139 	/*
140 	 * The reference for the fences in the new sync_file and held
141 	 * in add_fence() during the merge procedure, so for num_fences == 1
142 	 * we already own a new reference to the fence. For num_fence > 1
143 	 * we own the reference of the fence_array creation.
144 	 */
145 	if (num_fences == 1) {
146 		sync_file->fence = fences[0];
147 		kfree(fences);
148 	} else {
149 		array = fence_array_create(num_fences, fences,
150 					   fence_context_alloc(1), 1, false);
151 		if (!array)
152 			return -ENOMEM;
153 
154 		sync_file->fence = &array->base;
155 	}
156 
157 	return 0;
158 }
159 
get_fences(struct sync_file * sync_file,int * num_fences)160 static struct fence **get_fences(struct sync_file *sync_file, int *num_fences)
161 {
162 	if (fence_is_array(sync_file->fence)) {
163 		struct fence_array *array = to_fence_array(sync_file->fence);
164 
165 		*num_fences = array->num_fences;
166 		return array->fences;
167 	}
168 
169 	*num_fences = 1;
170 	return &sync_file->fence;
171 }
172 
add_fence(struct fence ** fences,int * i,struct fence * fence)173 static void add_fence(struct fence **fences, int *i, struct fence *fence)
174 {
175 	fences[*i] = fence;
176 
177 	if (!fence_is_signaled(fence)) {
178 		fence_get(fence);
179 		(*i)++;
180 	}
181 }
182 
183 /**
184  * sync_file_merge() - merge two sync_files
185  * @name:	name of new fence
186  * @a:		sync_file a
187  * @b:		sync_file b
188  *
189  * Creates a new sync_file which contains copies of all the fences in both
190  * @a and @b.  @a and @b remain valid, independent sync_file. Returns the
191  * new merged sync_file or NULL in case of error.
192  */
sync_file_merge(const char * name,struct sync_file * a,struct sync_file * b)193 static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
194 					 struct sync_file *b)
195 {
196 	struct sync_file *sync_file;
197 	struct fence **fences, **nfences, **a_fences, **b_fences;
198 	int i, i_a, i_b, num_fences, a_num_fences, b_num_fences;
199 
200 	sync_file = sync_file_alloc();
201 	if (!sync_file)
202 		return NULL;
203 
204 	a_fences = get_fences(a, &a_num_fences);
205 	b_fences = get_fences(b, &b_num_fences);
206 	if (a_num_fences > INT_MAX - b_num_fences)
207 		return NULL;
208 
209 	num_fences = a_num_fences + b_num_fences;
210 
211 	fences = kcalloc(num_fences, sizeof(*fences), GFP_KERNEL);
212 	if (!fences)
213 		goto err;
214 
215 	/*
216 	 * Assume sync_file a and b are both ordered and have no
217 	 * duplicates with the same context.
218 	 *
219 	 * If a sync_file can only be created with sync_file_merge
220 	 * and sync_file_create, this is a reasonable assumption.
221 	 */
222 	for (i = i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
223 		struct fence *pt_a = a_fences[i_a];
224 		struct fence *pt_b = b_fences[i_b];
225 
226 		if (pt_a->context < pt_b->context) {
227 			add_fence(fences, &i, pt_a);
228 
229 			i_a++;
230 		} else if (pt_a->context > pt_b->context) {
231 			add_fence(fences, &i, pt_b);
232 
233 			i_b++;
234 		} else {
235 			if (pt_a->seqno - pt_b->seqno <= INT_MAX)
236 				add_fence(fences, &i, pt_a);
237 			else
238 				add_fence(fences, &i, pt_b);
239 
240 			i_a++;
241 			i_b++;
242 		}
243 	}
244 
245 	for (; i_a < a_num_fences; i_a++)
246 		add_fence(fences, &i, a_fences[i_a]);
247 
248 	for (; i_b < b_num_fences; i_b++)
249 		add_fence(fences, &i, b_fences[i_b]);
250 
251 	if (i == 0)
252 		fences[i++] = fence_get(a_fences[0]);
253 
254 	if (num_fences > i) {
255 		nfences = krealloc(fences, i * sizeof(*fences),
256 				  GFP_KERNEL);
257 		if (!nfences)
258 			goto err;
259 
260 		fences = nfences;
261 	}
262 
263 	if (sync_file_set_fence(sync_file, fences, i) < 0) {
264 		kfree(fences);
265 		goto err;
266 	}
267 
268 	strlcpy(sync_file->name, name, sizeof(sync_file->name));
269 	return sync_file;
270 
271 err:
272 	fput(sync_file->file);
273 	return NULL;
274 
275 }
276 
sync_file_free(struct kref * kref)277 static void sync_file_free(struct kref *kref)
278 {
279 	struct sync_file *sync_file = container_of(kref, struct sync_file,
280 						     kref);
281 
282 	if (test_bit(POLL_ENABLED, &sync_file->fence->flags))
283 		fence_remove_callback(sync_file->fence, &sync_file->cb);
284 	fence_put(sync_file->fence);
285 	kfree(sync_file);
286 }
287 
sync_file_release(struct inode * inode,struct file * file)288 static int sync_file_release(struct inode *inode, struct file *file)
289 {
290 	struct sync_file *sync_file = file->private_data;
291 
292 	kref_put(&sync_file->kref, sync_file_free);
293 	return 0;
294 }
295 
sync_file_poll(struct file * file,poll_table * wait)296 static unsigned int sync_file_poll(struct file *file, poll_table *wait)
297 {
298 	struct sync_file *sync_file = file->private_data;
299 
300 	poll_wait(file, &sync_file->wq, wait);
301 
302 	if (!test_and_set_bit(POLL_ENABLED, &sync_file->fence->flags)) {
303 		if (fence_add_callback(sync_file->fence, &sync_file->cb,
304 					   fence_check_cb_func) < 0)
305 			wake_up_all(&sync_file->wq);
306 	}
307 
308 	return fence_is_signaled(sync_file->fence) ? POLLIN : 0;
309 }
310 
sync_file_ioctl_merge(struct sync_file * sync_file,unsigned long arg)311 static long sync_file_ioctl_merge(struct sync_file *sync_file,
312 				  unsigned long arg)
313 {
314 	int fd = get_unused_fd_flags(O_CLOEXEC);
315 	int err;
316 	struct sync_file *fence2, *fence3;
317 	struct sync_merge_data data;
318 
319 	if (fd < 0)
320 		return fd;
321 
322 	if (copy_from_user(&data, (void __user *)arg, sizeof(data))) {
323 		err = -EFAULT;
324 		goto err_put_fd;
325 	}
326 
327 	if (data.flags || data.pad) {
328 		err = -EINVAL;
329 		goto err_put_fd;
330 	}
331 
332 	fence2 = sync_file_fdget(data.fd2);
333 	if (!fence2) {
334 		err = -ENOENT;
335 		goto err_put_fd;
336 	}
337 
338 	data.name[sizeof(data.name) - 1] = '\0';
339 	fence3 = sync_file_merge(data.name, sync_file, fence2);
340 	if (!fence3) {
341 		err = -ENOMEM;
342 		goto err_put_fence2;
343 	}
344 
345 	data.fence = fd;
346 	if (copy_to_user((void __user *)arg, &data, sizeof(data))) {
347 		err = -EFAULT;
348 		goto err_put_fence3;
349 	}
350 
351 	fd_install(fd, fence3->file);
352 	fput(fence2->file);
353 	return 0;
354 
355 err_put_fence3:
356 	fput(fence3->file);
357 
358 err_put_fence2:
359 	fput(fence2->file);
360 
361 err_put_fd:
362 	put_unused_fd(fd);
363 	return err;
364 }
365 
sync_fill_fence_info(struct fence * fence,struct sync_fence_info * info)366 static void sync_fill_fence_info(struct fence *fence,
367 				 struct sync_fence_info *info)
368 {
369 	strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
370 		sizeof(info->obj_name));
371 	strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
372 		sizeof(info->driver_name));
373 
374 	info->status = fence_get_status(fence);
375 	info->timestamp_ns = ktime_to_ns(fence->timestamp);
376 }
377 
sync_file_ioctl_fence_info(struct sync_file * sync_file,unsigned long arg)378 static long sync_file_ioctl_fence_info(struct sync_file *sync_file,
379 				       unsigned long arg)
380 {
381 	struct sync_file_info info;
382 	struct sync_fence_info *fence_info = NULL;
383 	struct fence **fences;
384 	__u32 size;
385 	int num_fences, ret, i;
386 
387 	if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
388 		return -EFAULT;
389 
390 	if (info.flags || info.pad)
391 		return -EINVAL;
392 
393 	fences = get_fences(sync_file, &num_fences);
394 
395 	/*
396 	 * Passing num_fences = 0 means that userspace doesn't want to
397 	 * retrieve any sync_fence_info. If num_fences = 0 we skip filling
398 	 * sync_fence_info and return the actual number of fences on
399 	 * info->num_fences.
400 	 */
401 	if (!info.num_fences)
402 		goto no_fences;
403 
404 	if (info.num_fences < num_fences)
405 		return -EINVAL;
406 
407 	size = num_fences * sizeof(*fence_info);
408 	fence_info = kzalloc(size, GFP_KERNEL);
409 	if (!fence_info)
410 		return -ENOMEM;
411 
412 	for (i = 0; i < num_fences; i++)
413 		sync_fill_fence_info(fences[i], &fence_info[i]);
414 
415 	if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info,
416 			 size)) {
417 		ret = -EFAULT;
418 		goto out;
419 	}
420 
421 no_fences:
422 	strlcpy(info.name, sync_file->name, sizeof(info.name));
423 	info.status = fence_is_signaled(sync_file->fence);
424 	info.num_fences = num_fences;
425 
426 	if (copy_to_user((void __user *)arg, &info, sizeof(info)))
427 		ret = -EFAULT;
428 	else
429 		ret = 0;
430 
431 out:
432 	kfree(fence_info);
433 
434 	return ret;
435 }
436 
sync_file_ioctl(struct file * file,unsigned int cmd,unsigned long arg)437 static long sync_file_ioctl(struct file *file, unsigned int cmd,
438 			    unsigned long arg)
439 {
440 	struct sync_file *sync_file = file->private_data;
441 
442 	switch (cmd) {
443 	case SYNC_IOC_MERGE:
444 		return sync_file_ioctl_merge(sync_file, arg);
445 
446 	case SYNC_IOC_FILE_INFO:
447 		return sync_file_ioctl_fence_info(sync_file, arg);
448 
449 	default:
450 		return -ENOTTY;
451 	}
452 }
453 
454 static const struct file_operations sync_file_fops = {
455 	.release = sync_file_release,
456 	.poll = sync_file_poll,
457 	.unlocked_ioctl = sync_file_ioctl,
458 	.compat_ioctl = sync_file_ioctl,
459 };
460 
461