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 31 static struct sync_file *sync_file_alloc(int size) 32 { 33 struct sync_file *sync_file; 34 35 sync_file = kzalloc(size, 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 return sync_file; 49 50 err: 51 kfree(sync_file); 52 return NULL; 53 } 54 55 static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) 56 { 57 struct sync_file_cb *check; 58 struct sync_file *sync_file; 59 60 check = container_of(cb, struct sync_file_cb, cb); 61 sync_file = check->sync_file; 62 63 if (atomic_dec_and_test(&sync_file->status)) 64 wake_up_all(&sync_file->wq); 65 } 66 67 /** 68 * sync_file_create() - creates a sync file 69 * @fence: fence to add to the sync_fence 70 * 71 * Creates a sync_file containg @fence. Once this is called, the sync_file 72 * takes ownership of @fence. The sync_file can be released with 73 * fput(sync_file->file). Returns the sync_file or NULL in case of error. 74 */ 75 struct sync_file *sync_file_create(struct fence *fence) 76 { 77 struct sync_file *sync_file; 78 79 sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1])); 80 if (!sync_file) 81 return NULL; 82 83 sync_file->num_fences = 1; 84 atomic_set(&sync_file->status, 1); 85 snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%d-%d", 86 fence->ops->get_driver_name(fence), 87 fence->ops->get_timeline_name(fence), fence->context, 88 fence->seqno); 89 90 sync_file->cbs[0].fence = fence; 91 sync_file->cbs[0].sync_file = sync_file; 92 if (fence_add_callback(fence, &sync_file->cbs[0].cb, 93 fence_check_cb_func)) 94 atomic_dec(&sync_file->status); 95 96 return sync_file; 97 } 98 EXPORT_SYMBOL(sync_file_create); 99 100 /** 101 * sync_file_fdget() - get a sync_file from an fd 102 * @fd: fd referencing a fence 103 * 104 * Ensures @fd references a valid sync_file, increments the refcount of the 105 * backing file. Returns the sync_file or NULL in case of error. 106 */ 107 static struct sync_file *sync_file_fdget(int fd) 108 { 109 struct file *file = fget(fd); 110 111 if (!file) 112 return NULL; 113 114 if (file->f_op != &sync_file_fops) 115 goto err; 116 117 return file->private_data; 118 119 err: 120 fput(file); 121 return NULL; 122 } 123 124 static void sync_file_add_pt(struct sync_file *sync_file, int *i, 125 struct fence *fence) 126 { 127 sync_file->cbs[*i].fence = fence; 128 sync_file->cbs[*i].sync_file = sync_file; 129 130 if (!fence_add_callback(fence, &sync_file->cbs[*i].cb, 131 fence_check_cb_func)) { 132 fence_get(fence); 133 (*i)++; 134 } 135 } 136 137 /** 138 * sync_file_merge() - merge two sync_files 139 * @name: name of new fence 140 * @a: sync_file a 141 * @b: sync_file b 142 * 143 * Creates a new sync_file which contains copies of all the fences in both 144 * @a and @b. @a and @b remain valid, independent sync_file. Returns the 145 * new merged sync_file or NULL in case of error. 146 */ 147 static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, 148 struct sync_file *b) 149 { 150 int num_fences = a->num_fences + b->num_fences; 151 struct sync_file *sync_file; 152 int i, i_a, i_b; 153 unsigned long size = offsetof(struct sync_file, cbs[num_fences]); 154 155 sync_file = sync_file_alloc(size); 156 if (!sync_file) 157 return NULL; 158 159 atomic_set(&sync_file->status, num_fences); 160 161 /* 162 * Assume sync_file a and b are both ordered and have no 163 * duplicates with the same context. 164 * 165 * If a sync_file can only be created with sync_file_merge 166 * and sync_file_create, this is a reasonable assumption. 167 */ 168 for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) { 169 struct fence *pt_a = a->cbs[i_a].fence; 170 struct fence *pt_b = b->cbs[i_b].fence; 171 172 if (pt_a->context < pt_b->context) { 173 sync_file_add_pt(sync_file, &i, pt_a); 174 175 i_a++; 176 } else if (pt_a->context > pt_b->context) { 177 sync_file_add_pt(sync_file, &i, pt_b); 178 179 i_b++; 180 } else { 181 if (pt_a->seqno - pt_b->seqno <= INT_MAX) 182 sync_file_add_pt(sync_file, &i, pt_a); 183 else 184 sync_file_add_pt(sync_file, &i, pt_b); 185 186 i_a++; 187 i_b++; 188 } 189 } 190 191 for (; i_a < a->num_fences; i_a++) 192 sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence); 193 194 for (; i_b < b->num_fences; i_b++) 195 sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence); 196 197 if (num_fences > i) 198 atomic_sub(num_fences - i, &sync_file->status); 199 sync_file->num_fences = i; 200 201 strlcpy(sync_file->name, name, sizeof(sync_file->name)); 202 return sync_file; 203 } 204 205 static void sync_file_free(struct kref *kref) 206 { 207 struct sync_file *sync_file = container_of(kref, struct sync_file, 208 kref); 209 int i; 210 211 for (i = 0; i < sync_file->num_fences; ++i) { 212 fence_remove_callback(sync_file->cbs[i].fence, 213 &sync_file->cbs[i].cb); 214 fence_put(sync_file->cbs[i].fence); 215 } 216 217 kfree(sync_file); 218 } 219 220 static int sync_file_release(struct inode *inode, struct file *file) 221 { 222 struct sync_file *sync_file = file->private_data; 223 224 kref_put(&sync_file->kref, sync_file_free); 225 return 0; 226 } 227 228 static unsigned int sync_file_poll(struct file *file, poll_table *wait) 229 { 230 struct sync_file *sync_file = file->private_data; 231 int status; 232 233 poll_wait(file, &sync_file->wq, wait); 234 235 status = atomic_read(&sync_file->status); 236 237 if (!status) 238 return POLLIN; 239 if (status < 0) 240 return POLLERR; 241 return 0; 242 } 243 244 static long sync_file_ioctl_merge(struct sync_file *sync_file, 245 unsigned long arg) 246 { 247 int fd = get_unused_fd_flags(O_CLOEXEC); 248 int err; 249 struct sync_file *fence2, *fence3; 250 struct sync_merge_data data; 251 252 if (fd < 0) 253 return fd; 254 255 if (copy_from_user(&data, (void __user *)arg, sizeof(data))) { 256 err = -EFAULT; 257 goto err_put_fd; 258 } 259 260 if (data.flags || data.pad) { 261 err = -EINVAL; 262 goto err_put_fd; 263 } 264 265 fence2 = sync_file_fdget(data.fd2); 266 if (!fence2) { 267 err = -ENOENT; 268 goto err_put_fd; 269 } 270 271 data.name[sizeof(data.name) - 1] = '\0'; 272 fence3 = sync_file_merge(data.name, sync_file, fence2); 273 if (!fence3) { 274 err = -ENOMEM; 275 goto err_put_fence2; 276 } 277 278 data.fence = fd; 279 if (copy_to_user((void __user *)arg, &data, sizeof(data))) { 280 err = -EFAULT; 281 goto err_put_fence3; 282 } 283 284 fd_install(fd, fence3->file); 285 fput(fence2->file); 286 return 0; 287 288 err_put_fence3: 289 fput(fence3->file); 290 291 err_put_fence2: 292 fput(fence2->file); 293 294 err_put_fd: 295 put_unused_fd(fd); 296 return err; 297 } 298 299 static void sync_fill_fence_info(struct fence *fence, 300 struct sync_fence_info *info) 301 { 302 strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), 303 sizeof(info->obj_name)); 304 strlcpy(info->driver_name, fence->ops->get_driver_name(fence), 305 sizeof(info->driver_name)); 306 if (fence_is_signaled(fence)) 307 info->status = fence->status >= 0 ? 1 : fence->status; 308 else 309 info->status = 0; 310 info->timestamp_ns = ktime_to_ns(fence->timestamp); 311 } 312 313 static long sync_file_ioctl_fence_info(struct sync_file *sync_file, 314 unsigned long arg) 315 { 316 struct sync_file_info info; 317 struct sync_fence_info *fence_info = NULL; 318 __u32 size; 319 int ret, i; 320 321 if (copy_from_user(&info, (void __user *)arg, sizeof(info))) 322 return -EFAULT; 323 324 if (info.flags || info.pad) 325 return -EINVAL; 326 327 /* 328 * Passing num_fences = 0 means that userspace doesn't want to 329 * retrieve any sync_fence_info. If num_fences = 0 we skip filling 330 * sync_fence_info and return the actual number of fences on 331 * info->num_fences. 332 */ 333 if (!info.num_fences) 334 goto no_fences; 335 336 if (info.num_fences < sync_file->num_fences) 337 return -EINVAL; 338 339 size = sync_file->num_fences * sizeof(*fence_info); 340 fence_info = kzalloc(size, GFP_KERNEL); 341 if (!fence_info) 342 return -ENOMEM; 343 344 for (i = 0; i < sync_file->num_fences; ++i) 345 sync_fill_fence_info(sync_file->cbs[i].fence, &fence_info[i]); 346 347 if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info, 348 size)) { 349 ret = -EFAULT; 350 goto out; 351 } 352 353 no_fences: 354 strlcpy(info.name, sync_file->name, sizeof(info.name)); 355 info.status = atomic_read(&sync_file->status); 356 if (info.status >= 0) 357 info.status = !info.status; 358 359 info.num_fences = sync_file->num_fences; 360 361 if (copy_to_user((void __user *)arg, &info, sizeof(info))) 362 ret = -EFAULT; 363 else 364 ret = 0; 365 366 out: 367 kfree(fence_info); 368 369 return ret; 370 } 371 372 static long sync_file_ioctl(struct file *file, unsigned int cmd, 373 unsigned long arg) 374 { 375 struct sync_file *sync_file = file->private_data; 376 377 switch (cmd) { 378 case SYNC_IOC_MERGE: 379 return sync_file_ioctl_merge(sync_file, arg); 380 381 case SYNC_IOC_FILE_INFO: 382 return sync_file_ioctl_fence_info(sync_file, arg); 383 384 default: 385 return -ENOTTY; 386 } 387 } 388 389 static const struct file_operations sync_file_fops = { 390 .release = sync_file_release, 391 .poll = sync_file_poll, 392 .unlocked_ioctl = sync_file_ioctl, 393 .compat_ioctl = sync_file_ioctl, 394 }; 395 396