Solution:
Add a kernel count for dma_buf, and make sure the file
count
of dma_buf.file hold by kernel is 1.
Notes: For this solution, kref couldn't work because kernel ref
maybe added from 0, but kref don't allow it.
drivers/dma-buf/dma-buf.c | 23 +++++++++++++++++++----
include/linux/dma-buf.h | 6 ++++--
2 files changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-
buf.c
index 511fe0d217a0..04ee92aac8b9 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -62,6 +62,7 @@ static void dma_buf_release(struct dentry
*dentry)
if (unlikely(!dmabuf))
return;
@@ -555,6 +556,7 @@ struct dma_buf *dma_buf_export(const struct
dma_buf_export_info *exp_info)
goto err_module;
}
- atomic64_set(&dmabuf->kernel_ref, 1);
dmabuf->priv = exp_info->priv;
dmabuf->ops = exp_info->ops;
dmabuf->size = exp_info->size;
@@ -617,6 +619,9 @@ int dma_buf_fd(struct dma_buf *dmabuf, int
flags)
fd_install(fd, dmabuf->file);
- /* Add file cnt for each new fd */
- get_file(dmabuf->file);
- return fd;
}
EXPORT_SYMBOL_GPL(dma_buf_fd);
@@ -626,12 +631,13 @@ EXPORT_SYMBOL_GPL(dma_buf_fd);
* @fd: [in] fd associated with the struct dma_buf to
be
returned
*
* On success, returns the struct dma_buf associated with an
fd;
uses
- file's refcounting done by fget to increase refcount.
returns
ERR_PTR
- dmabuf's ref refcounting done by kref_get to increase
refcount.
@@ -643,7 +649,12 @@ struct dma_buf *dma_buf_get(int fd)
return ERR_PTR(-EINVAL);
}
- return file->private_data;
- dmabuf = file->private_data;
- /* replace file count increase as ref increase for kernel
user
*/
- get_dma_buf(dmabuf);
- fput(file);
- return dmabuf;
}
EXPORT_SYMBOL_GPL(dma_buf_get);
@@ -662,7 +673,11 @@ void dma_buf_put(struct dma_buf *dmabuf)
if (WARN_ON(!dmabuf || !dmabuf->file))
return;
- if (WARN_ON(!atomic64_read(&dmabuf->kernel_ref)))
return;
- if (!atomic64_dec_return(&dmabuf->kernel_ref))
fput(dmabuf->file);
}
EXPORT_SYMBOL_GPL(dma_buf_put);
diff --git a/include/linux/dma-buf.h b/include/linux/dma-buf.h
index efdc56b9d95f..bc790cb028eb 100644
--- a/include/linux/dma-buf.h
+++ b/include/linux/dma-buf.h
@@ -308,6 +308,7 @@ struct dma_buf_ops {
struct dma_buf {
size_t size;
struct file *file;
- atomic64_t kernel_ref;
struct list_head attachments;
const struct dma_buf_ops *ops;
struct mutex lock;
@@ -436,7 +437,7 @@ struct dma_buf_export_info {
.owner = THIS_MODULE }
/**
- get_dma_buf - convenience wrapper for get_file.
- get_dma_buf - increase a kernel ref of dma-buf
- @dmabuf: [in] pointer to dma_buf
- Increments the reference count on the dma-buf, needed in
case
of drivers
@@ -446,7 +447,8 @@ struct dma_buf_export_info {
*/
static inline void get_dma_buf(struct dma_buf *dmabuf)
{