Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9abdffe2 authored by Sumit Semwal's avatar Sumit Semwal
Browse files

dma-buf: add ref counting for module as exporter



Add reference counting on a kernel module that exports dma-buf and
implements its operations. This prevents the module from being unloaded
while DMABUF file is in use.

The original patch [1] was submitted by Tomasz Stanislawski, but this
is a simpler way to do it.

v3: call module_put() as late as possible, per gregkh's comment.
v2: move owner to struct dma_buf, and use DEFINE_DMA_BUF_EXPORT_INFO
    macro to simplify the change.

Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarSumit Semwal <sumit.semwal@linaro.org>

[1]: https://lkml.org/lkml/2012/8/8/163
parent 5ebe6afa
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/anon_inodes.h>
#include <linux/export.h>
#include <linux/debugfs.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/poll.h>
#include <linux/reservation.h>
@@ -72,6 +73,7 @@ static int dma_buf_release(struct inode *inode, struct file *file)
	if (dmabuf->resv == (struct reservation_object *)&dmabuf[1])
		reservation_object_fini(dmabuf->resv);

	module_put(dmabuf->owner);
	kfree(dmabuf);
	return 0;
}
@@ -302,14 +304,20 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
		return ERR_PTR(-EINVAL);
	}

	if (!try_module_get(exp_info->owner))
		return ERR_PTR(-ENOENT);

	dmabuf = kzalloc(alloc_size, GFP_KERNEL);
	if (dmabuf == NULL)
	if (!dmabuf) {
		module_put(exp_info->owner);
		return ERR_PTR(-ENOMEM);
	}

	dmabuf->priv = exp_info->priv;
	dmabuf->ops = exp_info->ops;
	dmabuf->size = exp_info->size;
	dmabuf->exp_name = exp_info->exp_name;
	dmabuf->owner = exp_info->owner;
	init_waitqueue_head(&dmabuf->poll);
	dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll;
	dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
+8 −2
Original line number Diff line number Diff line
@@ -115,6 +115,8 @@ struct dma_buf_ops {
 * @attachments: list of dma_buf_attachment that denotes all devices attached.
 * @ops: dma_buf_ops associated with this buffer object.
 * @exp_name: name of the exporter; useful for debugging.
 * @owner: pointer to exporter module; used for refcounting when exporter is a
 *         kernel module.
 * @list_node: node for dma_buf accounting and debugging.
 * @priv: exporter specific private data for this buffer object.
 * @resv: reservation object linked to this dma-buf
@@ -129,6 +131,7 @@ struct dma_buf {
	unsigned vmapping_counter;
	void *vmap_ptr;
	const char *exp_name;
	struct module *owner;
	struct list_head list_node;
	void *priv;
	struct reservation_object *resv;
@@ -164,7 +167,8 @@ struct dma_buf_attachment {

/**
 * struct dma_buf_export_info - holds information needed to export a dma_buf
 * @exp_name:	name of the exporting module - useful for debugging.
 * @exp_name:	name of the exporter - useful for debugging.
 * @owner:	pointer to exporter module - used for refcounting kernel module
 * @ops:	Attach allocator-defined dma buf ops to the new buffer
 * @size:	Size of the buffer
 * @flags:	mode flags for the file
@@ -176,6 +180,7 @@ struct dma_buf_attachment {
 */
struct dma_buf_export_info {
	const char *exp_name;
	struct module *owner;
	const struct dma_buf_ops *ops;
	size_t size;
	int flags;
@@ -187,7 +192,8 @@ struct dma_buf_export_info {
 * helper macro for exporters; zeros and fills in most common values
 */
#define DEFINE_DMA_BUF_EXPORT_INFO(a)	\
	struct dma_buf_export_info a = { .exp_name = KBUILD_MODNAME }
	struct dma_buf_export_info a = { .exp_name = KBUILD_MODNAME, \
					 .owner = THIS_MODULE }

/**
 * get_dma_buf - convenience wrapper for get_file.