Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sumit Semwal <sumit.semwal@linaro.org>

[1]: https://lkml.org/lkml/2012/8/8/163

+17 -3
+9 -1
drivers/dma-buf/dma-buf.c
··· 29 29 #include <linux/anon_inodes.h> 30 30 #include <linux/export.h> 31 31 #include <linux/debugfs.h> 32 + #include <linux/module.h> 32 33 #include <linux/seq_file.h> 33 34 #include <linux/poll.h> 34 35 #include <linux/reservation.h> ··· 73 72 if (dmabuf->resv == (struct reservation_object *)&dmabuf[1]) 74 73 reservation_object_fini(dmabuf->resv); 75 74 75 + module_put(dmabuf->owner); 76 76 kfree(dmabuf); 77 77 return 0; 78 78 } ··· 304 302 return ERR_PTR(-EINVAL); 305 303 } 306 304 305 + if (!try_module_get(exp_info->owner)) 306 + return ERR_PTR(-ENOENT); 307 + 307 308 dmabuf = kzalloc(alloc_size, GFP_KERNEL); 308 - if (dmabuf == NULL) 309 + if (!dmabuf) { 310 + module_put(exp_info->owner); 309 311 return ERR_PTR(-ENOMEM); 312 + } 310 313 311 314 dmabuf->priv = exp_info->priv; 312 315 dmabuf->ops = exp_info->ops; 313 316 dmabuf->size = exp_info->size; 314 317 dmabuf->exp_name = exp_info->exp_name; 318 + dmabuf->owner = exp_info->owner; 315 319 init_waitqueue_head(&dmabuf->poll); 316 320 dmabuf->cb_excl.poll = dmabuf->cb_shared.poll = &dmabuf->poll; 317 321 dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
+8 -2
include/linux/dma-buf.h
··· 115 115 * @attachments: list of dma_buf_attachment that denotes all devices attached. 116 116 * @ops: dma_buf_ops associated with this buffer object. 117 117 * @exp_name: name of the exporter; useful for debugging. 118 + * @owner: pointer to exporter module; used for refcounting when exporter is a 119 + * kernel module. 118 120 * @list_node: node for dma_buf accounting and debugging. 119 121 * @priv: exporter specific private data for this buffer object. 120 122 * @resv: reservation object linked to this dma-buf ··· 131 129 unsigned vmapping_counter; 132 130 void *vmap_ptr; 133 131 const char *exp_name; 132 + struct module *owner; 134 133 struct list_head list_node; 135 134 void *priv; 136 135 struct reservation_object *resv; ··· 167 164 168 165 /** 169 166 * struct dma_buf_export_info - holds information needed to export a dma_buf 170 - * @exp_name: name of the exporting module - useful for debugging. 167 + * @exp_name: name of the exporter - useful for debugging. 168 + * @owner: pointer to exporter module - used for refcounting kernel module 171 169 * @ops: Attach allocator-defined dma buf ops to the new buffer 172 170 * @size: Size of the buffer 173 171 * @flags: mode flags for the file ··· 180 176 */ 181 177 struct dma_buf_export_info { 182 178 const char *exp_name; 179 + struct module *owner; 183 180 const struct dma_buf_ops *ops; 184 181 size_t size; 185 182 int flags; ··· 192 187 * helper macro for exporters; zeros and fills in most common values 193 188 */ 194 189 #define DEFINE_DMA_BUF_EXPORT_INFO(a) \ 195 - struct dma_buf_export_info a = { .exp_name = KBUILD_MODNAME } 190 + struct dma_buf_export_info a = { .exp_name = KBUILD_MODNAME, \ 191 + .owner = THIS_MODULE } 196 192 197 193 /** 198 194 * get_dma_buf - convenience wrapper for get_file.