Commit 19e8697ba45e7bcdb04f2adf6110fbf4882863e5
Committed by
Sumit Semwal
1 parent
9022e24e89
Exists in
master
and in
20 other branches
dma-buf: Expose buffer size to userspace (v2)
Each dma-buf has an associated size and it's reasonable for userspace to want to know what it is. Since userspace already has an fd, expose the size using the size = lseek(fd, SEEK_END, 0); lseek(fd, SEEK_CUR, 0); idiom. v2: Added Daniel's sugeested documentation, with minor fixups Signed-off-by: Christopher James Halse Rogers <christopher.halse.rogers@canonical.com> Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> Tested-by: Daniel Vetter <daniel.vetter@ffwll.ch> Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>
Showing 2 changed files with 41 additions and 0 deletions Side-by-side Diff
Documentation/dma-buf-sharing.txt
... | ... | @@ -407,6 +407,18 @@ |
407 | 407 | interesting ways depending upong the exporter (if userspace starts depending |
408 | 408 | upon this implicit synchronization). |
409 | 409 | |
410 | +Other Interfaces Exposed to Userspace on the dma-buf FD | |
411 | +------------------------------------------------------ | |
412 | + | |
413 | +- Since kernel 3.12 the dma-buf FD supports the llseek system call, but only | |
414 | + with offset=0 and whence=SEEK_END|SEEK_SET. SEEK_SET is supported to allow | |
415 | + the usual size discover pattern size = SEEK_END(0); SEEK_SET(0). Every other | |
416 | + llseek operation will report -EINVAL. | |
417 | + | |
418 | + If llseek on dma-buf FDs isn't support the kernel will report -ESPIPE for all | |
419 | + cases. Userspace can use this to detect support for discovering the dma-buf | |
420 | + size using llseek. | |
421 | + | |
410 | 422 | Miscellaneous notes |
411 | 423 | ------------------- |
412 | 424 |
drivers/base/dma-buf.c
... | ... | @@ -77,9 +77,36 @@ |
77 | 77 | return dmabuf->ops->mmap(dmabuf, vma); |
78 | 78 | } |
79 | 79 | |
80 | +static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence) | |
81 | +{ | |
82 | + struct dma_buf *dmabuf; | |
83 | + loff_t base; | |
84 | + | |
85 | + if (!is_dma_buf_file(file)) | |
86 | + return -EBADF; | |
87 | + | |
88 | + dmabuf = file->private_data; | |
89 | + | |
90 | + /* only support discovering the end of the buffer, | |
91 | + but also allow SEEK_SET to maintain the idiomatic | |
92 | + SEEK_END(0), SEEK_CUR(0) pattern */ | |
93 | + if (whence == SEEK_END) | |
94 | + base = dmabuf->size; | |
95 | + else if (whence == SEEK_SET) | |
96 | + base = 0; | |
97 | + else | |
98 | + return -EINVAL; | |
99 | + | |
100 | + if (offset != 0) | |
101 | + return -EINVAL; | |
102 | + | |
103 | + return base + offset; | |
104 | +} | |
105 | + | |
80 | 106 | static const struct file_operations dma_buf_fops = { |
81 | 107 | .release = dma_buf_release, |
82 | 108 | .mmap = dma_buf_mmap_internal, |
109 | + .llseek = dma_buf_llseek, | |
83 | 110 | }; |
84 | 111 | |
85 | 112 | /* |
... | ... | @@ -137,6 +164,8 @@ |
137 | 164 | kfree(dmabuf); |
138 | 165 | return ERR_CAST(file); |
139 | 166 | } |
167 | + | |
168 | + file->f_mode |= FMODE_LSEEK; | |
140 | 169 | dmabuf->file = file; |
141 | 170 | |
142 | 171 | mutex_init(&dmabuf->lock); |