Commit 19e8697ba45e7bcdb04f2adf6110fbf4882863e5

Authored by Christopher James Halse Rogers
Committed by Sumit Semwal
1 parent 9022e24e89

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);