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>
This commit is contained in:
Christopher James Halse Rogers 2013-09-10 11:36:45 +05:30 committed by Sumit Semwal
parent 9022e24e89
commit 19e8697ba4
2 changed files with 41 additions and 0 deletions

View file

@ -407,6 +407,18 @@ Being able to mmap an export dma-buf buffer object has 2 main use-cases:
interesting ways depending upong the exporter (if userspace starts depending interesting ways depending upong the exporter (if userspace starts depending
upon this implicit synchronization). upon this implicit synchronization).
Other Interfaces Exposed to Userspace on the dma-buf FD
------------------------------------------------------
- Since kernel 3.12 the dma-buf FD supports the llseek system call, but only
with offset=0 and whence=SEEK_END|SEEK_SET. SEEK_SET is supported to allow
the usual size discover pattern size = SEEK_END(0); SEEK_SET(0). Every other
llseek operation will report -EINVAL.
If llseek on dma-buf FDs isn't support the kernel will report -ESPIPE for all
cases. Userspace can use this to detect support for discovering the dma-buf
size using llseek.
Miscellaneous notes Miscellaneous notes
------------------- -------------------

View file

@ -77,9 +77,36 @@ static int dma_buf_mmap_internal(struct file *file, struct vm_area_struct *vma)
return dmabuf->ops->mmap(dmabuf, vma); return dmabuf->ops->mmap(dmabuf, vma);
} }
static loff_t dma_buf_llseek(struct file *file, loff_t offset, int whence)
{
struct dma_buf *dmabuf;
loff_t base;
if (!is_dma_buf_file(file))
return -EBADF;
dmabuf = file->private_data;
/* only support discovering the end of the buffer,
but also allow SEEK_SET to maintain the idiomatic
SEEK_END(0), SEEK_CUR(0) pattern */
if (whence == SEEK_END)
base = dmabuf->size;
else if (whence == SEEK_SET)
base = 0;
else
return -EINVAL;
if (offset != 0)
return -EINVAL;
return base + offset;
}
static const struct file_operations dma_buf_fops = { static const struct file_operations dma_buf_fops = {
.release = dma_buf_release, .release = dma_buf_release,
.mmap = dma_buf_mmap_internal, .mmap = dma_buf_mmap_internal,
.llseek = dma_buf_llseek,
}; };
/* /*
@ -137,6 +164,8 @@ struct dma_buf *dma_buf_export_named(void *priv, const struct dma_buf_ops *ops,
kfree(dmabuf); kfree(dmabuf);
return ERR_CAST(file); return ERR_CAST(file);
} }
file->f_mode |= FMODE_LSEEK;
dmabuf->file = file; dmabuf->file = file;
mutex_init(&dmabuf->lock); mutex_init(&dmabuf->lock);