dma-buf: Add support to set a destructor on a dma-buf

dma-buf destructor support is useful as it allows clients an opportunity
to undo any attributes, such as security attributes, they have applied to
the dma-buf's memory.

The destructor is called when the dma-buf is freed, if the destructor
returns an error the dma-buf's exporter release function is not called in
order to ensure that memory which has not been properly cleaned up isn't
returned to the system.

Change-Id: If2173b23b441157b3638110f02e2ff90ab6ad1aa
Signed-off-by: Liam Mark <lmark@codeaurora.org>
Signed-off-by: Swathi Sridhar <swatsrid@codeaurora.org>
This commit is contained in:
Liam Mark
2019-02-21 11:56:18 -08:00
parent f74ff6264d
commit 3af4db1543
2 changed files with 37 additions and 1 deletions

View File

@@ -69,6 +69,7 @@ static struct dma_buf_list db_list;
static int dma_buf_release(struct inode *inode, struct file *file)
{
struct dma_buf *dmabuf;
int dtor_ret = 0;
if (!is_dma_buf_file(file))
return -EINVAL;
@@ -91,7 +92,14 @@ static int dma_buf_release(struct inode *inode, struct file *file)
list_del(&dmabuf->list_node);
mutex_unlock(&db_list.lock);
dmabuf->ops->release(dmabuf);
if (dmabuf->dtor)
dtor_ret = dmabuf->dtor(dmabuf, dmabuf->dtor_data);
if (!dtor_ret)
dmabuf->ops->release(dmabuf);
else
pr_warn_ratelimited("Leaking dmabuf %s because destructor failed error:%d\n",
dmabuf->name, dtor_ret);
dma_buf_ref_destroy(dmabuf);

View File

@@ -371,6 +371,18 @@ struct dma_buf_ops {
int (*get_flags)(struct dma_buf *dmabuf, unsigned long *flags);
};
/**
* dma_buf_destructor - dma-buf destructor function
* @dmabuf: [in] pointer to dma-buf
* @dtor_data: [in] destructor data associated with this buffer
*
* The dma-buf destructor which is called when the dma-buf is freed.
*
* If the destructor returns an error the dma-buf's exporter release function
* won't be called.
*/
typedef int (*dma_buf_destructor)(struct dma_buf *dmabuf, void *dtor_data);
/**
* struct dma_buf - shared buffer object
* @size: size of the buffer
@@ -428,6 +440,8 @@ struct dma_buf {
} cb_excl, cb_shared;
struct list_head refs;
dma_buf_destructor dtor;
void *dtor_data;
};
/**
@@ -537,4 +551,18 @@ int dma_buf_mmap(struct dma_buf *, struct vm_area_struct *,
void *dma_buf_vmap(struct dma_buf *);
void dma_buf_vunmap(struct dma_buf *, void *vaddr);
int dma_buf_get_flags(struct dma_buf *dma_buf, unsigned long *flags);
/**
* dma_buf_set_destructor - set the dma-buf's destructor
* @dmabuf: [in] pointer to dma-buf
* @dma_buf_destructor [in] the destructor function
* @dtor_data: [in] destructor data associated with this buffer
*/
static inline void dma_buf_set_destructor(struct dma_buf *dmabuf,
dma_buf_destructor dtor,
void *dtor_data)
{
dmabuf->dtor = dtor;
dmabuf->dtor_data = dtor_data;
}
#endif /* __DMA_BUF_H__ */